Я пытался разработать алгоритм под названием «Сохраняйте инструмент как можно скорее, но во время моделирования я понял, что он требует слишком много времени для запуска».
Я хочу уменьшить время выполнения и проверить другие предыдущие вопросы о том, как ускорить кодирование на Python. Python медленнее, чем Java / C#? [закрыто] Я нашел несколько решений, но не знаю, как реализовать их в моем коде.
На моем компьютере это занимает 0,004999876022338867 секунд, но основная проблема в том, что для всей программы эта функция вызывается 13000 раз.
Здесь я прилагаю весь свой код. Если у вас есть предложения по его улучшению, пожалуйста, не стесняйтесь поделиться со мной.
import sets
import numpy
import copy
import time
J= {1: [6, 7],2: [2, 3], 3: [1, 6, 9], 4: [1, 5, 9], 5: [5, 8, 10], 6: [1, 3, 6, 8], 7: [5, 6, 8, 9], 8: [5, 7, 8], 9: [1, 4, 5, 8], 10: [1, 2, 4, 10]}
def KTNS(sigma=[10, 9, 4, 1, 6, 3, 7, 5, 2, 8], Jobs=J, m=10 ,capacity=4 ):
t0=time.time()
Tools = {}
Lin = {}
n=len(sigma)
for i in range(1,m+1):
for e in sigma:
if i in Jobs[e]:
Tools[i]=sets.Set([])
count = 1
available_tools=sets.Set()
for e in sigma:
for i in Jobs[e]:
Tools[i].add(count)
available_tools.add(i)
count+=1
Tin=copy.deepcopy(Tools)
for e in Tin:
Lin[e]=min(Tin[e])
count=1
J = numpy.array([0] *m)
W = numpy.array([[0] * m] * n)
while count<=len(sigma):
for e in Tools:
if len(available_tools)<capacity:
reference=len(available_tools)
else:
reference=capacity
while numpy.count_nonzero(J == 1) <reference:
min_value = min(Lin.itervalues())
min_keys = [k for k in Lin if Lin[k] == min_value]
temp = min_keys[0] #min(Lin, key=Lin.get)
if min_value>count:
if len(min_keys)>=2:
if count==1:
J[temp - 1] = 1
Lin[temp] = '-'
else:
J0=W[count-2]
k=0
for elements in min_keys: #tested
if numpy.count_nonzero(J == 1) < reference:
if J0[elements-1]==1:
J[elements-1]=1
Lin[elements]='-'
k=1
else:
pass
else:
pass
if k==0:
J[temp - 1] = 1
Lin[temp] = '-'
else:
J[temp - 1] = 1
Lin[temp] = '-'
else:
J[temp-1]=1
Lin[temp] = '-'
Tin[e].discard(count)
for element in Tin:
try:
Lin[element] = min(Tin[element])
except ValueError:
Tin[element]=sets.Set([len(sigma)+1])
Lin[element]=len(sigma)+1
W[count-1]=J
J= numpy.array([0] *m)
count+=1
Cost=0
for e in range(1,len(sigma)):
temp=W[e]-W[e-1]
temp[temp < 0] = 0
Cost+=sum(temp)
return Cost+capacity,time.time()-t0
Если вам нужен полный обзор рабочего кода, попробуйте codereview.stackexchange.com - но прочтите справочный центр перед тем, как публиковать, чтобы убедиться, что ваш вопрос там по теме!
Также может помочь подробное объяснение алгоритма, который вы реализуете.
Умножив время на 13000, я получу, что весь процесс занимает 65 секунд. Какое максимальное время занимает должен? Я согласен с Blorgbeard - в то время как многим людям неправильно говорят перейти на codereview, у вас есть полностью функционирующий код, на который вы хотите, чтобы люди посмотрели. Этот вопрос подойдет, просто убедитесь, что вы упомянули, что он размещен здесь. (Здесь это не не по теме, но, вероятно, там будет лучше встречено, поэтому я не голосую за закрытие.)
Вам следует использовать лучшие соглашения об именах для ваших переменных и, возможно, разбить эту функцию на множество более мелких функций. Как есть, потребуется время, чтобы понять, что делает этот код.
@zmbq Я только просил кое-какие знания, потому что я пробовал несколько функций, и они не работали. Я не хотел, чтобы вы выясняли весь код и исправляли его, только я хотел знать методы или предложения. Если правильное место - это обзор cody, я отправлю его туда, но я подумал, что здесь может поместиться.
Одна рекомендация - постарайтесь свести к минимуму использование словарей. Похоже, что многие из ваших словарей могут быть списками. Доступ к словарю намного медленнее, чем доступ к списку в python.
Похоже, вы могли бы просто сделать списками Tools, Lin и Tin, например Lin = []
вместо Lin = {}
, и я ожидаю, что вы увидите резкое улучшение производительности.
Вы знаете размеры ваших 3 словарей, поэтому просто инициализируйте их до нужного вам размера. Создайте Lin и Tools следующим образом:
Lin = [None] * m+1
Tools = [None] * m+1
Tin = [None] * m+1
Это создаст список из m + 1 элементов (это то, что вы получите с вашим циклом от 1 до m + 1). Поскольку вы выполняете индексацию на основе 1, она оставляет пустое место в Lin [0], Tools [0] и т. д., Но тогда вы сможете получить доступ к Lin [1] - Lin [10], как и вы » ре в настоящее время занимаюсь. Простой пример, который вы можете попробовать сами:
python3 -m timeit -s 'foo = [x for x in range(10000)]' 'foo[500]'
100000000 loops, best of 3: 0.0164 usec per loop
python3 -m timeit -s 'foo = {x: x for x in range(10000)}' 'foo[500]'
10000000 loops, best of 3: 0.0254 usec per loop
Просто изменив словари на список, вы получите почти двукратное улучшение. Ваша 65-секундная задача теперь займет около 35 секунд.
Кстати, ознакомьтесь с вики-страницей python для советы по увеличению скорости, включая множество ссылок о том, как профилировать вашу функцию.
И как мне приспособить использование словарей к списку? В настоящее время я использую словари, потому что они довольно просты для доступа к информации и ее обновления. Если я использую список и удаляю некоторые элементы, индекс будет изменен, и я не узнаю. Любая идея?
Помните, что списки также являются динамическими, и вы можете добавить push
в индекс, добавить в конец и конкретные индексы del
, хотя я не вижу нигде в вашем коде, который вам может понадобиться. Вы никогда не добавляете Lin, Tin или Tools, хотя вы добавляете их в набор, который вы помещаете в Tools [i]. Просто создайте свой список. Я немного поправил свой ответ, чтобы прояснить это. Удачи!
Вы всерьез ожидаете, что кто-то изучит ваш код, выяснит, что он делает, и предложит улучшения?