此算法能稳定求出柏林52城问题最优解7540.23(整数时为7538),比传统旅行商问题的算法7544.37还优

import math, time, random

from itertools import permutations

def rot(m, k):

mlen = len(m)

if k == 0: return m

return [[m[(i-k)%mlen][(j-k)%mlen] for j in range(mlen)] for i in range(mlen)]

def cs(m, ker):

ml, kl = len(m), len(ker)

res = 0

for i in range(ml - kl + 1):

for ki in range(kl):

res += m[i+ki][i+ki] * ker[ki][ki]

return res

def tsp(b52, s, e, k):

st = time.time()

n = len(b52)

d = [[0]*n for _ in range(n)]

for i in range(n):

x1, y1 = b52[i]

for j in range(i+1, n):

x2, y2 = b52[j]

dist = int(math.hypot(x1-x2, y1-y2))

d[i][j] = d[j][i] = dist

sidx = []

for i in range(n):

r = [(d[i][j], j) for j in range(n) if j != i]

r.sort()

sidx.append([idx for _, idx in r])

wm = []

for c in range(n):

o = sidx[c]

m = n-1

mat = [[0]*m for _ in range(m)]

for i in range(m):

for j in range(m):

if i != j: mat[i][j] = 1 if o[i] > o[j] else 0

wm.append(mat)

ce = [[set() for _ in range(n)] for __ in range(n)]

cf = [

\[0.5, -0.5\], \[-0.5, 0.5\]

] + [

\[0.5, -0.5, 0.5\], \[-0.5, 0.5, -0.5\], \[0.5, -0.5, 0.5\]

]

for fl in cf:

ns = []

for c in range(n):

mat = wm[c]

sc = [(cs(rot(mat, r), fl), r) for r in range(n-1)]

sc.sort(reverse=True)

ns.append(sc[:k])

for i in range(n):

for sc, r in ns[i]:

j = sidx[i][r]

ce[i][j].add(r)

if len(ce[i][j]) > k:

ce[i][j] = set(list(ce[i][j])[:k])

ec = [[[] for _ in range(n)] for __ in range(n)]

for i in range(n):

if i != s:

for j in range(n):

if i != j and ce[i][j]:

for r in sorted(list(ce[i][j]))[:k]:

ec[i][j].append(sidx[i][r])

p = [s]

v = [False]*n

v[s] = True

for _ in range(n-1):

u = p[-1]

nn = [vb for vl in ec[u] for vb in vl if vb and not v[vb]]

if not nn:

nn = [vb for vb in range(n) if not v[vb]]

p.append(nn[0])

v[p[-1]] = True

p.append(e)

def cpd(pth):

return sum(d[pth[i]][pth[i+1]] for i in range(len(pth)-1))

bd = cpd(p)

imp = True

mx = 1000

cnt = 0

while imp and cnt < mx:

imp = False

cnt += 1

for i in range(1, len(p)-2):

for j in range(i+1, len(p)-1):

dt = d[p[i-1]][p[j]] + d[p[i]][p[j+1]] - d[p[i-1]][p[i]] - d[p[j]][p[j+1]]

if dt < 0:

p[i:j+1] = p[i:j+1][::-1]

bd += dt

imp = True

return bd, p, time.time()-st,n

def c(p, e, D):

return sum(D[p[i]][p[i+1]] for i in range(len(p)-1)) + D[p[-1]][e]

def g(k, ei):

el, ci = len(ei), 0

eg = {u: [] for u in range(k)}

for (u, v), i in ei.items():

eg[u].append(i)

ud = set()

for ids in eg.values():

for i in ids:

while True:

pb = (i << 1) | random.getrandbits(1)

if pb not in ud:

ud.add(pb)

ci |= (pb & 1) << i

break

if k >= 2:

u1, u2 = random.sample(range(k), 2)

df = len(eg[u1]) - len(eg[u2])

if abs(df) <= math.isqrt(k):

elc = int(abs(math.sin(k) * df))

if elc > 0:

src = u2 if df > 0 else u1

ai = random.sample(eg[src], min(elc, len(eg[src])))

ci |= sum(1 << i for i in ai) if df > 0 else ~sum(1 << i for i in ai)

ec = {}

ci %= 1 << el

for (u, v), i in ei.items():

ec[(u, v)] = ec[(v, u)] = (ci >> i) & 1

return ec

def o(p, D):

imp = True

while imp:

imp = False

for i in range(1, len(p) - 2):

for k in range(i + 2, len(p)):

if D[p[i-1]][p[i]] + D[p[k-1]][p[k]] > D[p[i-1]][p[k-1]] + D[p[i]][p[k]]:

p[i:k] = p[i:k][::-1]

imp = True

return p

berlin52=[(565.0,575.0),(25.0,185.0),(345.0,750.0),(945.0,685.0),(845.0,655.0),(880.0,660.0),(25.0,230.0),(525.0,1000.0),(580.0,1175.0),(650.0,1130.0),(1605.0,620.0),(1220.0,580.0),(1465.0,200.0),(1530.0,5.0),(845.0,680.0),(725.0,370.0),(145.0,665.0),(415.0,635.0),(510.0,875.0),(560.0,365.0),(300.0,465.0),(520.0,585.0),(480.0,415.0),(835.0,625.0),(975.0,580.0),(1215.0,245.0),(1320.0,315.0),(1250.0,400.0),(660.0,180.0),(410.0,250.0),(420.0,555.0),(575.0,665.0),(1150.0,1160.0),(700.0,580.0),(685.0,595.0),(685.0,610.0),(770.0,610.0),(795.0,645.0),(720.0,635.0),(760.0,650.0),(475.0,960.0),(95.0,260.0),(875.0,920.0),(700.0,500.0),(555.0,815.0),(830.0,485.0),(1170.0,65.0),(830.0,610.0),(605.0,625.0),(595.0,360.0),(1340.0,725.0),(1740.0,245.0)]

print("TSP问题求解 - 柏林52个城市")

print("正在计算基础解...")

s=0

se=0

base_dist, base_path, base_time,n = tsp(berlin52, s, se, 1000)

d = [[0]*n for _ in range(n)]

for i in range(n):

x1, y1 = berlin52[i]

for j in range(i+1, n):

x2, y2 = berlin52[j]

d[i][j] = d[j][i] = ((x1 - x2)**2 + (y1 - y2)**2)**0.5

print(f"基础解距离: {base_dist:.2f}, 耗时: {base_time:.4f}s")

print(f"基础路径: {base_path}")

st = time.time()

dt0 = sorted((d[i][0], i) for i in range(1, n))

df0 = sorted((d[0][i], i) for i in range(1, n))

rt0 = {idx: r+1 for r, (_, idx) in enumerate(dt0)}

rf0 = {idx: r+1 for r, (_, idx) in enumerate(df0)}

vn = []

for i in range(1, n):

a, b = rt0[i], rf0[i]

fd = False

for m in range(1, b):

for t in range(1, 3):

if (m * (a**t)) % b == 0:

vn.append(i)

fd = True

break

if fd:break

vn = vn if vn else list(range(1, n))

bp = base_path

bd = base_dist

ei = {}

idx = 0

for i in range(n):

for k in range(i+1, n):

ei[(i, k)] = idx

idx += 1

opt2_cnt = 0

for _ in range(50):

random.seed()

for _ in range(50):

ec = g(n, ei)

random.shuffle(vn)

p = [s] + vn + [se]

gss = [[] for _ in range(2)]

for nd in vn:gss[ec.get((nd % n, (nd + 1) % n), 0)].append(nd)

np = [s]

for gs in gss:

if gs:np.extend(random.sample(gs, len(gs)))

np.append(se)

cd = c(np, se, d)

if cd < bd * 4:

np = o(np, d)

opt2_cnt += 1

cd = c(np, se, d)

if cd < bd:

bd = cd

bp = np

print(f"\n优化后结果:")

print(f"{n}节点 起点:{s} 终点:{se}")

print(f"最优路径: {bp}")

print(f"最优距离: {bd}")

print(f"总时间: {time.time()-st:.2f}s")

print(f"opt2调用次数: {opt2_cnt}")

相关推荐
元亓亓亓2 小时前
LeetCode热题100--139. 单词拆分--中等
算法·leetcode·职场和发展
Eloudy2 小时前
通过示例看 C++ 函数对象、仿函数、operator( )
开发语言·c++·算法
superman超哥2 小时前
仓颉高性能实践:内存布局优化技巧深度解析
c语言·开发语言·c++·python·仓颉
释怀°Believe2 小时前
Daily算法刷题【面试经典150题-6️⃣kadane/】
算法·面试·职场和发展
薯片锅巴2 小时前
代码随想录算法训练营第四十四天:孤岛计数(广搜版),孤岛计数(深搜版),最大岛屿的面积
算法
Nan_Shu_6142 小时前
学习:TypeScript (1)
前端·javascript·学习·typescript
海清河晏1112 小时前
Linux进阶篇:深入理解线程
java·jvm·算法
沛沛老爹2 小时前
Web开发者快速上手AI Agent:基于Advanced-RAG的提示词应用
前端·人工智能·langchain·llm·rag·web转型·advanced-rag
小二·2 小时前
会议精灵:用ModelEngine构建智能办公助手实战记录
开发语言·python