热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python对函数优化_python寻找优化使成本函数最小的最优解的方法

今天来学习变量优化问题。寻找使成本函数最小的题解。适用于题解相互独立的情况,设计随机优化算法、爬山法、模拟退火算法、遗传算法。优化问题的的精髓是:1、将

今天来学习变量优化问题。寻找使成本函数最小的题解。适用于题解相互独立的情况,设计随机优化算法、爬山法、模拟退火算法、遗传算法。

优化问题的的精髓是:1、将题解转化为数字序列化,可以写出题解范围。2、成本函数能返回值

问题场景:

所有乘客从不同的地方飞到同一个目的地,服务人员等待所有人到来以后将人一次性接走。

离开时,服务人员将人一次性带到飞机场,所有乘客等待自己的航班离开。

要解决的问题:

如何设置乘客的到来和离开航班,以及接送机的时间,使得总代价最小。

将题解设为数字序列。

数字表示某人乘坐的第几次航班,从0开始,例如[1,4,3,2,7,3,6,3,2]表示第1个人做第2个航班来,第5个航班走,第2个人做第4个航班来,第3个航班走

题解相互独立:组团旅游问题,举办会议的人员接送问题

首先从网上采集航班信息,存储到schedule.txt文件中。共6个起始点,和共同的目的地。每个起止点之间包含多道航班。在txt中记录的就是起飞点、着陆点、起飞时间、着陆时间、价钱。

des_place,src6_place,6:19,8:13,239

src6_place,des_place,6:11,8:31,249

des_place,src6_place,8:04,10:59,136

src6_place,des_place,7:39,10:24,219

des_place,src6_place,9:31,11:43,210

src6_place,des_place,9:15,12:03,99

des_place,src6_place,11:07,13:24,171

src6_place,des_place,11:08,13:07,175

des_place,src6_place,12:31,14:02,234

src6_place,des_place,12:18,14:56,172

des_place,src6_place,14:05,15:47,226

src6_place,des_place,13:37,15:08,250

des_place,src6_place,15:07,17:21,129

src6_place,des_place,15:03,16:42,135

des_place,src6_place,16:35,18:56,144

src6_place,des_place,16:51,19:09,147

des_place,src6_place,18:25,20:34,205

src6_place,des_place,18:12,20:17,242

des_place,src6_place,20:05,21:44,172

src6_place,des_place,20:05,22:06,261

des_place,src5_place,6:03,8:43,219

src5_place,des_place,6:05,8:32,174

des_place,src5_place,7:50,10:08,164

src5_place,des_place,8:25,10:34,157

des_place,src5_place,9:11,10:42,172

src5_place,des_place,9:42,11:32,169

des_place,src5_place,10:33,13:11,132

src5_place,des_place,11:01,12:39,260

des_place,src5_place,12:08,14:47,231

src5_place,des_place,12:44,14:17,134

des_place,src5_place,14:19,17:09,190

src5_place,des_place,14:22,16:32,126

des_place,src5_place,15:04,17:23,189

src5_place,des_place,15:58,18:40,173

des_place,src5_place,17:06,20:00,95

src5_place,des_place,16:43,19:00,246

des_place,src5_place,18:33,20:22,143

src5_place,des_place,18:48,21:45,246

des_place,src5_place,19:32,21:25,160

src5_place,des_place,19:50,22:24,269

des_place,src4_place,6:33,9:14,172

src4_place,des_place,6:25,9:30,335

des_place,src4_place,8:23,11:07,143

src4_place,des_place,7:34,9:40,324

des_place,src4_place,9:25,12:46,295

src4_place,des_place,9:15,12:29,225

des_place,src4_place,11:08,14:38,262

src4_place,des_place,11:28,14:40,248

des_place,src4_place,12:37,15:05,170

src4_place,des_place,12:05,15:30,330

des_place,src4_place,14:08,16:09,232

src4_place,des_place,14:01,17:24,338

des_place,src4_place,15:23,18:49,150

src4_place,des_place,15:34,18:11,326

des_place,src4_place,16:50,19:26,304

src4_place,des_place,17:07,20:04,291

des_place,src4_place,18:07,21:30,355

src4_place,des_place,18:23,21:35,134

des_place,src4_place,20:27,23:42,169

src4_place,des_place,19:53,22:21,173

des_place,src1_place,6:39,8:09,86

src1_place,des_place,6:17,8:26,89

des_place,src1_place,8:23,10:28,149

src1_place,des_place,8:04,10:11,95

des_place,src1_place,9:58,11:18,130

src1_place,des_place,9:45,11:50,172

des_place,src1_place,10:33,12:03,74

src1_place,des_place,11:16,13:29,83

des_place,src1_place,12:08,14:05,142

src1_place,des_place,12:34,15:02,109

des_place,src1_place,13:39,15:30,74

src1_place,des_place,13:40,15:37,138

des_place,src1_place,15:25,16:58,62

src1_place,des_place,15:27,17:18,151

des_place,src1_place,17:03,18:03,103

src1_place,des_place,17:11,18:30,108

des_place,src1_place,18:24,20:49,124

src1_place,des_place,18:34,19:36,136

des_place,src1_place,19:58,21:23,142

src1_place,des_place,20:17,22:22,102

des_place,src2_place,6:09,9:49,414

src2_place,des_place,6:12,10:22,230

des_place,src2_place,7:57,11:15,347

src2_place,des_place,7:53,11:37,433

des_place,src2_place,9:49,13:51,229

src2_place,des_place,9:08,12:12,364

des_place,src2_place,10:51,14:16,256

src2_place,des_place,10:30,14:57,290

des_place,src2_place,12:20,16:34,500

src2_place,des_place,12:19,15:25,342

des_place,src2_place,14:20,17:32,332

src2_place,des_place,13:54,18:02,294

des_place,src2_place,15:49,20:10,497

src2_place,des_place,15:44,18:55,382

des_place,src2_place,17:14,20:59,277

src2_place,des_place,16:52,20:48,448

des_place,src2_place,18:44,22:42,351

src2_place,des_place,18:26,21:29,464

des_place,src2_place,19:57,23:15,512

src2_place,des_place,20:07,23:27,473

des_place,src3_place,6:58,9:01,238

src3_place,des_place,6:08,8:06,224

des_place,src3_place,8:19,11:16,122

src3_place,des_place,8:27,10:45,139

des_place,src3_place,9:58,12:56,249

src3_place,des_place,9:15,12:14,247

des_place,src3_place,10:32,13:16,139

src3_place,des_place,10:53,13:36,189

des_place,src3_place,12:01,13:41,267

src3_place,des_place,12:08,14:59,149

des_place,src3_place,13:37,15:33,142

src3_place,des_place,13:40,15:38,137

des_place,src3_place,15:50,18:45,243

src3_place,des_place,15:23,17:25,232

des_place,src3_place,16:33,18:15,253

src3_place,des_place,17:08,19:08,262

des_place,src3_place,18:17,21:04,259

src3_place,des_place,18:35,20:28,204

des_place,src3_place,19:46,21:45,214

src3_place,des_place,20:30,23:11,114

构建6名游客的航班信息

# 人员的名称和来源地信息

peoplelist = [('name1','src1_place'),

('name2','src2_place'),

('name3','src3_place'),

('name4','src4_place'),

('name5','src5_place'),

('name6','src6_place')]

# 目的机场

destination='des_place'

flights={} #加载所有航班信息。

# 查询所有的航班信息

for line in open('schedule.txt'):

origin,dest,depart,arrive,price=line.strip().split(',') #源地址、目的地址、离开时间、到达时间、价格

flights.setdefault((origin,dest),[]) #航班信息已起止点为键值,每个起止点有多个航班

# 将航班信息添加到航班列表中

flights[(origin,dest)].append((depart,arrive,int(price))) #按时间顺序扩展每次航班

为了实现优化,我们将题解转变为数字序列,为了理解更加方便的理解数字序列代表的含义。实现一个函数,接受数字序列,打印输出航班信息。

# 将数字序列转换为航班,打印输出。输入为数字序列

def printschedule(r):

for d in range(int(len(r)/2)):

name=peoplelist[d][0] #人员名称

origin=peoplelist[d][1] #人员来源地

out=flights[(origin,destination)][int(r[2*d])] #往程航班

ret=flights[(destination,origin)][int(r[2*d+1])] #返程航班

print('%10s %10s %5s-%5s $%3s %5s-%5s $%3s' % (name,origin,out[0],out[1],out[2],ret[0],ret[1],ret[2]))

此场景我们要解决的问题就是寻找使花费最小的每位游客应该乘坐的往返航班。

我们定义一个成本函数代表我们需要花费的资金。

# 计算某个给定时间在一天中的分钟数

def getminutes(t):

x = time.strptime(t, '%H:%M')

return x[3] * 60 + x[4]

# 成本函数。输入为数字序列

def schedulecost(sol):

totalprice=0

latestarrival=0

earliestdep=24*60

for d in range(int(len(sol)/2)):

# 得到往返航班

origin=peoplelist[d][1] #获取人员的来源地

outbound=flights[(origin,destination)][int(sol[2*d])] #获取往程航班

returnf=flights[(destination,origin)][int(sol[2*d+1])] #获取返程航班

# 总价格等于所有往返航班的价格之和

totalprice+=outbound[2]

totalprice+=returnf[2]

# 记录最晚到达和最早离开的时间

if latestarrival

if earliestdep>getminutes(returnf[0]): earliestdep=getminutes(returnf[0])

# 接机服务:每个人必须在机场等待直到最后一个人到达位置

# 送机服务:他们必须同时达到机场,并等待他们的返程航班

totalwait=0

for d in range(int(len(sol)/2)):

origin=peoplelist[d][1]

outbound=flights[(origin,destination)][int(sol[2*d])]

returnf=flights[(destination,origin)][int(sol[2*d+1])]

totalwait+=latestarrival-getminutes(outbound[1])

totalwait+=getminutes(returnf[0])-earliestdep

# 这个题解要求多付一天的汽车出租费用么?如果是,则费用为50美元

if latestarrival>earliestdep: totalprice+=50

return totalprice+totalwait

1、随机搜索算法:随机选择题解,计算成本值,成本值最小的题解为确定题解。domain为题解范围(可选航班范围),costf为成本函数。

def randomoptimize(domain,costf):

best=999999999

bestr=None

for i in range(0,1000):

# 创建随机解

sol=[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

#计算成本值

cost=costf(sol)

# 与目前得到的最优解进行比较

if cost

best=cost

bestr=sol

return sol #返回随机最优解

2、爬山法:对于成本函数连续的情况,题解向成本值减小的地方渐变,直到成本值不再变化。domain为题解范围(可选航班范围),costf为成本函数。在只有一个极低点时最有效。可以采用随机重复爬山法优化。

def hillclimb(domain,costf):

# 创建一个随机解

sol=[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

# 主循环

while 1:

# 创建相邻解的列表

neighbors=[]

for j in range(len(domain)): #在j等于0和末尾的时候存在问题

# 在每个方向上相对于原值偏离一点。每个方向上的偏离不相互影响

if sol[j]>domain[j][0]:

neighbors.append(sol[0:j]+[sol[j]-1]+sol[j+1:]) #向近0偏移

if sol[j]

neighbors.append(sol[0:j]+[sol[j]+1]+sol[j+1:]) #远0偏移

# 在相邻解中寻找最优解

current=costf(sol)

best=current

for j in range(len(neighbors)):

cost=costf(neighbors[j])

if cost

best=cost

sol=neighbors[j]

# 如果没有更好的解,则退出循环。即寻找了极低点

if best==current:

break

return sol

3、模拟退火算法:概率性接收更优解(更差解),时间越久,概率越大(越低)。

def annealingoptimize(domain,costf,T=10000.0,cool=0.95,step=1):

# 随机初始化值

vec=[float(random.randint(domain[i][0],domain[i][1])) for i in range(len(domain))]

while T>0.1:

# 选择一个索引值

i=random.randint(0,len(domain)-1)

# 选择一个改变索引值的方向

dir=random.randint(-step,step)

#创建一个代表题解的新列表,改变其中一个值

vecb=vec[:]

vecb[i]+=dir

if vecb[i]

elif vecb[i]>domain[i][1]: vecb[i]=domain[i][1] #如果渐变不超出了题解的范围

# 计算当前成本与新的成本

ea=costf(vec)

eb=costf(vecb)

p=pow(math.e,(-eb-ea)/T)

# 它是更好的解么?或者是趋向最优解的可能的临界解么

if (eb

vec=vecb

# 降低温度

T=T*cool

return vec

4、遗传算法:基因杂交(交叉)或基因变异。domain题解范围,costf成本函数,popsize种群大小,step变异基因量,mutprob变异比例,elite优秀基因者的比例,maxiter运行多少代。

def geneticoptimize(domain,costf,popsize=50,step=1,mutprob=0.2,elite=0.2,maxiter=100):

# 变异操作,存在变异失败的情况

def mutate(vec):

i=random.randint(0,len(domain)-1)

if random.random()<0.5 and vec[i]>&#61;domain[i][0]&#43;step:

return vec[0:i]&#43;[vec[i]-step]&#43;vec[i&#43;1:]

elif vec[i]<&#61;domain[i][1]-step:

return vec[0:i]&#43;[vec[i]&#43;step]&#43;vec[i&#43;1:]

# 杂交操作(交叉)

def crossover(r1,r2):

i&#61;random.randint(1,len(domain)-2)

return r1[0:i]&#43;r2[i:]

# 构建初始种群

pop&#61;[]

for i in range(popsize): #随机产生50个动物的种群

vec&#61;[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

pop.append(vec)

# 每一代有多少胜出者&#xff1f;

topelite&#61;int(elite*popsize)

# 主循环

for i in range(maxiter):

scores&#61;[(costf(v),v) for v in pop]

scores.sort()

ranked&#61;[v for (s,v) in scores]

# 在种群中选出优胜者

pop&#61;ranked[0:topelite]

# 为优秀基因者&#xff0c;添加变异和配对后的胜出者

while len(pop)

if random.random()

# 变异

c&#61;random.randint(0,topelite-1)

newanimal &#61; mutate(ranked[c])

if newanimal!&#61;None: #有可能存在变异死亡者

pop.append(newanimal)

else:

# 相互杂交。以后会遇到近亲结婚的问题

c1&#61;random.randint(0,topelite-1)

c2&#61;random.randint(0,topelite-1)

newanimal &#61; crossover(ranked[c1], ranked[c2])

pop.append(newanimal)

# 打印当前最优解和成本

# print(scores[0])

return scores[0][1] #返回最优解

测试程序

if __name__&#61;&#61;"__main__": #只有在执行当前模块时才会运行此函数

print(flights) #打印所有航班信息

domain&#61;[]

for start_stop in flights: #查询每个起止点的航班个数

domain.append((0,len(flights[start_stop])-1)) #获取题解范围&#xff0c;两边必区间(航班范围的数据序列)

# domain&#61;[(0,9)]*(len(peoplelist)*2)

print(domain)

s&#61;randomoptimize(domain,schedulecost) # 随机搜索法&#xff0c;寻找最优题解

print(s)

printschedule(s) #打印最优航班信息

s &#61; hillclimb(domain, schedulecost) # 爬山法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

s &#61; annealingoptimize(domain, schedulecost) # 模拟退火算法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

s &#61; geneticoptimize(domain, schedulecost) # 遗传算法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

全部代码optimization.py

# 优化算法。寻找使成本函数最小的题解。

import time

import random

import math

# 问题场景&#xff1a;

# 所有乘客从不同的地方飞到同一个目的地&#xff0c;服务人员等待所有人到来以后将人一次性接走。

# 离开时&#xff0c;服务人员将人一次性带到飞机场&#xff0c;所有乘客等待自己的航班离开。

# 要解决的问题&#xff1a;

# 如何设置乘客的到来和离开航班&#xff0c;以及接送机的时间&#xff0c;使得总代价最小。

# 将题解设为数字序列。

# 数字表示某人乘坐的第几次航班&#xff0c;从0开始&#xff0c;例如[1,4,3,2,7,3,6,3,2]表示第1个人做第2个航班来&#xff0c;第5个航班走&#xff0c;第2个人做第4个航班来&#xff0c;第3个航班走

# 题解相互独立&#xff1a;组团旅游问题&#xff0c;举办会议的人员接送问题

# 人员的名称和来源地信息

peoplelist &#61; [(&#39;name1&#39;,&#39;src1_place&#39;),

(&#39;name2&#39;,&#39;src2_place&#39;),

(&#39;name3&#39;,&#39;src3_place&#39;),

(&#39;name4&#39;,&#39;src4_place&#39;),

(&#39;name5&#39;,&#39;src5_place&#39;),

(&#39;name6&#39;,&#39;src6_place&#39;)]

# 目的机场

destination&#61;&#39;des_place&#39;

flights&#61;{} #加载所有航班信息。

# 查询所有的航班信息

for line in open(&#39;schedule.txt&#39;):

origin,dest,depart,arrive,price&#61;line.strip().split(&#39;,&#39;) #源地址、目的地址、离开时间、到达时间、价格

flights.setdefault((origin,dest),[]) #航班信息已起止点为键值&#xff0c;每个起止点有多个航班

# 将航班信息添加到航班列表中

flights[(origin,dest)].append((depart,arrive,int(price))) #按时间顺序扩展每次航班

# 将数字序列转换为航班&#xff0c;打印输出。输入为数字序列

def printschedule(r):

for d in range(int(len(r)/2)):

name&#61;peoplelist[d][0] #人员名称

origin&#61;peoplelist[d][1] #人员来源地

out&#61;flights[(origin,destination)][int(r[2*d])] #往程航班

ret&#61;flights[(destination,origin)][int(r[2*d&#43;1])] #返程航班

print(&#39;%10s %10s %5s-%5s $%3s %5s-%5s $%3s&#39; % (name,origin,out[0],out[1],out[2],ret[0],ret[1],ret[2]))

# 计算某个给定时间在一天中的分钟数

def getminutes(t):

x &#61; time.strptime(t, &#39;%H:%M&#39;)

return x[3] * 60 &#43; x[4]

# 成本函数。输入为数字序列

def schedulecost(sol):

totalprice&#61;0

latestarrival&#61;0

earliestdep&#61;24*60

for d in range(int(len(sol)/2)):

# 得到往返航班

origin&#61;peoplelist[d][1] #获取人员的来源地

outbound&#61;flights[(origin,destination)][int(sol[2*d])] #获取往程航班

returnf&#61;flights[(destination,origin)][int(sol[2*d&#43;1])] #获取返程航班

# 总价格等于所有往返航班的价格之和

totalprice&#43;&#61;outbound[2]

totalprice&#43;&#61;returnf[2]

# 记录最晚到达和最早离开的时间

if latestarrival

if earliestdep>getminutes(returnf[0]): earliestdep&#61;getminutes(returnf[0])

# 接机服务&#xff1a;每个人必须在机场等待直到最后一个人到达位置

# 送机服务&#xff1a;他们必须同时达到机场&#xff0c;并等待他们的返程航班

totalwait&#61;0

for d in range(int(len(sol)/2)):

origin&#61;peoplelist[d][1]

outbound&#61;flights[(origin,destination)][int(sol[2*d])]

returnf&#61;flights[(destination,origin)][int(sol[2*d&#43;1])]

totalwait&#43;&#61;latestarrival-getminutes(outbound[1])

totalwait&#43;&#61;getminutes(returnf[0])-earliestdep

# 这个题解要求多付一天的汽车出租费用么&#xff1f;如果是&#xff0c;则费用为50美元

if latestarrival>earliestdep: totalprice&#43;&#61;50

return totalprice&#43;totalwait

# 随机搜索算法&#xff1a;随机选择题解&#xff0c;计算成本值&#xff0c;成本值最小的题解为确定题解。domain为题解范围(可选航班范围)&#xff0c;costf为成本函数。

def randomoptimize(domain,costf):

best&#61;999999999

bestr&#61;None

for i in range(0,1000):

# 创建随机解

sol&#61;[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

#计算成本值

cost&#61;costf(sol)

# 与目前得到的最优解进行比较

if cost

best&#61;cost

bestr&#61;sol

return sol #返回随机最优解

# 爬山法&#xff1a;对于成本函数连续的情况&#xff0c;题解向成本值减小的地方渐变&#xff0c;直到成本值不再变化。domain为题解范围(可选航班范围)&#xff0c;costf为成本函数。

# 在只有一个极低点时最有效。可以采用随机重复爬山法优化

def hillclimb(domain,costf):

# 创建一个随机解

sol&#61;[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

# 主循环

while 1:

# 创建相邻解的列表

neighbors&#61;[]

for j in range(len(domain)): #在j等于0和末尾的时候存在问题

# 在每个方向上相对于原值偏离一点。每个方向上的偏离不相互影响

if sol[j]>domain[j][0]:

neighbors.append(sol[0:j]&#43;[sol[j]-1]&#43;sol[j&#43;1:]) #向近0偏移

if sol[j]

neighbors.append(sol[0:j]&#43;[sol[j]&#43;1]&#43;sol[j&#43;1:]) #远0偏移

# 在相邻解中寻找最优解

current&#61;costf(sol)

best&#61;current

for j in range(len(neighbors)):

cost&#61;costf(neighbors[j])

if cost

best&#61;cost

sol&#61;neighbors[j]

# 如果没有更好的解&#xff0c;则退出循环。即寻找了极低点

if best&#61;&#61;current:

break

return sol

# 模拟退火算法&#xff1a;概率性接收更优解(更差解)&#xff0c;时间越久&#xff0c;概率越大(越低)。

def annealingoptimize(domain,costf,T&#61;10000.0,cool&#61;0.95,step&#61;1):

# 随机初始化值

vec&#61;[float(random.randint(domain[i][0],domain[i][1])) for i in range(len(domain))]

while T>0.1:

# 选择一个索引值

i&#61;random.randint(0,len(domain)-1)

# 选择一个改变索引值的方向

dir&#61;random.randint(-step,step)

#创建一个代表题解的新列表&#xff0c;改变其中一个值

vecb&#61;vec[:]

vecb[i]&#43;&#61;dir

if vecb[i]

elif vecb[i]>domain[i][1]: vecb[i]&#61;domain[i][1] #如果渐变不超出了题解的范围

# 计算当前成本与新的成本

ea&#61;costf(vec)

eb&#61;costf(vecb)

p&#61;pow(math.e,(-eb-ea)/T)

# 它是更好的解么&#xff1f;或者是趋向最优解的可能的临界解么

if (eb

vec&#61;vecb

# 降低温度

T&#61;T*cool

return vec

# 遗传算法&#xff1a;基因杂交(交叉)或基因变异。domain题解范围&#xff0c;costf成本函数&#xff0c;popsize种群大小&#xff0c;step变异基因量&#xff0c;mutprob变异比例&#xff0c;elite优秀基因者的比例&#xff0c;maxiter运行多少代

def geneticoptimize(domain,costf,popsize&#61;50,step&#61;1,mutprob&#61;0.2,elite&#61;0.2,maxiter&#61;100):

# 变异操作&#xff0c;存在变异失败的情况

def mutate(vec):

i&#61;random.randint(0,len(domain)-1)

if random.random()<0.5 and vec[i]>&#61;domain[i][0]&#43;step:

return vec[0:i]&#43;[vec[i]-step]&#43;vec[i&#43;1:]

elif vec[i]<&#61;domain[i][1]-step:

return vec[0:i]&#43;[vec[i]&#43;step]&#43;vec[i&#43;1:]

# 杂交操作(交叉)

def crossover(r1,r2):

i&#61;random.randint(1,len(domain)-2)

return r1[0:i]&#43;r2[i:]

# 构建初始种群

pop&#61;[]

for i in range(popsize): #随机产生50个动物的种群

vec&#61;[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]

pop.append(vec)

# 每一代有多少胜出者&#xff1f;

topelite&#61;int(elite*popsize)

# 主循环

for i in range(maxiter):

scores&#61;[(costf(v),v) for v in pop]

scores.sort()

ranked&#61;[v for (s,v) in scores]

# 在种群中选出优胜者

pop&#61;ranked[0:topelite]

# 为优秀基因者&#xff0c;添加变异和配对后的胜出者

while len(pop)

if random.random()

# 变异

c&#61;random.randint(0,topelite-1)

newanimal &#61; mutate(ranked[c])

if newanimal!&#61;None: #有可能存在变异死亡者

pop.append(newanimal)

else:

# 相互杂交。以后会遇到近亲结婚的问题

c1&#61;random.randint(0,topelite-1)

c2&#61;random.randint(0,topelite-1)

newanimal &#61; crossover(ranked[c1], ranked[c2])

pop.append(newanimal)

# 打印当前最优解和成本

# print(scores[0])

return scores[0][1] #返回最优解

if __name__&#61;&#61;"__main__": #只有在执行当前模块时才会运行此函数

print(flights) #打印所有航班信息

domain&#61;[]

for start_stop in flights: #查询每个起止点的航班个数

domain.append((0,len(flights[start_stop])-1)) #获取题解范围&#xff0c;两边必区间(航班范围的数据序列)

# domain&#61;[(0,9)]*(len(peoplelist)*2)

print(domain)

s&#61;randomoptimize(domain,schedulecost) # 随机搜索法&#xff0c;寻找最优题解

print(s)

printschedule(s) #打印最优航班信息

s &#61; hillclimb(domain, schedulecost) # 爬山法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

s &#61; annealingoptimize(domain, schedulecost) # 模拟退火算法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

s &#61; geneticoptimize(domain, schedulecost) # 遗传算法&#xff0c;寻找最优题解

print(s)

printschedule(s) # 打印最优航班信息

使用优化算法解决房间住宿问题

场景&#xff1a;每个房间有两个床位&#xff0c;每个学生有自己首选房间和次选房间(只选房间&#xff0c;不选床位)。将所有学生安排到所有房间

目标&#xff1a;在尽量满足学生的选择的情况下&#xff0c;为学生安排宿舍。

将题解转化为数字间皆有联系的数字序列。可以让每个数字代表可选床位的第几个&#xff0c;索引从0开始

例如&#xff1a;[0,2,1,1,1,2,0,1]表示第1个人选可选床位的第1个&#xff0c;第2个人选剩余可选床位的第3个床位&#xff0c;第3个人选剩余可选床位的第2个。。。

测试代码

# 利用之前设计好的优化算法&#xff0c;解决涉及偏好的优化问题。1、将题解转化为数字序列化&#xff0c;可以写出题解范围。2、成本函数能返回值

import random

import math

import optimization

# 场景&#xff1a;每个房间有两个床位&#xff0c;每个学生有自己首选房间和次选房间(只选房间&#xff0c;不选床位)。将所有学生安排到所有房间

# 目标&#xff1a;在尽量满足学生的选择的情况下&#xff0c;为学生安排宿舍

# 将题解转化为数字间没有联系的数字序列。可以让每个数字代表可选床位的第几个&#xff0c;索引从0开始

# 例如&#xff1a;[0,2,1,1,1,2,0,1]表示第1个人选可选床位的第1个&#xff0c;第2个人选剩余可选床位的第3个床位&#xff0c;第3个人选剩余可选床位的第2个。。。

# 代表宿舍&#xff0c;每个宿舍有两个床位。5个房间

dorms&#61;[&#39;Zeus&#39;,&#39;Athena&#39;,&#39;Hercules&#39;,&#39;Bacchus&#39;,&#39;Pluto&#39;]

# 代表学生及其首选房间和次选房间。10个人

prefs&#61;[(&#39;Toby&#39;, (&#39;Bacchus&#39;, &#39;Hercules&#39;)),

(&#39;Steve&#39;, (&#39;Zeus&#39;, &#39;Pluto&#39;)),

(&#39;Karen&#39;, (&#39;Athena&#39;, &#39;Zeus&#39;)),

(&#39;Sarah&#39;, (&#39;Zeus&#39;, &#39;Pluto&#39;)),

(&#39;Dave&#39;, (&#39;Athena&#39;, &#39;Bacchus&#39;)),

(&#39;Jeff&#39;, (&#39;Hercules&#39;, &#39;Pluto&#39;)),

(&#39;Fred&#39;, (&#39;Pluto&#39;, &#39;Athena&#39;)),

(&#39;Suzie&#39;, (&#39;Bacchus&#39;, &#39;Hercules&#39;)),

(&#39;Laura&#39;, (&#39;Bacchus&#39;, &#39;Hercules&#39;)),

(&#39;James&#39;, (&#39;Hercules&#39;, &#39;Athena&#39;))]

# [(0,9),(0,8),(0,7),(0,6),...,(0,0)] 题解范围。因为前面选择了一个&#xff0c;后面的可选范围就会变少

domain&#61;[(0,(len(dorms)*2)-i-1) for i in range(0,len(dorms)*2)] #题解的可选范围

# 打印输出题解。输入为题解序列

def printsolution(vec):

slots&#61;[]

# 为每个宿舍键两个槽

for i in range(len(dorms)): slots&#43;&#61;[i,i]

# 遍历每一名学生的安置情况

for i in range(len(vec)):

x&#61;int(vec[i])

# 从剩余槽中选择

dorm&#61;dorms[slots[x]]

# 输出学生及其被分配的宿舍

print(prefs[i][0],dorm)

# 删除该槽&#xff0c;这样后面的数字列表才能正确翻译成“剩余床位”

del slots[x]

# 成本函数&#xff1a;

def dormcost(vec):

cost&#61;0

# 创建一个槽序列

slots&#61;[0,0,1,1,2,2,3,3,4,4]

# 遍历每一名学生

for i in range(len(vec)):

x&#61;int(vec[i])

dorm&#61;dorms[slots[x]]

pref&#61;prefs[i][1]

# 首选成本值为0&#xff0c;次选成本值为1

if pref[0]&#61;&#61;dorm: cost&#43;&#61;0

elif pref[1]&#61;&#61;dorm: cost&#43;&#61;1

else: cost&#43;&#61;3

# 不在选择之列则成本值为3

# 删除选中的槽

del slots[x]

return cost

if __name__&#61;&#61;"__main__": #只有在执行当前模块时才会运行此函数

print(domain)

s &#61; optimization.randomoptimize(domain, dormcost) # 随机搜索法&#xff0c;寻找最优题解

print(s)

printsolution(s) # 打印最优解代表的含义

s &#61; optimization.hillclimb(domain, dormcost) # 爬山法&#xff0c;寻找最优题解

print(s)

printsolution(s) # 打印最优解代表的含义

s &#61; optimization.annealingoptimize(domain, dormcost) # 模拟退火算法&#xff0c;寻找最优题解

print(s)

printsolution(s) # 打印最优解代表的含义

s &#61; optimization.geneticoptimize(domain, dormcost) # 遗传算法&#xff0c;寻找最优题解

print(s)

printsolution(s) # 打印最优解代表的含义

使用优化算法解决绘制关系网问题

场景&#xff1a;在绘制关系网图中&#xff0c;每个人在图中都有位置x&#xff0c;y坐标&#xff0c;在有关联的两个人中间添加连线。

目标&#xff1a;是所有连线的交叉数最少

将题解转化为数字间没有联系的数字序列。可以让每个数字代表人物在图形中的位置x&#xff0c;y

例如&#xff1a;[200,120,250,230..]表示第1个人坐标为200,120&#xff0c;第2个人坐标为250,230…

测试代码

# 将优化算法应用到绘制关系网图中&#xff0c;使得交叉线最少

import math

import optimization

# 场景&#xff1a;在绘制关系网图中&#xff0c;每个人在图中都有位置x&#xff0c;y坐标&#xff0c;在有关联的两个人中间添加连线。

# 目标&#xff1a;是所有连线的交叉数最少

# 将题解转化为数字间没有联系的数字序列。可以让每个数字代表人物在图形中的位置x&#xff0c;y

# 例如&#xff1a;[200,120,250,230..]表示第1个人坐标为200,120&#xff0c;第2个人坐标为250,230...

# 关系网中涉及的人员

people&#61;[&#39;Charlie&#39;,&#39;Augustus&#39;,&#39;Veruca&#39;,&#39;Violet&#39;,&#39;Mike&#39;,&#39;Joe&#39;,&#39;Willy&#39;,&#39;Miranda&#39;]

# 关联关系

links&#61;[(&#39;Augustus&#39;, &#39;Willy&#39;),

(&#39;Mike&#39;, &#39;Joe&#39;),

(&#39;Miranda&#39;, &#39;Mike&#39;),

(&#39;Violet&#39;, &#39;Augustus&#39;),

(&#39;Miranda&#39;, &#39;Willy&#39;),

(&#39;Charlie&#39;, &#39;Mike&#39;),

(&#39;Veruca&#39;, &#39;Joe&#39;),

(&#39;Miranda&#39;, &#39;Augustus&#39;),

(&#39;Willy&#39;, &#39;Augustus&#39;),

(&#39;Joe&#39;, &#39;Charlie&#39;),

(&#39;Veruca&#39;, &#39;Augustus&#39;),

(&#39;Miranda&#39;, &#39;Joe&#39;)]

# 计算交叉线&#xff0c;作为成本函数

def crosscount(v):

# 将数字序列转化为一个person:(x,y)的字典

loc&#61;dict([(people[i],(v[i*2],v[i*2&#43;1])) for i in range(0,len(people))])

total&#61;0

# 遍历每一对连线

for i in range(len(links)):

for j in range(i&#43;1,len(links)):

# 获取坐标位置

(x1,y1),(x2,y2)&#61;loc[links[i][0]],loc[links[i][1]]

(x3,y3),(x4,y4)&#61;loc[links[j][0]],loc[links[j][1]]

den&#61;(y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)

# 如果两线平行&#xff0c;则den&#61;&#61;0。两条线是线段&#xff0c;不是直线

if den&#61;&#61;0: continue

# 否则&#xff0c;ua与ub就是两条交叉线的分数值。

# line where they cross

ua&#61;((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/den

ub&#61;((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/den

# 如果两条线的分数值介于0和1之间&#xff0c;则两线彼此交叉

if ua>0 and ua<1 and ub>0 and ub<1:

total&#43;&#61;1

for i in range(len(people)):

for j in range(i&#43;1,len(people)):

# 获取两个节点的位置

(x1,y1),(x2,y2)&#61;loc[people[i]],loc[people[j]]

# 获取两节点之间的距离

dist&#61;math.sqrt(math.pow(x1-x2,2)&#43;math.pow(y1-y2,2))

# 对间距小于50个像素的节点进行判罚

if dist<50:

total&#43;&#61;(1.0-(dist/50.0))

return total

#画图&#xff0c;绘制网络

from PIL import Image,ImageDraw

def drawnetwork(sol):

# 建立image对象

img&#61;Image.new(&#39;RGB&#39;,(400,400),(255,255,255))

draw&#61;ImageDraw.Draw(img)

# 建立标识位置信息的字典

pos&#61;dict([(people[i],(sol[i*2],sol[i*2&#43;1])) for i in range(0,len(people))])

for (a,b) in links:

draw.line((pos[a],pos[b]),fill&#61;(255,0,0))

for n,p in pos.items():

draw.text(p,n,(0,0,0))

img.show()

domain&#61;[(10,370)]*(len(people)*2) #设定题解范围

if __name__&#61;&#61;"__main__": #只有在执行当前模块时才会运行此函数

print(domain)

s &#61; optimization.randomoptimize(domain, crosscount) # 随机搜索法&#xff0c;寻找最优题解

print(s)

drawnetwork(s) # 绘制关系网

s &#61; optimization.hillclimb(domain, crosscount) # 爬山法&#xff0c;寻找最优题解

print(s)

drawnetwork(s) # 绘制关系网

s &#61; optimization.annealingoptimize(domain, crosscount) # 模拟退火算法&#xff0c;寻找最优题解

print(s)

drawnetwork(s) # 绘制关系网

s &#61; optimization.geneticoptimize(domain, crosscount) # 遗传算法&#xff0c;寻找最优题解

print(s)

drawnetwork(s) # 绘制关系网

以上就是本文的全部内容&#xff0c;希望对大家的学习有所帮助&#xff0c;也希望大家多多支持脚本之家。



推荐阅读
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
author-avatar
zero__
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有