import sympy as sy
import random # y = (xi)^2 变异重组 利用偏导数的值 寻找最小值import copy
defbianma(upper_bound, lower_bound, geshu, nwei):
p =[]
pey ={}whilelen(p)< geshu:# 生成随意geshu个长度为nwei的不相同二进制编码
t =""for i inrange(nwei):
q =str(random.randint(0,1))
t = t + q
if t notin p:
p.append(t)for i in p:# 将编码分配到函数可行域,得到数学对应值。
ey =(upper_bound - lower_bound)*(int(i,2))/2** nwei + lower_bound
pey[i]= ey
return p, pey
defbianliangbiao(d):
s =[]for i inrange(d):
t ="x"+str(i +1)
s.append(t)return s
defjiema(jieji, upper_bound, lower_bound):
pey ={}for i in jieji:
ey =(upper_bound - lower_bound)*(int(i,2))/2**len(i)+ lower_bound
pey[i]= ey
return pey
defevaluate(eva_ls, shu_ma, d):
r ={}# xi与编码
q ={}# xi与编码数学值
qi ={}# {编码:偏导值}
chuji = copy.copy(eva_ls)
f =0
e =0
bianliang = bianliangbiao(d)# 输入d,生成bianliang['x1','x2'.....'xd']for i in bianliang:
r[i]= random.choice(chuji)# ,r->{'xi':'码'}
chuji.remove(r[i])for i in r:
i = sy.symbols(str(i))# 将xd赋为变量
f = f + i * i
'''
F1
for i in r:
i = sy.symbols(str(i)) # 将xd赋为变量
f = f+i*i # 测试函数
F2
xi_index=bianliang.index(i)
i = sy.symbols(str(i)) # 将xd赋为变量
f = f+(xi_index+1)*i*i # 测试函数
F3
i = sy.symbols(str(i)) # 将xd赋为变量
f = f + abs(i+0.5) **2 # 测试函数
F4
xi_index = bianliang.index(i)
i = sy.symbols(str(i)) # 将xd赋为变量
f = f + (xi_index + 1) * i ** 4 + random.randint(0, 1)'''for i in r:
w = sy.diff(f, i)# 求得偏导 e(xd)
e += w
q[i]= shu_ma[r[i]]# 将xd 与 对应编码的数学值 归入字典{q}
t = w.subs({i: q[i]})# 求各个Xi偏导值t
qi[r[i]]=abs(t)# qi {码:偏导值},ls[码]return eva_ls, qi
defmutation(p, muji):
mo =[]
pp = copy.copy(muji)# 变异,遍历群体 , 遍历个体, 每个个体编码的每个位置都有p的概率变异。
len_muji =len(pp)for i in muji:
q =""for t in i:
pt = random.randint(1,100)if p >= pt:
t =abs(int(t)-1)
q = q +str(t)else:
q = q + t
if q notin mo:# 避免mo 内元素重复,当mo内不含有q时,增加q
mo.append(q)else:continuewhilelen(mo)!= len_muji:# 补齐子集群体个数 ,不够的时候 ,从母群体挑选补到子集。for o in pp:if o notin mo:
mo.append(o)break
muji = copy.copy(mo)return muji
defcrossover(pc, coji):
yuanji = copy.copy(coji)
e = copy.copy(coji)
mi =[]
t =len(yuanji)
d = yuanji
whilelen(d)>2:
pt = random.randint(1,100)
c = random.randint(0,len(d)-1)
cy = d[c]
d.pop(c)
b = random.randint(0,len(d)-1)
by = d[b]
d.pop(b)if pc >= pt:
q = random.randint(0,len(d[0]))
cyy = cy.replace(cy[q:-1], by[q:-1])
byy = by.replace(by[q:-1], cy[q:-1])
mi.append(cyy)
mi.append(byy)else:
mi.append(cy)
mi.append(by)for i in d:
mi.append(i)
mi =list(set(mi))whilelen(mi)!= t:# 避免mi元素重复,转元组再转列表 至mi元素补齐。for o in e:if o notin mi:
mi.append(o)break
coji = copy.copy(mi)return coji
defselect(c1, c2):
c ={}
v_dict ={}
v_ls =[]
c.update(c1)
c.update(c2)
c_order =sorted(c.items(), key=lambda x: x[1], reverse=False)for i inrange(len(c1)):
v_dict[c_order[i][0]]= c_order[i][1]
v_ls.append(c_order[i][0])return v_ls, v_dict
a = bianma(100,-100,40,50)# bianma(上界,下界,编码个数,编码长度)
b = evaluate(a[0], a[1],30)# 输入[评估群体],{群体:数值},维度 ;;; 输出:b[0]->[初码], b[1]->{初码 :偏导值}
poi =sum(b[1].values())# 偏导值的和
i =0while poi >0.01:
i +=1
mu = mutation(5, b[0])# 变异,p 取值为【0~100】
co = crossover(20, mu)# 交叉,p 取值【0~100】
co_number = jiema(co,100,-100)# 解码,输入[码集],输出{码:数学值}
ne = evaluate(co, co_number,30)# 评估,输入[码],{码:数} 维度 输出[码] {码:偏导值} ne[0]->码 ,ne[1]->码与偏导
new = select(b[1], ne[1])# 挑选,b[1] ne[1] 的并集的前一半。输出new ([码],{码:偏导值})
poi =sum(new[1].values())# 新集群偏导值
b = new # b = 新集群print(poi)else:print(poi)# 输出[偏导值]print(i,sum(jiema(b[0],100,-100).values()), jiema(b[0],100,-100).values())# 输出数学值