遗传算法案例demo学习

前置学习:Geatpy库学习流程_要努力呦的博客-CSDN博客

目录

1. demo1---简单的连续型决策变量最大化目标的单目标优化问题的求解

2.demo2---带等式约束的连续型决策变量最大化目标的单目标优化问题的求解

3. demo3--带约束的单目标旅行商问题的求解

4.demo4--利用单目标进化算法实现句子匹配

5.demo5---需要混合编码种群来进化的最大化目标的单目标优化问题

7. demo7--- 用进化算法来搜索SVM的参数C和Gamma的最佳值

8. demo8--利用进化算法进行仿k-means聚类(可称之为EA-KMeans算法)

10. demo10--带等式约束的连续型决策变量最大化目标的单目标优化问题.

11. demo11--决策变量的值将取自于一个设定好的变量集合


案例问题均在代码中,不在博客中赘述

1. demo1---简单的连续型决策变量最大化目标的单目标优化问题的求解

# -*- coding: utf-8 -*-
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类
    """Demo.

    max f = x * np.sin(10 * np.pi * x) + 2.0
    s.t.
    -1 <= x <= 2
    """

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 1  # 初始化Dim(决策变量维数)
        varTypes = [0] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [-1]  # 决策变量下界
        ub = [2]  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, x):  # 目标函数
        f = x * np.sin(10 * np.pi * x) + 2.0
        return f


# -*- coding: utf-8 -*-
"""该案例展示了一个简单的连续型决策变量最大化目标的单目标优化问题的求解。问题的定义详见MyProblem.py."""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_SEGA_templet(
        problem,
        ea.Population(Encoding='RI', NIND=40),
        MAXGEN=25,  # 最大进化代数。
        logTras=10,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-6,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=10)  # 进化停滞计数器最大上限值。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    print(res)

2.demo2---带等式约束的连续型决策变量最大化目标的单目标优化问题的求解

# -*- coding: utf-8 -*-
"""该目标函数存在多个欺骗性很强的局部最优点.
max f = 4*x1 + 2*x2 + x3
s.t.
2*x1 + x2 - 1 <= 0
x1 + 2*x3 - 2 <= 0
x1 + x2 + x3 - 1 == 0
0 <= x1,x2 <= 1
0 < x3 < 2
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 3  # 初始化Dim(决策变量维数)
        varTypes = [0] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [0, 0, 0]  # 决策变量下界
        ub = [1, 1, 2]  # 决策变量上界
        lbin = [1, 1, 0]  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1, 1, 0]  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, Vars):  # 目标函数
        x1 = Vars[:, [0]]
        x2 = Vars[:, [1]]
        x3 = Vars[:, [2]]
        f = 4 * x1 + 2 * x2 + x3
        # 采用可行性法则处理约束
        CV = np.hstack(
            [2 * x1 + x2 - 1, x1 + 2 * x3 - 2, np.abs(x1 + x2 + x3 - 1)])
        return f, CV

    def calReferObjV(self):  # 设定目标数参考值(本问题目标函数参考值设定为理论最优值)
        referenceObjV = np.array([[2.5]])
        return referenceObjV

    
# -*- coding: utf-8 -*-
"""该案例展示了一个带等式约束的连续型决策变量最大化目标的单目标优化问题的求解。问题的定义详见MyProblem.py."""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_DE_rand_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=100),
        MAXGEN=500,  # 最大进化代数。
        logTras=100)  # 表示每隔多少代记录一次日志信息,0表示不记录。
    algorithm.mutOper.F = 0.5  # 差分进化中的参数F
    algorithm.recOper.XOVR = 0.7  # 重组概率
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    print(res)    

3. demo3--带约束的单目标旅行商问题的求解

# -*- coding: utf-8 -*-
"""Demo.
    有十座城市:A, B, C, D, E, F, G, H, I, J,坐标如下:
        X      Y
    [[0.4,  0.4439],
     [0.2439,0.1463],
     [0.1707,0.2293],
     [0.2293,0.761],
     [0.5171,0.9414],
     [0.8732,0.6536],
     [0.6878,0.5219],
     [0.8488,0.3609],
     [0.6683,0.2536],
     [0.6195,0.2634]]
    某旅行者从A城市出发,想逛遍所有城市,并且每座城市去且只去一次,最后要返回出发地,
而且需要从G地拿重要文件到D地,另外要从F地把公司的车开到E地,那么他应该如何设计行程方案,才能用
最短的路程来满足他的旅行需求?
    分析:在这个案例中,旅行者从A地出发,把其他城市走遍一次后回到A地,因此我们只需要考虑中间途
径的9个城市的访问顺序即可。这9个城市需要排列组合选出满足约束条件的最优的排列顺序作为最终的路线方案。
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 9  # 初始化Dim(决策变量维数)
        varTypes = [1] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [1] * Dim  # 决策变量下界
        ub = [9] * Dim  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)
        # 新增一个属性存储旅行地坐标
        self.places = np.array([[0.4, 0.4439], [0.2439, 0.1463],
                                [0.1707, 0.2293], [0.2293, 0.761],
                                [0.5171, 0.9414], [0.8732,
                                                   0.6536], [0.6878, 0.5219],
                                [0.8488, 0.3609], [0.6683,
                                                   0.2536], [0.6195, 0.2634]])

    def evalVars(self, x):  # 目标函数
        # 添加从0地出发且最后回到出发地
        X = np.hstack(
            [np.zeros((x.shape[0], 1)), 
             x, 
             np.zeros((x.shape[0], 1))]).astype(int)
        ObjV = []  # 存储所有种群个体对应的总路程
        for i in range(X.shape[0]):
            journey = self.places[X[i], :]  # 按既定顺序到达的地点坐标
            distance = np.sum(np.sqrt(np.sum(np.diff(journey.T)**2,
                                             0)))  # 计算总路程
            ObjV.append(distance)
        f = np.array([ObjV]).T
        # 找到违反约束条件的个体在种群中的索引,保存在向量exIdx中(如:若0、2、4号个体违反约束条件,则编程找出他们来)

        exIdx1 = np.where(np.where(x == 3)[1] - np.where(x == 6)[1] < 0)[0]
        exIdx2 = np.where(np.where(x == 4)[1] - np.where(x == 5)[1] < 0)[0]
        exIdx = np.unique(np.hstack([exIdx1, exIdx2]))
        CV = np.zeros((x.shape[0], 1))
        CV[exIdx] = 1  # 把求得的违反约束程度矩阵赋值给种群pop的CV
        return f, CV

    
    
# -*- coding: utf-8 -*-
"""该案例展示了一个带约束的单目标旅行商问题的求解。问题的定义详见MyProblem.py."""
import matplotlib.pyplot as plt
# from MyProblem import MyProblem  # 导入自定义问题接口
import numpy as np

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_SEGA_templet(
        problem,
        ea.Population(Encoding='P', NIND=50),
        MAXGEN=200,  # 最大进化代数
        logTras=100)  # 表示每隔多少代记录一次日志信息,0表示不记录。
    algorithm.mutOper.Pm = 0.5  # 变异概率
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    # 绘制路线图
    if res['success']:
        print('最短路程为:%s' % res['ObjV'][0][0])
        print('最佳路线为:')
        best_journey = np.hstack([0, res['Vars'][0, :], 0])
        for i in range(len(best_journey)):
            print(int(best_journey[i]), end=' ')
        print()
        # 绘图
        plt.figure()
        plt.plot(problem.places[best_journey.astype(int), 0],
                 problem.places[best_journey.astype(int), 1],
                 c='black')
        plt.plot(problem.places[best_journey.astype(int), 0],
                 problem.places[best_journey.astype(int), 1],
                 'o',
                 c='black')
        for i in range(len(best_journey)):
            plt.text(problem.places[int(best_journey[i]), 0],
                     problem.places[int(best_journey[i]), 1],
                     chr(int(best_journey[i]) + 65),
                     fontsize=20)
        plt.grid(True)
        plt.xlabel('x')
        plt.ylabel('y')
        plt.savefig('roadmap.svg', dpi=600, bbox_inches='tight')
        plt.show()
    else:
        print('没找到可行解。')    

4.demo4--利用单目标进化算法实现句子匹配

# -*- coding: utf-8 -*-
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        # 定义需要匹配的句子
        strs = 'Tom is a little boy, isn\'t he? Yes he is, he is a good and smart child and he is always ready to ' \
               'help others, all in all we all love him very much.'
        self.words = []
        for c in strs:
            self.words.append(ord(c))  # 把字符串转成ASCII码
        M = 1  # 初始化M(目标维数)
        maxormins = [1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = len(self.words)  # 初始化Dim(决策变量维数)
        varTypes = [1] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [32] * Dim  # 决策变量下界
        ub = [122] * Dim  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)
        print('句子长度: ', len(self.words))

    def evalVars(self, Vars):  # 目标函数
        diff = np.sum((Vars - self.words)**2, 1)
        f = np.array([diff]).T
        return f
    
    
# -*- coding: utf-8 -*-
"""该案例展示了一个利用单目标进化算法实现句子匹配的应用实例。问题的定义详见MyProblem.py."""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 快速构建算法
    algorithm = ea.soea_DE_rand_1_L_templet(
        problem,
        ea.Population(Encoding='RI', NIND=50),
        MAXGEN=2000,  # 最大进化代数
        logTras=100)  # 表示每隔多少代记录一次日志信息,0表示不记录。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=False,
                      drawLog=False,
                      saveFlag=True)
    print('最佳目标函数值:%s' % res['ObjV'][0][0])
    print('搜索到的句子为:')
    for num in res['Vars'][0, :]:
        print(chr(int(num)), end='')    

5.demo5---需要混合编码种群来进化的最大化目标的单目标优化问题

# -*- coding: utf-8 -*-
"""该案例展示了一个需要混合编码种群来进化的最大化目标的单目标优化问题.
模型:
max f = sin(2x1) - cos(x2) + 2x3^2 -3x4 + (x5-3)^2 + 7x6
s.t.
-1.5 <= x1,x2 <= 2.5,
1 <= x3,x4,x5,x6 <= 7,且x3,x4,x5,x6为互不相等的整数。
分析:
该问题可以单纯用实整数编码'RI'来实现,但由于有一个”x3,x4,x5,x6互不相等“的约束,
因此把x3,x4,x5,x6用排列编码'P',x1和x2采用实整数编码'RI'来求解会更好。
MyProblem是问题类,本质上是不需要管具体使用什么编码的,因此混合编码的设置在执行脚本main.py中进行而不是在此处。
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 6  # 初始化Dim(决策变量维数)
        varTypes = [0, 0, 1, 1, 1,
                    1]  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [-1.5, -1.5, 1, 1, 1, 1]  # 决策变量下界
        ub = [2.5, 2.5, 7, 7, 7, 7]  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, X):  # 目标函数
        x1 = X[:, [0]]
        x2 = X[:, [1]]
        x3 = X[:, [2]]
        x4 = X[:, [3]]
        x5 = X[:, [4]]
        x6 = X[:, [5]]
        f = np.sin(
            2 * x1) - np.cos(x2) + 2 * x3**2 - 3 * x4 + (x5 - 3)**2 + 7 * x6
        return f
    
# -*- coding: utf-8 -*-
"""该案例展示了一个需要混合编码种群来进化的最大化目标的单目标优化问题.
问题的定义详见MyProblem.py。
分析:
该问题可以单纯用实整数编码'RI'来实现,但由于有一个”x3,x4,x5,x6互不相等“的约束,
因此把x3,x4,x5,x6用排列编码'P',x1和x2采用实整数编码'RI'来求解会更好。
MyProblem是问题类,本质上是不需要管具体使用什么编码的,因此混合编码的设置在执行脚本main.py中进行而不是在此处。
"""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 快速构建算法
    algorithm = ea.soea_psy_EGA_templet(
        problem,
        ea.PsyPopulation(Encodings=['RI', 'P'],
                         NIND=40,
                         EncoIdxs=[[0, 1], [2, 3, 4, 5]]),
        MAXGEN=25,  # 最大进化代数
        logTras=100)  # 表示每隔多少代记录一次日志信息,0表示不记录。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    print(res)    

6.demo6--利用进化算法+多进程/多线程来搜索SVM中的两个参数:C和Gamma的最佳值

# -*- coding: utf-8 -*-
"""Demo.
本问题需要用到一个外部数据集,存放在同目录下的iris.data中,
并且把iris.data按3:2划分为训练集数据iris_train.data和测试集数据iris_test.data。
有关该数据集的详细描述详见http://archive.ics.uci.edu/ml/datasets/Iris
数据集下载:https://github.com/geatpy-dev/geatpy/tree/master/demo/soea_demo/soea_demo6
"""
from multiprocessing import Pool as ProcessPool
import multiprocessing as mp
from multiprocessing.dummy import Pool as ThreadPool

import numpy as np
from sklearn import preprocessing
from sklearn import svm
from sklearn.model_selection import cross_val_score

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self, PoolType):  # PoolType是取值为'Process'或'Thread'的字符串
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 2  # 初始化Dim(决策变量维数)
        varTypes = [0, 0]  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [2**(-8)] * Dim  # 决策变量下界
        ub = [2**8] * Dim  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)
        # 目标函数计算中用到的一些数据
        fp = open('iris_train.data')
        datas = []
        data_targets = []
        for line in fp.readlines():
            line_data = line.strip('\n').split(',')
            data = []
            for i in line_data[0:4]:
                data.append(float(i))
            datas.append(data)
            data_targets.append(line_data[4])
        fp.close()
        self.data = preprocessing.scale(np.array(datas))  # 训练集的特征数据(归一化)
        self.dataTarget = np.array(data_targets)
        # 设置用多线程还是多进程
        self.PoolType = PoolType
        if self.PoolType == 'Thread':
            self.pool = ThreadPool(2)  # 设置池的大小
        elif self.PoolType == 'Process':
            num_cores = int(mp.cpu_count())  # 获得计算机的核心数
            self.pool = ProcessPool(num_cores)  # 设置池的大小

    def evalVars(self, Vars):  # 目标函数,采用多线程加速计算
        N = Vars.shape[0]
        args = list(
            zip(list(range(N)), [Vars] * N, [self.data] * N,
                [self.dataTarget] * N
               )
                )
#         print(args)
#         print(N)
        if self.PoolType == 'Thread':
            f = np.array(list(self.pool.map(subAimFunc, args)))
        elif self.PoolType == 'Process':
            result = self.pool.map_async(subAimFunc, args)
            result.wait()
            f = np.array(result.get())
        return f

    def test(self, C, G):  # 代入优化后的C、Gamma对测试集进行检验
        # 读取测试集数据
        fp = open('iris_test.data')
        datas = []
        data_targets = []
        for line in fp.readlines():
            line_data = line.strip('\n').split(',')
            data = []
            for i in line_data[0:4]:
                data.append(float(i))
            datas.append(data)
            data_targets.append(line_data[4])
        fp.close()
        data_test = preprocessing.scale(np.array(datas))  # 测试集的特征数据(归一化)
        dataTarget_test = np.array(data_targets)  # 测试集的标签数据
        svc = svm.SVC(C=C, kernel='rbf',
                      gamma=G).fit(self.data,
                                   self.dataTarget)  # 创建分类器对象并用训练集的数据拟合分类器模型
        dataTarget_predict = svc.predict(data_test)  # 采用训练好的分类器对象对测试集数据进行预测
        print("测试集数据分类正确率 = %s%%" %
              (len(np.where(dataTarget_predict == dataTarget_test)[0])
               / len(dataTarget_test) * 100))


def subAimFunc(args):
    i = args[0] # 序号
    Vars = args[1]# 参数变量
    data = args[2]# 数据
    dataTarget = args[3]# 数据标记
    C = Vars[i, 0] # 取出哪一个参数
    G = Vars[i, 1] # 取出参数
    svc = svm.SVC(C=C, kernel='rbf',
                  gamma=G).fit(data, dataTarget)  # 创建分类器对象并用训练集的数据拟合分类器模型
    scores = cross_val_score(svc, data, dataTarget, cv=30)  # 计算交叉验证的得分
    ObjV_i = [scores.mean()]  # 把交叉验证的平均得分作为目标函数值
    return ObjV_i

# -*- coding: utf-8 -*-
"""该案例展示了如何利用进化算法+多进程/多线程来搜索SVM中的两个参数:C和Gamma的最佳值.
问题的定义详见MyProblem.py。
在执行脚本main.py中设置PoolType字符串来控制采用的是多进程还是多线程。
注意:使用多进程时,程序必须以“if __name__ == '__main__':”作为入口,
      这个是multiprocessing的多进程模块的硬性要求。
"""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem(
        PoolType='Thread')  # 设置采用多线程,若修改为: PoolType = 'Process',则表示用多进程
    # 构建算法
    algorithm = ea.soea_DE_rand_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=50),
        MAXGEN=30,  # 最大进化代数。
        logTras=100,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-6,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=10)  # 进化停滞计数器最大上限值。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    # 检验结果
    if res['success']:
        problem.test(C=res['Vars'][0, 0], G=res['Vars'][0, 1])

7. demo7--- 用进化算法来搜索SVM的参数C和Gamma的最佳值

# -*- coding: utf-8 -*-
"""本案例和soea_demo6类似,同样是用进化算法来搜索SVM的参数C和Gamma的最佳值.
不同的是,本案例选用更庞大的数据集,使得每次训练SVM模型时耗时更高,从而更适合采用分布式加速计算。
该数据集存放在同目录下的Data_User_Modeling_Dataset_Hamdi Tolga KAHRAMAN.xls中,
有关该数据集的详细描述详见http://archive.ics.uci.edu/ml/datasets/User+Knowledge+Modeling
"""
import numpy as np
from scoop import futures
from sklearn import preprocessing
from sklearn import svm
from sklearn.model_selection import cross_val_score
import xlrd

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 2  # 初始化Dim(决策变量维数)
        varTypes = [0, 0]  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [2**(-8), 2**(-8)]  # 决策变量下界
        ub = [2**8, 1]  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)
        # 目标函数计算中用到的一些数据
        workbook = xlrd.open_workbook(
            "Data_User_Modeling_Dataset_Hamdi Tolga KAHRAMAN.xls"
        )  # 打开文件,获取excel文件的workbook(工作簿)对象
        worksheet = workbook.sheet_by_name(
            "Training_Data")  # 通过sheet名获得sheet对象
        self.data = np.vstack([
            worksheet.col_values(0)[1:],
            worksheet.col_values(1)[1:],
            worksheet.col_values(2)[1:],
            worksheet.col_values(3)[1:],
            worksheet.col_values(4)[1:]
        ]).T  # 获取特征数据
        self.data = preprocessing.scale(self.data)  # 归一化特征数据
        self.dataTarget = worksheet.col_values(5)[1:]  # 获取标签数据

    def evalVars(self, Vars):  # 目标函数
        N = Vars.shape[0]
        print(N)
        args = list(
            zip(list(range(N)), [Vars] * N, [self.data] * N,
                [self.dataTarget] * N))
        ObjV = np.array(list(futures.map(
            subEvalVars, args)))  # 调用SCOOP的map函数进行分布式计算,并构造目标函数值矩阵ObjV
        return ObjV

    def test(self, C, G):  # 代入优化后的C、Gamma对测试集进行检验
        # 读取测试集数据
        workbook = xlrd.open_workbook(
            "Data_User_Modeling_Dataset_Hamdi Tolga KAHRAMAN.xls"
        )  # 打开文件,获取excel文件的workbook(工作簿)对象
        worksheet = workbook.sheet_by_name("Test_Data")  # 通过sheet名获得sheet对象
        data_test = np.vstack([
            worksheet.col_values(0)[1:],
            worksheet.col_values(1)[1:],
            worksheet.col_values(2)[1:],
            worksheet.col_values(3)[1:],
            worksheet.col_values(4)[1:]
        ]).T  # 获取特征数据
        data_test = preprocessing.scale(data_test)  # 归一化特征数据
        dataTarget_test = worksheet.col_values(5)[1:]  # 获取标签数据
        svc = svm.SVC(C=C, kernel='rbf',
                      gamma=G).fit(self.data,
                                   self.dataTarget)  # 创建分类器对象并用训练集的数据拟合分类器模型
        dataTarget_predict = svc.predict(data_test)  # 采用训练好的分类器对象对测试集数据进行预测
        print("测试集数据分类正确率 = %s%%" %
              (len(np.where(dataTarget_predict == dataTarget_test)[0])
               / len(dataTarget_test) * 100))


def subEvalVars(args):  # 单独计算单个个体的目标函数值
    i = args[0]
    Vars = args[1]
    data = args[2]
    dataTarget = args[3]
    C = Vars[i, 0]
    G = Vars[i, 1]
    svc = svm.SVC(C=C, kernel='rbf',
                  gamma=G).fit(data, dataTarget)  # 创建分类器对象并用训练集的数据拟合分类器模型
    scores = cross_val_score(svc, data, dataTarget, cv=20)  # 计算交叉验证的得分
    ObjV_i = [scores.mean()]  # 把交叉验证的平均得分作为目标函数值
    return ObjV_i


# -*- coding: utf-8 -*-
"""本案例和soea_demo6类似,同样是用进化算法来搜索SVM的参数C和Gamma的最佳值.
不同的是这里采用SCOOP来
在执行本案例前,需要确保正确安装sklearn以及SCOOP,以保证SVM和SCOOP部分的代码能够正常执行。
SCOOP安装方法:控制台执行命令pip install scoop
分布式加速计算注意事项:
1.当目标函数的计算十分耗时,比如计算单个个体的目标函数值就需要很长时间时,
  适合采用分布式计算,否则贸然采用分布式计算反而会大大降低性能。
2.分布式执行方法:python -m scoop -n 10 main.py 其中10表示把计算任务分发给10个workers。
  非分布式执行方法:python main.py
"""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_DE_rand_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=20),
        MAXGEN=30,  # 最大进化代数。
        logTras=1,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-6,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=10)  # 进化停滞计数器最大上限值。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    # 检验结果
    problem.test(C=res['Vars'][0, 0], G=res['Vars'][0, 1])

8. demo8--利用进化算法进行仿k-means聚类(可称之为EA-KMeans算法)

# -*- coding: utf-8 -*-
"""该案例展示了如何利用进化算法进行仿k-means聚类(可称之为EA-KMeans算法).
问题的定义详见MyProblem.py。
本案例采用与k-means类似的聚类方法,采用展开的聚类中心点坐标作为染色体的编码,基本流程大致如下:
1) 初始化种群染色体。
2) 迭代进化(循环第3步至第6步),直到满足终止条件。
3) 重组变异,然后根据得到的新染色体计算出对应的聚类中心点。
4) 计算各数据点到聚类中心点的欧式距离。
5) 把与各中心点关联的数据点的坐标平均值作为新的中心点,并以此更新种群的染色体。
6) 把各中心点到与其关联的数据点之间的距离之和作为待优化的目标函数值。
注意:导入的数据是以列为特征的,即每一列代表一个特征(如第一列代表x,第二列代表y......)。
"""
import matplotlib.pyplot as plt
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        # 目标函数计算中用到的一些数据
        self.datas = np.loadtxt('data.csv', delimiter=',')  # 读取数据
        self.k = 6  # 分类数目
        # 问题类设置
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = self.datas.shape[1] * self.k  # 初始化Dim
        varTypes = [0] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = list(np.min(self.datas, 0)) * self.k  # 决策变量下界
        ub = list(np.max(self.datas, 0)) * self.k  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def aimFunc(self, pop):  # 目标函数
        centers = pop.Phen.reshape(int(pop.sizes * self.k),
                                   int(pop.Phen.shape[1] / self.k))  # 得到聚类中心
#         print(centers)
        dis = ea.cdist(centers, self.datas, 'euclidean')  # 计算距离
        dis_split = dis.reshape(
            pop.sizes, self.k,
            self.datas.shape[0])  # 分割距离矩阵,把各个聚类中心到各个点之间的距离的数据分开
        labels = np.argmin(dis_split, 1)[0]  # 得到聚类标签值
        uni_labels = np.unique(labels)
        for i in range(len(uni_labels)):
            centers[uni_labels[i], :] = np.mean(
                self.datas[np.where(labels == uni_labels[i])[0], :], 0)
        # 直接修改染色体为已知的更优值,加快收敛
        pop.Chrom = centers.reshape(pop.sizes, self.k * centers.shape[1])
        pop.Phen = pop.decoding()  # 染色体解码(要同步修改Phen,否则后面会导致数据不一致)
        dis = ea.cdist(centers, self.datas, 'euclidean')
        dis_split = dis.reshape(pop.sizes, self.k, self.datas.shape[0])
        pop.ObjV = np.sum(np.min(dis_split, 1), 1, keepdims=True)  # 计算个体的目标函数值

    def draw(self, centers):  # 绘制聚类效果图
        dis = ea.cdist(centers, self.datas, 'euclidean')
        dis_split = dis.reshape(1, self.k, self.datas.shape[0])
        labels = np.argmin(dis_split, 1)[0]
        colors = ['r', 'g', 'b', 'y','violet','tan']
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        for i in range(self.k):
            idx = np.where(labels == i)[0]  # 找到同一类的点的下标
            datas = self.datas[idx, :]
            ax.scatter(datas[:, 0], datas[:, 1], datas[:, 2], c=colors[i])
            
# -*- coding: utf-8 -*-

# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_DE_rand_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=2),
        MAXGEN=20,  # 最大进化代数。
        logTras=1,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-4,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=10)  # 进化停滞计数器最大上限值。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    # 检验结果
    if res['success']:
        print('最优的聚类中心为:')
        Vars = res['Vars'][0, :]
        centers = Vars.reshape(problem.k,
                               int(len(Vars) / problem.k))  # 得到最优的聚类中心
        print(centers)
        """=================================检验结果==============================="""
        problem.draw(centers)

9.demo9--利用多种群来进行单目标优化.

# -*- coding: utf-8 -*-
"""Demo.
max f = x * np.sin(10 * np.pi * x) + 2.0
s.t.
-1 <= x <= 2
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 1  # 初始化Dim(决策变量维数)
        varTypes = [0] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [-1]  # 决策变量下界
        ub = [2]  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, x):  # 目标函数
        f = x * np.sin(10 * np.pi * x) + 2.0
        return f
    
    
# -*- coding: utf-8 -*-
"""该案例是soea_demo1的拓展,展示了如何利用多种群来进行单目标优化.
问题的定义详见MyProblem.py。
在执行脚本main.py中,通过调用带"multi"字样的进化算法类来进行多种群进化优化。
"""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 种群设置
    Encoding = 'RI'  # 编码方式
    NINDs = [5, 10, 15, 20]  # 种群规模
    population = []  # 创建种群列表
    for i in range(len(NINDs)):
        Field = ea.crtfld(Encoding,
                          problem.varTypes,
                          problem.ranges,
                          problem.borders)  # 创建区域描述器。
        population.append(ea.Population(
            Encoding, Field, NINDs[i]))  # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)。
    # 构建算法
    algorithm = ea.soea_multi_SEGA_templet(
        problem,
        population,
        MAXGEN=30,  # 最大进化代数。
        logTras=1,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-6,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=5)  # 进化停滞计数器最大上限值。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=False)
    print(res)    

10. demo10--带等式约束的连续型决策变量最大化目标的单目标优化问题.

# -*- coding: utf-8 -*-
"""这是一个带等式约束的连续型决策变量最大化目标的单目标优化问题,该函数存在多个欺骗性很强的局部最优点.
max f = 4*x1 + 2*x2 + x3
s.t.
2*x1 + x2 - 1 <= 0
x1 + 2*x3 - 2 <= 0
x1 + x2 + x3 - 1 == 0
0 <= x1,x2 <= 1
0 < x3 < 2
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [-1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        Dim = 3  # 初始化Dim(决策变量维数)
        varTypes = [0] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [0, 0, 0]  # 决策变量下界
        ub = [1, 1, 2]  # 决策变量上界
        lbin = [1, 1, 0]  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1, 1, 0]  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, Vars):  # 目标函数
        x1 = Vars[:, [0]]
        x2 = Vars[:, [1]]
        x3 = Vars[:, [2]]
        f = 4 * x1 + 2 * x2 + x3
        # 采用可行性法则处理约束
        CV = np.hstack(
            [2 * x1 + x2 - 1, x1 + 2 * x3 - 2, np.abs(x1 + x2 + x3 - 1)])
        return f, CV

    def calReferObjV(self):  # 设定目标数参考值(本问题目标函数参考值设定为理论最优值)
        referenceObjV = np.array([[2.5]])
        return referenceObjV
    
    
    
    
# -*- coding: utf-8 -*-
"""该案例展示了一个带等式约束的连续型决策变量最大化目标的单目标优化问题.
问题的定义详见MyProblem.py。与soea_demo2不同之处是采用先验知识帮助进化优化。
"""
# from MyProblem import MyProblem  # 导入自定义问题接口
import numpy as np

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()  # 生成问题对象
    # 快速构建算法
    algorithm = ea.soea_DE_currentToBest_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=20),
        MAXGEN=400,  # 最大进化代数。
        logTras=0)  # 表示每隔多少代记录一次日志信息,0表示不记录。
    algorithm.mutOper.F = 0.7  # 差分进化中的参数F。
    algorithm.recOper.XOVR = 0.7  # 交叉概率。
    # 先验知识
    prophetVars = np.array([[0.4, 0.2, 0.4]])  # 假设已知[0.4, 0.2, 0.4]为一组比较优秀的变量。
    # 求解
    res = ea.optimize(algorithm,
                      prophet=prophetVars,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=True,
                      saveFlag=True)
    print(res)

11. demo11--决策变量的值将取自于一个设定好的变量集合

# -*- coding: utf-8 -*-
"""Demo.
max f = (-1+x1+((6-x2)*x2-2)*x2)**2+(-1+x1+((x2+2)*x2-10)*x2)**2
s.t.  x∈{1.1, 1, 0, 3, 5.5, 7.2, 9}
"""
import numpy as np

import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name(函数名称,可以随意设置)
        M = 1  # 初始化M(目标维数)
        maxormins = [1]  # 初始化maxormins(目标最小最大化标记列表,1:最小化该目标;-1:最大化该目标)
        self.var_set = np.array([1.1, 1, 0, 3, 5.5, 7.2,
                                 9])  # 设定一个集合,要求决策变量的值取自于该集合
        Dim = 2  # 初始化Dim(决策变量维数)
        varTypes = [1] * Dim  # 初始化varTypes(决策变量的类型,元素为0表示对应的变量是连续的;1表示是离散的)
        lb = [0, 0]  # 决策变量下界
        ub = [6, 6]  # 决策变量上界
        lbin = [1] * Dim  # 决策变量下边界(0表示不包含该变量的下边界,1表示包含)
        ubin = [1] * Dim  # 决策变量上边界(0表示不包含该变量的上边界,1表示包含)
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self,
                            name,
                            M,
                            maxormins,
                            Dim,
                            varTypes,
                            lb,
                            ub,
                            lbin,
                            ubin)

    def evalVars(self, Vars):  # 目标函数
        Vars = Vars.astype(np.int32)  # 强制类型转换确保元素是整数
        x1 = self.var_set[Vars[:, [0]]]  # 得到所有的x1组成的列向量
        x2 = self.var_set[Vars[:, [1]]]  # 得到所有的x2组成的列向量
        f = (-1 + x1 +
             ((6 - x2) * x2 - 2) * x2)**2 + (-1 + x1 +
                                             ((x2 + 2) * x2 - 10) * x2)**2
        return f
    
    
# -*- coding: utf-8 -*-
"""该案例展示2个决策变量的单目标优化,决策变量的值将取自于一个设定好的变量集合。问题的定义详见MyProblem.py."""
# from MyProblem import MyProblem  # 导入自定义问题接口

import geatpy as ea  # import geatpy

if __name__ == '__main__':
    # 实例化问题对象
    problem = MyProblem()
    # 构建算法
    algorithm = ea.soea_DE_rand_1_bin_templet(
        problem,
        ea.Population(Encoding='RI', NIND=20),
        MAXGEN=25,  # 最大进化代数。
        logTras=1,  # 表示每隔多少代记录一次日志信息,0表示不记录。
        trappedValue=1e-6,  # 单目标优化陷入停滞的判断阈值。
        maxTrappedCount=10)  # 进化停滞计数器最大上限值。
    algorithm.mutOper.F = 0.5  # 差分进化中的参数F。
    algorithm.recOper.XOVR = 0.2  # 差分进化中的参数Cr。
    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=False,
                      saveFlag=True)
    print(res)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++遗传算法是一种模拟自然选择和遗传机制的优化技术,常用于解决复杂问题中的全局优化问题。以下是一个简单的C++遗传算法程序的demo概述: ```cpp // 假设我们正在解决一个简单的函数优化问题,如找到函数f(x) = x^2 + y^2的最小值 #include <iostream> #include <vector> #include <random> #include <algorithm> class Individual { public: std::vector<double> genes; double fitness; // 构造函数,初始化基因(可能是一个随机数列) Individual(int size) : genes(size, 0.0), fitness(0.0) {} // 计算个体的适应度(这里用平方和作为例子) void calculateFitness() { fitness = 0.0; for (double gene : genes) { fitness += gene * gene; } } }; // 遗传操作(例如选择、交叉和变异) std::vector<Individual> geneticOperators(std::vector<Individual>& population) { // 选择操作(选择适应度较高的个体) // ... // 交叉操作(将两个个体的部分基因交换) // ... // 变异操作(随机改变某个基因) // ... return population; } int main() { // 初始化种群 int populationSize = 100; std::vector<Individual> population(populationSize); for (int i = 0; i < populationSize; ++i) { population[i].calculateFitness(); } // 进行迭代直到达到某个停止条件(如最大迭代次数或适应度阈值) while (/* stop condition */) { population = geneticOperators(population); // 更新适应度并可能进行排序 std::sort(population.begin(), population.end(), [](const Individual& a, const Individual& b) { return a.fitness < b.fitness; }); // 打印当前最优解 std::cout << "Generation " << iterationCount << ", Best individual: Fitness = " << population.fitness << std::endl; } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值