Python 中的模拟退火,While 循环中的变量?
Simulated Annealing in Python, Variables in While loop?
成功编写了一个遗传算法后,我现在正在编写一个模拟退火程序来与 GA 进行比较,但似乎无法使其达到任何一种优化,更不用说全局优化了。
经过一些测试后,我认为问题似乎是将变量传递回 while 循环。出于测试目的,我已将代码更改为基本上只接受比以前的解决方案具有更低能量增量的解决方案,因此我应该期望存储最佳解决方案的变量仅显示较低的数字,但实际上是波动的并且总是返回最多最近的解决方案是否更好。任何帮助将不胜感激。
while temperature >0.01:
solutionlength = len(Solution)
NeighbourSolution = Solution
switch1 = i % solutionlength
i +=random.randint(0,100)
switch2 = i % solutionlength
NeighbourSolution[switch1], NeighbourSolution[switch2] = NeighbourSolution[switch2], NeighbourSolution[switch1]
EnergyOld = Solution.get_changeover_times()
EnergyNew = NeighbourSolution.get_changeover_times()
EnergyDelta = EnergyNew - EnergyOld
if EnergyDelta < 0:
acceptanceprob = 1
else:
acceptanceprob = 0 #math.exp(-EnergyDelta/temperature)
if acceptanceprob > 0: #random.random():
Solution = NeighbourSolution
if Solution.get_changeover_times() < bestsolution.get_changeover_times():
bestsolution = Solution
print (bestsolution.get_changeover_times())
temperature -= coolingrate
问题不在于 "passing variables back into the while loop",因为您只能将变量传递给函数,而不能传递给循环。
问题是像 NeighbourSolution = Solution
或 bestsolution = Solution
这样的行仅仅使两个名称指向同一个对象。因此,如果您更改例如Solution
你也在改变 bestsolution
。当然,当你比较bestsolution.get_changeover_times()
和Solution.get_changeover_times()
时,一个对象的切换次数绝不会少于同一个对象的切换次数。
解决方案是制作对象的副本,而不是仅仅为其分配一个额外的名称。我不知道你的 Solution
是什么类型的对象,但如果它是一个列表子类,你可以使用 Solution[:]
来复制它。或者它可能有一个 .copy()
方法,或者你可以使用 copy
模块。例如:
from copy import copy
# ...
bestsolution = copy(Solution)
copy.copy()
是一个 浅拷贝, 意味着它创建了一个新的 top-level 对象,但在其中放置了对与原始对象相同的对象的引用目的。如果这不完全有效,请尝试 copy.deepcopy()
,它还会复制包含的对象以及它们包含的任何对象,依此类推。
成功编写了一个遗传算法后,我现在正在编写一个模拟退火程序来与 GA 进行比较,但似乎无法使其达到任何一种优化,更不用说全局优化了。
经过一些测试后,我认为问题似乎是将变量传递回 while 循环。出于测试目的,我已将代码更改为基本上只接受比以前的解决方案具有更低能量增量的解决方案,因此我应该期望存储最佳解决方案的变量仅显示较低的数字,但实际上是波动的并且总是返回最多最近的解决方案是否更好。任何帮助将不胜感激。
while temperature >0.01:
solutionlength = len(Solution)
NeighbourSolution = Solution
switch1 = i % solutionlength
i +=random.randint(0,100)
switch2 = i % solutionlength
NeighbourSolution[switch1], NeighbourSolution[switch2] = NeighbourSolution[switch2], NeighbourSolution[switch1]
EnergyOld = Solution.get_changeover_times()
EnergyNew = NeighbourSolution.get_changeover_times()
EnergyDelta = EnergyNew - EnergyOld
if EnergyDelta < 0:
acceptanceprob = 1
else:
acceptanceprob = 0 #math.exp(-EnergyDelta/temperature)
if acceptanceprob > 0: #random.random():
Solution = NeighbourSolution
if Solution.get_changeover_times() < bestsolution.get_changeover_times():
bestsolution = Solution
print (bestsolution.get_changeover_times())
temperature -= coolingrate
问题不在于 "passing variables back into the while loop",因为您只能将变量传递给函数,而不能传递给循环。
问题是像 NeighbourSolution = Solution
或 bestsolution = Solution
这样的行仅仅使两个名称指向同一个对象。因此,如果您更改例如Solution
你也在改变 bestsolution
。当然,当你比较bestsolution.get_changeover_times()
和Solution.get_changeover_times()
时,一个对象的切换次数绝不会少于同一个对象的切换次数。
解决方案是制作对象的副本,而不是仅仅为其分配一个额外的名称。我不知道你的 Solution
是什么类型的对象,但如果它是一个列表子类,你可以使用 Solution[:]
来复制它。或者它可能有一个 .copy()
方法,或者你可以使用 copy
模块。例如:
from copy import copy
# ...
bestsolution = copy(Solution)
copy.copy()
是一个 浅拷贝, 意味着它创建了一个新的 top-level 对象,但在其中放置了对与原始对象相同的对象的引用目的。如果这不完全有效,请尝试 copy.deepcopy()
,它还会复制包含的对象以及它们包含的任何对象,依此类推。