我同意脚注将其减少到了四种方式,而非两种。
在下面的代码中,您可以传递一个排列p
,它将执行3-opt中的四种可能之一。如果您还传递 broad=False
,则允许使用任何8个(包括身份)之一。
但是,我真的很希望对此代码进行审查,或者提供任何其他在线实现的链接。
请注意,此代码不强制执行我们剪切的边最初是不连续的。应该吗?
还要注意,这仅执行移动,而不执行尝试所有移动并选择最佳移动的完整程序。
def three_opt(p, broad=False):
"""In the broad sense, 3-opt means choosing any three edges ab, cd
and ef and chopping them, and then reconnecting (such that the
result is still a complete tour). There are eight ways of doing
it. One is the identity, 3 are 2-opt moves (because either ab, cd,
or ef is reconnected), and 4 are 3-opt moves (in the narrower
sense)."""
n = len(p)
a, c, e = random.sample(range(n+1), 3)
a, c, e = sorted([a, c, e])
b, d, f = a+1, c+1, e+1
if broad == True:
which = random.randint(0, 7)
else:
which = random.choice([3, 4, 5, 6])
if which == 0:
sol = p[:a+1] + p[b:c+1] + p[d:e+1] + p[f:]
elif which == 1:
sol = p[:a+1] + p[b:c+1] + p[e:d-1:-1] + p[f:]
elif which == 2:
sol = p[:a+1] + p[c:b-1:-1] + p[d:e+1] + p[f:]
elif which == 3:
sol = p[:a+1] + p[c:b-1:-1] + p[e:d-1:-1] + p[f:]
elif which == 4:
sol = p[:a+1] + p[d:e+1] + p[b:c+1] + p[f:]
elif which == 5:
sol = p[:a+1] + p[d:e+1] + p[c:b-1:-1] + p[f:]
elif which == 6:
sol = p[:a+1] + p[e:d-1:-1] + p[b:c+1] + p[f:]
elif which == 7:
sol = p[:a+1] + p[e:d-1:-1] + p[c:b-1:-1] + p[f:]
return sol