【发布时间】:2023-04-01 06:23:01
【问题描述】:
我在网格上定义了以下 3D 表面:
%pylab inline
def muller_potential(x, y, use_numpy=False):
"""Muller potential
Parameters
----------
x : {float, np.ndarray, or theano symbolic variable}
X coordinate. If you supply an array, x and y need to be the same shape,
and the potential will be calculated at each (x,y pair)
y : {float, np.ndarray, or theano symbolic variable}
Y coordinate. If you supply an array, x and y need to be the same shape,
and the potential will be calculated at each (x,y pair)
Returns
-------
potential : {float, np.ndarray, or theano symbolic variable}
Potential energy. Will be the same shape as the inputs, x and y.
Reference
---------
Code adapted from https://cims.nyu.edu/~eve2/ztsMueller.m
"""
aa = [-1, -1, -6.5, 0.7]
bb = [0, 0, 11, 0.6]
cc = [-10, -10, -6.5, 0.7]
AA = [-200, -100, -170, 15]
XX = [1, 0, -0.5, -1]
YY = [0, 0.5, 1.5, 1]
# use symbolic algebra if you supply symbolic quantities
exp = np.exp
value = 0
for j in range(0, 4):
if use_numpy:
value += AA[j] * numpy.exp(aa[j] * (x - XX[j])**2 + bb[j] * (x - XX[j]) * (y - YY[j]) + cc[j] * (y - YY[j])**2)
else: # use sympy
value += AA[j] * sympy.exp(aa[j] * (x - XX[j])**2 + bb[j] * (x - XX[j]) * (y - YY[j]) + cc[j] * (y - YY[j])**2)
return value
这给出了以下情节:
minx=-1.5
maxx=1.2
miny=-0.2
maxy=2
ax=None
grid_width = max(maxx-minx, maxy-miny) / 50.0
xx, yy = np.mgrid[minx : maxx : grid_width, miny : maxy : grid_width]
V = muller_potential(xx, yy, use_numpy=True)
V = ma.masked_array(V, V>200)
contourf(V, 40)
colorbar();
我编写了以下代码来定义该网格上两点之间的最短路径。我在网格的两个相邻点之间使用的度量由(V[e]-V[cc])**2 给出,cc 是当前单元格,e 是相邻单元格之一。邻居被定义为完全连通性:包括对角线的所有直接邻居。
def dijkstra(V):
mask = V.mask
visit_mask = mask.copy() # mask visited cells
m = numpy.ones_like(V) * numpy.inf
connectivity = [(i,j) for i in [-1, 0, 1] for j in [-1, 0, 1] if (not (i == j == 0))]
cc = unravel_index(V.argmin(), m.shape) # current_cell
m[cc] = 0
P = {} # dictionary of predecessors
#while (~visit_mask).sum() > 0:
for _ in range(V.size):
#print cc
neighbors = [tuple(e) for e in asarray(cc) - connectivity
if e[0] > 0 and e[1] > 0 and e[0] < V.shape[0] and e[1] < V.shape[1]]
neighbors = [ e for e in neighbors if not visit_mask[e] ]
tentative_distance = [(V[e]-V[cc])**2 for e in neighbors]
for i,e in enumerate(neighbors):
d = tentative_distance[i] + m[cc]
if d < m[e]:
m[e] = d
P[e] = cc
visit_mask[cc] = True
m_mask = ma.masked_array(m, visit_mask)
cc = unravel_index(m_mask.argmin(), m.shape)
return m, P
def shortestPath(start, end, P):
Path = []
step = end
while 1:
Path.append(step)
if step == start: break
step = P[step]
Path.reverse()
return asarray(Path)
D, P = dijkstra(V)
path = shortestPath(unravel_index(V.argmin(), V.shape), (40,4), P)
结果如下:
contourf(V, 40)
plot(path[:,1], path[:,0], 'r.-')
路径长度为112:
print path.shape[0]
112
我想知道是否可以计算start 和end 之间精确长度n 之间的最短路径,并为函数提供一个参数n。
备注:如果我将使用的度量从 (V[e]-V[cc])**2 更改为 V[e]-V[cc],这会增加负距离,我会得到该图,因为它按预期通过局部最小值时看起来更好:
【问题讨论】:
-
我猜你问的是traveling purchaser problem 的变体NP-complete。因此,没有算法可以解决多项式时间。我认为各种solutions of similar problem 对你来说会很有趣。
-
@Vadim Shkaberda:是的,这是一个类似的问题。我将研究提出的各种解决方案。但是,我认为与旅行商问题 (TSP) 的一个区别是我不想访问所有节点,而只想访问 $n$ 个节点。
-
您不能尝试为每一步添加与
start/end的最大距离的强约束,换句话说,声明一个您可以在每一步且不超过步数限制的区域。如果您要访问的节点数量与start/end之间的直接距离相比不是很大,则可以成功。显然,你应该放弃visit_mask。 -
和 TSP 问题还是没有太大区别。如果您在
start和end之间有直接距离d并且您想找到s步骤的最小解决方案并且您有8 个方向可以走每一步(除了第一个),您必须检查所有路径对于第一个(s-d)/2步骤。所以,你需要检查(8^((s-d)/2) + k)路径和蛮力算法是O(8^s)。
标签: python numpy shortest-path