Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 每次在for循环中调用函数时,该函数似乎运行得更快_Python_Algorithm - Fatal编程技术网

Python 每次在for循环中调用函数时,该函数似乎运行得更快

Python 每次在for循环中调用函数时,该函数似乎运行得更快,python,algorithm,Python,Algorithm,我写了一个非常粗糙的爬山/贪婪算法来解决旅行推销员问题。其目的是将其用作基准,同时不断改进运行时间并优化解决方案 编辑:根据Stefan Pochmann的建议,这似乎与硬件有关,而与程序无关。在i7-4790处理器上,在开始爬山循环之前立即执行sum(xrange(10**8))将导致第一次爬山的运行时间超过一半,并在每个循环上进一步提高。 如果我在循环中对相同的数据运行爬山算法10次(每次爬山进行10000次迭代),我注意到解决方案的运行时间几乎总是普遍下降,最终解决方案占用第一个解决方案所

我写了一个非常粗糙的爬山/贪婪算法来解决旅行推销员问题。其目的是将其用作基准,同时不断改进运行时间并优化解决方案

编辑:根据Stefan Pochmann的建议,这似乎与硬件有关,而与程序无关。在i7-4790处理器上,在开始爬山循环之前立即执行
sum(xrange(10**8))
将导致第一次爬山的运行时间超过一半,并在每个循环上进一步提高。

如果我在
循环中对相同的数据运行爬山算法10次(每次爬山进行10000次迭代),我注意到解决方案的运行时间几乎总是普遍下降,最终解决方案占用第一个解决方案所需时间的约50%。在每个解上计算的唯一东西是爬山本身;支持数据(如距离/时间矩阵和作业列表)在所有解决方案之前存储在内存中。因此,前三个函数仅用于MCVE,可以忽略

打印的输出是运行时,然后是
[(迭代次数,贪婪路径成本)]
列表,即搜索解决方案时选择新的
最佳路径的迭代次数。运行时间似乎与每次爬山时存储的临时路线数无关。每个解决方案都应该是独立的。有人能在
计算路线成本
爬山
中看到加速的原因吗?我在这里遗漏了什么?我将如何分析这种加速的原因?这是在Python2.7.9中实现的

import math
import random
import datetime

# To generate a random customer name for each fake order
LETTERS = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
            'r','s','t','u','v','w','x','y','z']


def crow_flies(lat1, lon1, lat2, lon2):
    ''' For MCVE. Straight-line distance between two locations. Should not affect 
    run time.
    '''

    dx1,dy1 = (lat1/180)*3.141593,(lon1/180)*3.141593
    dx2,dy2 = (lat2/180)*3.141593,(lon2/180)*3.141593
    dlat,dlon = abs(dx2-dx1),abs(dy2-dy1)
    a = (math.sin(dlat/2))**2 + (math.cos(dx1) * math.cos(dx2) 
        * (math.sin(dlon/2))**2)
    c = 2*(math.atan2(math.sqrt(a),math.sqrt(1-a))) 
    km = 6373 * c
    return km


def gen_matrix(order_list):
    ''' For MCVE. Returns dictionary of distance and time between all 
    location pairs. Should not affect run time.
    Returns {(location_id_from, location_id_to): [distance, time]}
    '''

    matrix = {}
    for loc in order_list:
        for pair_loc in order_list:
            if loc[0] != pair_loc[0]:
                distance = crow_flies(loc[1], loc[2], pair_loc[1], pair_loc[2])
                matrix[(loc[0], pair_loc[0])] = [distance, distance*random.random()]
    return matrix


def gen_jobs(num_jobs, start_time, end_time, lat_low, lat_high, lon_low, lon_high):
    ''' For MVCE. Creates random jobs with random time windows and locations 
    '''

    job_list = []
    for x in range(num_jobs):
        lat = random.uniform(lat_low, lat_high)
        lon = random.uniform(lon_low, lon_high)
        start = random.randrange(start_time, end_time-120, 1)
        end = start + 120
        faux_start = random.randrange(start, end-60, 1)
        faux_end = faux_start + 60
        capacity_demand = random.choice([-1, 1])
        name_1 = random.choice(LETTERS)
        name_2 = random.choice(LETTERS)
        name_3 = random.choice(LETTERS)
        name_4 = random.choice(LETTERS)
        name_5 = random.choice(LETTERS)
        NAME = name_1 + name_2 + name_3 + name_4 + name_5
        job_list.append([NAME, lat, lon, start, end, faux_start, faux_end, 
                        capacity_demand])
    return job_list


def calc_route_cost(start_time, route, matrix):
    ''' Returns the cost of each randomly generated route '''

    cost = 0

    # Mileage cost
    dist_cost = sum([matrix[(route[x][0], route[x+1][0])][0] for x in 
                    range(len(route)-1)]) * 0.14
    cost += dist_cost

    # Man-hour cost
    time_cost = sum([matrix[(route[x][0], route[x+1][0])][1] for x in 
                    range(len(route)-1)]) * 0.35        
    cost += time_cost

    for x in range(0, len(route)-1):
        travel_time = matrix[(route[x][0], route[x+1][0])][1]
        arrival = start_time + travel_time
        start_time += travel_time
        departure = arrival + 10

        if arrival < route[x+1][3]:
            # Penalise early arrival
            arr_cost = (route[x+1][3] - arrival)**2
            cost += arr_cost

        elif departure > route[x+1][4]:
            # Penalise late departure
            dep_cost = (departure - route[x+1][4])**2
            cost += dep_cost

        if arrival < route[x+1][5]:
            # Penalise 'soft' early arrival i.e. earlier than a fake prediction 
            # of arrival
            faux_arr_cost = (route[x+1][5] - arrival)**1.2
            cost += faux_arr_cost 

        elif departure > route[x+1][6]:
            # Penalise 'soft' late departure
            faux_dep_cost = (departure - route[x+1][6])**1.2
            cost += faux_dep_cost

    return cost


def hill_climb(jobs, matrix, iterations):
    ''' Randomly generate routes and store route if cheaper than predecessor '''

    cost_tracking, iteration_track = [], []
    initial_cost = calc_route_cost(480, jobs, matrix)
    best_cost = initial_cost
    best_route = jobs[:]
    changed_route = jobs[:]

    for x in range(iterations):
        random.shuffle(changed_route)
        new_cost = calc_route_cost(480, changed_route, matrix)

        if new_cost < best_cost:
            best_route = changed_route[:]
            best_cost = new_cost
            cost_tracking.append(best_cost)
            iteration_track.append(x)

    return cost_tracking, iteration_track


if __name__ == '__main__':

    #random_jobs = gen_jobs(20, 480, 1080, 24, 25, 54, 55)

    random_jobs = [['lmizn', 24.63441343319078, 54.766698677134784, 501, 621, 558, 618, 1],
                    ['jwrmk', 24.45711393348282, 54.255786174435165, 782, 902, 782, 842, 1],
                    ['gbzqc', 24.967074991405035, 54.07326911656665, 682, 802, 687, 747, 1],
                    ['odriz', 24.54161147027789, 54.13774173532877, 562, 682, 607, 667, -1],
                    ['majfj', 24.213785557876257, 54.452603867220475, 681, 801, 731, 791, -1],
                    ['scybg', 24.936517492880274, 54.83786889438055, 645, 765, 662, 722, -1],
                    ['betow', 24.78072704532661, 54.99907581479066, 835, 955, 865, 925, -1],
                    ['jkhmp', 24.88461478479374, 54.42327833917202, 546, 666, 557, 617, -1],
                    ['wbpnq', 24.328080543462, 54.85565694610073, 933, 1053, 961, 1021, -1],
                    ['ezguc', 24.292203133848382, 54.65239508177714, 567, 687, 583, 643, -1],
                    ['nlbgh', 24.111932340385735, 54.895627940055995, 675, 795, 711, 771, -1],
                    ['rtmbc', 24.64381176454049, 54.739636798961044, 870, 990, 910, 970, 1],
                    ['znkah', 24.235361720889216, 54.699010081109854, 627, 747, 645, 705, -1],
                    ['yysai', 24.48931405352803, 54.37480185313546, 870, 990, 882, 942, -1],
                    ['mkmbk', 24.5628992946158, 54.219159859450926, 833, 953, 876, 936, -1],
                    ['wqygy', 24.035376675509728, 54.92994438408514, 693, 813, 704, 764, -1],
                    ['gzwwa', 24.476121543580852, 54.13822533413381, 854, 974, 879, 939, 1],
                    ['xuyov', 24.288078529689894, 54.81812092976614, 933, 1053, 935, 995, 1],
                    ['tulss', 24.841925420359246, 54.08156783033599, 670, 790, 684, 744, -1],
                    ['ptdng', 24.113767467325335, 54.9417036320267, 909, 1029, 941, 1001, 1]]

    matrix = gen_matrix(random_jobs)

    # Below is the loop that appears to accelerate

    for p in range(10):
        start = datetime.datetime.now()
        sim_ann = hill_climb(random_jobs, matrix, 10000)
        end = datetime.datetime.now()

        # Number of iterations against greedy cost
        iteration_count = zip(sim_ann[1], sim_ann[0])

        print 'RUNTIME:', str(end - start)        
        print 'SOLUTION CONVERGENCE:', str(iteration_count)
导入数学
随机输入
导入日期时间
#为每个假订单生成随机客户名称
字母=['a'、'b'、'c'、'd'、'e'、'f'、'g'、'h'、'i'、'j'、'k'、'l'、'm'、'n'、'o'、'p'、'q',
‘r’、‘s’、‘t’、‘u’、‘v’、‘w’、‘x’、‘y’、‘z’]
def乌鸦蝇(lat1、lon1、lat2、lon2):
“给麦克维。两个位置之间的直线距离。不应影响
运行时。
'''
dx1,dy1=(lat1/180)*3.141593,(lon1/180)*3.141593
dx2,dy2=(lat2/180)*3.141593,(lon2/180)*3.141593
dlat,dlon=abs(dx2-dx1),abs(dy2-dy1)
a=(math.sin(dlat/2))**2+(math.cos(dx1)*math.cos(dx2)
*(数学单(dlon/2))**2)
c=2*(数学atan2(数学sqrt(a),数学sqrt(1-a)))
公里=6373*c
返回公里
def gen_矩阵(订单列表):
“给麦克维。返回所有对象之间的距离和时间字典
位置对。不应影响运行时。
返回{(location_id_from,location_id_to):[distance,time]}
'''
矩阵={}
对于订单列表中的loc:
对于订单列表中的配对位置:
如果loc[0]!=配对位置[0]:
距离=乌鸦(位置[1],位置[2],成对位置[1],成对位置[2])
矩阵[(loc[0],pair_loc[0])]=[距离,距离*随机。随机()
返回矩阵
def gen_作业(数量作业、开始时间、结束时间、纬度低、纬度高、纬度低、纬度高):
“给MVCE。创建具有随机时间窗口和位置的随机作业
'''
作业列表=[]
对于范围内的x(num_作业):
横向=随机均匀(横向低,横向高)
lon=随机均匀(lon_低,lon_高)
开始=随机。随机范围(开始时间,结束时间-120,1)
结束=开始+120
faux_start=random.randrange(开始,结束-60,1)
人造终点=人造起点+60
容量需求=随机选择([-1,1])
name_1=随机选择(字母)
name_2=随机选择(字母)
name_3=随机选择(字母)
name_4=随机选择(字母)
name_5=随机选择(字母)
姓名=姓名1+姓名2+姓名3+姓名4+姓名5
作业列表。追加([名称、纬度、经度、起点、终点、假起点、假终点、,
容量(单位需求量)
返回作业列表
def计算路线成本(开始时间、路线、矩阵):
''返回每个随机生成路由的成本''
成本=0
#里程成本
dist_cost=x in的总和([matrix[(route[x][0],route[x+1][0])][0]
范围(长度(路线)-1)]*0.14
成本+=距离成本
#工时费
时间成本=x英寸的总和([矩阵[(路径[x][0],路径[x+1][0])][1]
范围(长度(路线)-1)]*0.35
成本+=时间成本
对于范围内的x(0,透镜(路线)-1):
行程时间=矩阵[(路线[x][0],路线[x+1][0])][1]
到达=开始时间+旅行时间
开始时间+=行程时间
出发=到达+10
如果到达<路线[x+1][3]:
#惩罚提前到达
到达成本=(路线[x+1][3]-到达)**2
成本+=到货成本
elif出发>路线[x+1][4]:
#处罚迟到
dep_成本=(出发-路线[x+1][4])**2
成本+=折旧成本
如果到达<路线[x+1][5]:
#惩罚“软”提前到达,即早于虚假预测
#到达时间
人工到达成本=(路线[x+1][5]-到达)**1.2
成本+=人造成本
elif出发>路线[x+1][6]:
#处罚“软性”迟到
假折旧成本=(出发-路线[x+1][6])**1.2
成本+=假折旧成本
退货成本
def爬山(作业、矩阵、迭代):
''随机生成路由并存储路由(如果比前一个路由便宜''
成本跟踪,迭代跟踪=[],[]
初始成本=计算路线成本(480,作业,矩阵)
最佳成本=初始成本
最佳路径=作业[:]
更改的路径=作业[:]
对于范围内的x(迭代):
随机。洗牌(改变路线)
新成本=计算路线成本(480,变更路线,矩阵)
如果新成本<最佳成本:
最佳路线=更改的路线[:]
最佳成本=新成本
成本跟踪。追加(最佳成本)
迭代_track.append(x)
退货成本
for x in range(10):
    a = sum(xrange(10**8))