神奇的量子世界——量子遗传算法(Python&Matlab实现)

1 重要知识点


在专栏我已经系统总结了遗传算法:*智能优化算法(持续更新中…),下面我们先讲解重要知识点,然后用Python和Matlab分别实现。

1.1 遗传算法

遗传算法是一种模拟达尔文生物进化论和遗传变异的智能算法。这种算法具有鲁棒性(用以表征控制系统对特性或参数扰动的不敏感性)较强,实现的步骤规范、简单通用等优点,在人工智能、多目标决策、社会及经济等领域都有大量运用。但一般遗传算法存在一定的局限性:收敛速度慢、迭代的次数多,易过早收敛,容易陷入局部最优解。

1**.2 量子计算**

量子计算为量子力学与信息科学的综合交叉学科。量子计算具有量子力学的并行性,计算速度更快;同时,量子状态多种多样,在进行最优解的搜索时极少陷入局部的极值。

1.3 量子遗传算法

量子遗传算法将量子的态矢量引入遗传算法,利用量子比特的概率幅应用于染色体的编码。一条染色体是多个量子状态的叠加。并使用量子旋转门实现染色体的变异更新。因此量子遗传算法具有迭代次数少,运行速度快,能以较少种群进行遗传变异,搜索范围广,难以陷入局部的极值等优点。

想更深入了解量子遗传算法,可以阅读以下两篇文章:

简单通过一幅图介绍量子遗传算法的特性,黄色个体上有当前最优值,黑色为某其他个体,迭代一次,黑色个体会旋转并向黄色个体靠近,量子遗传算法用旋转门取代了原有的交叉过程。个体自带两个函数值,寻优收敛速度更快,有旋转过程寻找最优,旋转公式中也有惯性公式,即随着迭代次数增加旋转幅度会降低,整体比较遗传算法,更不易陷入局部最优。

操作步骤


2.1 运用量子比特初始化父代染色体

在传统的二进制计算中,用|0》与|1》表示数值,它们即为比特。类似的,在量子计算的过程中,使用与表示量子的两种基本状态,称其为量子比特。量子比特的各种状态,用下式表示:

其中,α与β为一复数,称之为概率幅,且α与β满足

其等效于

量子状态又可表示为:

量子遗传算法将染色体上的基因用量子比特表示,从而增加种群多样性。随机生成m个染色体,每个染色体上的基因用量子比特表示,且初始化为

2.2 在量子遗传算法中,染色体采用量子位的概率幅进行编码,编码方案如下:

Pi为第i个基因,为量子比特的相位,n为染色体数目,k为量子位的位数即解空间的维数,rand是[0,1]范围内的随机数。每个量子位为分上下两行,分别对应两个量子基本态的概率幅,满足归一化条件,因此每个个体包含上下两条文化基因链,每条基因链是优化问题的一个候选解。由此可知,量子遗传算法在种群规模不变的情况下,候选解个数比遗传算法多一倍,增加了解空间的多样性,提高了寻优成功的概率。

2.3 对初始化种群中的每一个个体进行测量。

随机生成一个数x∈[0,1],若

则测量值取1,否则取0。

2.4 对每个测量值进行适应度的评估,以适应度来选择最优个体,进行遗传变异。

2.5 使用量子旋转门进行下一代个体的更新,量子旋转门为逻辑门中一种较为常用的方法,具体表示为:

为量子旋转的角度,则量子比特的更新表示为:

2.6 进行迭代,y=y+1

2.7 达到终止设定条件,输出最佳个体,得到最优解。

3 流程图


4 量子遗传算法——Python实现


4.1 数据

4.2 代码

-- coding: utf-8 --

#导入包==

import numpy as np

from sklearn import svm #SVM是二分类器

from sklearn import cross_validation #交叉验证(Cross Validation)用来验证分类器的性能一种统计分析方法

import random

import math

import matplotlib.pyplot as plt

#=1.导入训练数据==

def load_data(data_file):

‘’’

input: data_file(string):训练数据所在文件

output: data(mat):训练样本的特征

label(mat):训练样本的标签

‘’’

data = []

label = []

f = open(data_file)

for line in f.readlines():

lines = line.strip().split(’ ')

#=提取得出label=

label.append(float(lines[0]))

#提取出特征,并将其放入到矩阵中=

index = 0

tmp = []

for i in range(1, len(lines)):

li = lines[i].strip().split(“:”)

if int(li[0]) - 1 == index:

tmp.append(float(li[1]))

else:

while(int(li[0]) - 1 > index):

tmp.append(0)

index += 1

tmp.append(float(li[1]))

index += 1

while len(tmp) < 13:

tmp.append(0)

data.append(tmp)

f.close()

return np.array(data), np.array(label).T

#=2. QGA算法===================

class QGA(object):

#2.1 类初始化==

‘’'定义QGA类

‘’’

def init(self,population_size,chromosome_num,chromosome_length,max_value,min_value,iter_num,deta):

‘’'初始化类参数

population_size(int):种群数

chromosome_num(int):染色体数,对应需要寻优的参数个数

chromosome_length(int):染色体长度

max_value(float):染色体十进制数值最大值

min_value(float):染色体十进制数值最小值

iter_num(int):迭代次数

deta(float):量子旋转角度

‘’’

self.population_size = population_size

self.chromosome_num = chromosome_num

self.chromosome_length = chromosome_length

self.max_value = max_value

self.min_value = min_value

self.iter_num = iter_num

self.deta = deta

#2.2 种群的量子形式初始化===========

def species_origin_angle(self):

‘’'种群初始化

input:self(object):QGA类

output:population_Angle(list):种群的量子角度列表

population_Angle2(list):空的种群的量子角度列表,用于存储交叉后的量子角度列表

‘’’

population_Angle = []

for i in range(self.chromosome_num):

tmp1 = [] #存储每个染色体所有取值的量子角度

for j in range(self.population_size):

tmp2 = [] #存储量子角度

for m in range(self.chromosome_length):

a = np.pi * 2 * np.random.random()

tmp2.append(a)

tmp1.append(tmp2)

population_Angle.append(tmp1)

return population_Angle

#将初始化的量子角度序列转换为种群的量子系数列表

def population_Q(self,population_Angle):

‘’’

input:self(object):QGA类

population_Angle(list):种群的量子角度列表

output:population_Q(list):种群的量子系数列表

‘’’

population_Q = []

for i in range(len(population_Angle)):

tmp1 = [] #存储每个染色体所有取值的量子系数对

for j in range(len(population_Angle[i])):

tmp2 = [] #存储每个染色体的每个取值的量子对

tmp3 = [] #存储量子对的一半

tmp4 = [] #存储量子对的另一半

for m in range(len(population_Angle[i][j])):

a = population_Angle[i][j][m]

tmp3.append(np.sin(a))

tmp4.append(np.cos(a))

tmp2.append(tmp3)

tmp2.append(tmp4)

tmp1.append(tmp2)

population_Q.append(tmp1)

return population_Q

#2.3计算适应度函数值==========

def translation(self,population_Q):

‘’'将种群的量子列表转换为二进制列表

input:self(object):QGA类

population_Q(list):种群的量子列表

output:population_Binary:种群的二进制列表

‘’’

population_Binary = []

for i in range(len(population_Q)):

tmp1 = [] # 存储每个染色体所有取值的二进制形式

for j in range(len(population_Q[i])):

tmp2 = [] ##存储每个染色体每个取值的二进制形式

for l in range(len(population_Q[i][j][0])):

if np.square(population_Q[i][j][0][l]) > np.random.random():

tmp2.append(1)

else:

tmp2.append(0)

tmp1.append(tmp2)

population_Binary.append(tmp1)

return population_Binary

#=求适应度函数数值列表,本实验采用的适应度函数为RBF_SVM的3_fold交叉验证平均值=

def fitness(self,population_Binary):

‘’’

input:self(object):QGA类

population_Binary(list):种群的二进制列表

output:fitness_value(list):适应度函数值类表

parameters(list):对应寻优参数的列表

‘’’

#=(1)染色体的二进制表现形式转换为十进制并设置在[min_value,max_value]之间=

parameters = [] #存储所有参数的可能取值

for i in range(len(population_Binary)):

tmp1 = [] #存储一个参数的可能取值

for j in range(len(population_Binary[i])):

total = 0.0

for l in range(len(population_Binary[i][j])):

total += population_Binary[i][j][l] * math.pow(2,l) #计算二进制对应的十进制数值

value = (total * (self.max_value - self.min_value)) / math.pow(2,len(population_Binary[i][j])) + self.min_value ##将十进制数值坐落在[min_value,max_value]之间

tmp1.append(value)

parameters.append(tmp1)

#(2)适应度函数为RBF_SVM的3_fold交叉校验平均值=====

fitness_value = []

for l in range(len(parameters[0])):

rbf_svm = svm.SVC(kernel = ‘rbf’, C = parameters[0][l], gamma = parameters[1][l])

cv_scores = cross_validation.cross_val_score(rbf_svm,trainX,trainY,cv =3,scoring = ‘accuracy’)

fitness_value.append(cv_scores.mean())

#=(3)找到最优的适应度函数值和对应的参数二进制表现形式==

best_fitness = 0.0

best_parameter = []

best_parameter_Binary = []

for j in range(len(population_Binary)):

tmp2 = []

best_parameter_Binary.append(tmp2)

best_parameter.append(tmp2)

for i in range(len(population_Binary[0])):

if best_fitness < fitness_value[i]:

best_fitness = fitness_value[i]

for j in range(len(population_Binary)):

best_parameter_Binary[j] = population_Binary[j][i]

best_parameter[j] = parameters[j][i]

return parameters,fitness_value,best_parameter_Binary,best_fitness,best_parameter

#2.4 全干扰交叉===

def crossover(self,population_Angle):

‘’'对种群量子角度列表进行全干扰交叉

input:self(object):QGA类

population_Angle(list):种群的量子角度列表

‘’’

#=初始化一个空列表,全干扰交叉后的量子角度列表

population_Angle_crossover = []

for i in range(self.chromosome_num):

tmp11 = []

for j in range(self.population_size):

tmp21 = []

for m in range(self.chromosome_length):

tmp21.append(0.0)

tmp11.append(tmp21)

population_Angle_crossover.append(tmp11)

for i in range(len(population_Angle)):

for j in range(len(population_Angle[i])):

for m in range(len(population_Angle[i][j])):

ni = (j - m) % len(population_Angle[i])

population_Angle_crossover[i][j][m] = population_Angle[i][ni][m]

return population_Angle_crossover

#2.4 变异======

def mutation(self,population_Angle_crossover,population_Angle,best_parameter_Binary,best_fitness):

‘’'采用量子门变换矩阵进行量子变异

input:self(object):QGA类

population_Angle_crossover(list):全干扰交叉后的量子角度列表

output:population_Angle_mutation(list):变异后的量子角度列表

‘’’

#(1)求出交叉后的适应度函数值列表=====

population_Q_crossover = self.population_Q(population_Angle_crossover) ## 交叉后的种群量子系数列表

population_Binary_crossover = self.translation(population_Q_crossover) ## 交叉后的种群二进制数列表

parameters,fitness_crossover,best_parameter_Binary_crossover,best_fitness_crossover,best_parameter = self.fitness(population_Binary_crossover) ## 交叉后的适应度函数值列表

#(2)初始化每一个量子位的旋转角度==

Rotation_Angle = []

for i in range(len(population_Angle_crossover)):

tmp1 = []

for j in range(len(population_Angle_crossover[i])):

tmp2 = []

for m in range(len(population_Angle_crossover[i][j])):

tmp2.append(0.0)

tmp1.append(tmp2)

Rotation_Angle.append(tmp1)

deta = self.deta

#(3)求每个量子位的旋转角度====

for i in range(self.chromosome_num):

for j in range(self.population_size):

if fitness_crossover[j] <= best_fitness:

for m in range(self.chromosome_length):

s1 = 0

a1 = population_Q_crossover[i][j][0][m]

b1 = population_Q_crossover[i][j][1][m]

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a1 * b1 > 0:

s1 = -1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a1 * b1 < 0:

s1 = 1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a1 * b1 == 0:

s1 = 1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 1 and a1 * b1 < 0:

s1 = -1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 1 and a1 * b1 == 0:

s1 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a1 * b1 > 0:

s1 = -1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a1 * b1 < 0:

s1 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a1 * b1 == 0:

s1 = -1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a1 * b1 > 0:

s1 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a1 * b1 < 0:

s1 = -1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a1 * b1 == 0:

s1 = 1

Rotation_Angle[i][j][m] = deta * s1

else:

for m in range(self.chromosome_length):

s2 = 0

a2 = population_Q_crossover[i][j][0][m]

b2 = population_Q_crossover[i][j][1][m]

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a2 * b2 > 0:

s2 = -1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a2 * b2 < 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 0 and a2 * b2 == 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 1 and a2 * b2 > 0:

s2 = -1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 1 and a2 * b2 < 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 0 and best_parameter_Binary[i][m] == 1 and a2 * b2 == 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a2 * b2 > 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a2 * b2 < 0:

s2 = -1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 0 and a2 * b2 == 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a2 * b2 > 0:

s2 = 1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a2 * b2 < 0:

s2 = -1

if population_Binary_crossover[i][j][m] == 1 and best_parameter_Binary[i][m] == 1 and a2 * b2 == 0:

s2 = 1

Rotation_Angle[i][j][m] = deta * s2

#=(4)根据每个量子位的旋转角度,生成种群新的量子角度列表=========

for i in range(self.chromosome_num):

for j in range(self.population_size):

for m in range(self.chromosome_length):

population_Angle[i][j][m] = population_Angle[i][j][m] + Rotation_Angle[i][j][m]

return population_Angle

#2.5 画出适应度函数值变化图

def plot(self,results):

‘’’

画图

最后

🍅 硬核资料:关注即可领取PPT模板、简历模板、行业经典书籍PDF。
🍅 技术互助:技术群大佬指点迷津,你的问题可能不是问题,求资源在群里喊一声。
🍅 面试题库:由技术群里的小伙伴们共同投稿,热乎的大厂面试真题,持续更新中。
🍅 知识体系:含编程语言、算法、大数据生态圈组件(Mysql、Hive、Spark、Flink)、数据仓库、Python、前端等等。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值