计算网格上两点之间恰好有“n”个节点的最短路径

2024-04-16

我在网格上定义了以下 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 with 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 and end精确长度n, with n赋予函数的参数。

备注:如果我更改使用的指标(V[e]-V[cc])**2 to V[e]-V[cc],这会增加负距离,当它按预期经过局部最小值时,我得到的图看起来更好:


由于我想获得对势中的盆地进行采样的合理路径,因此我编写了以下函数。为了完整起见,我记得dijkstra我写的函数:

%pylab
def dijkstra(V, start):
    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 = start # 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] ]
        t.ntative_distance = asarray([V[e]-V[cc] 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

start, end = unravel_index(V.argmin(), V.shape), (40,4)
D, P = dijkstra(V, start)

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)

path = shortestPath(start, end, P)

其中给出了以下情节:

contourf(V, 40)
plot(path[:,1], path[:,0], 'r.-')
colorbar()

然后,背后的基本思想extend_path功能是扩展通过获取路径中使势能最小化的节点的邻居而获得的最短路径。集合保存在扩展过程中已经访问过的单元格的记录。

def get_neighbors(cc, V, visited_nodes):
    connectivity = [(i,j) for i in [-1, 0, 1] for j in [-1, 0, 1] if (not (i == j == 0))]
    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 e not in visited_nodes ]
    return neighbors

def extend_path(V, path, n):
    """
    Extend the given path with n steps
    """
    path = [tuple(e) for e in path]
    visited_nodes = set()
    for _ in range(n):
        visited_nodes.update(path)
        dist_min = numpy.inf
        for i_cc, cc in enumerate(path[:-1]):
            neighbors = get_neighbors(cc, V, visited_nodes)
            next_step = path[i_cc+1]
            next_neighbors = get_neighbors(next_step, V, visited_nodes)
            join_neighbors = list(set(neighbors) & set(next_neighbors))
            if len(join_neighbors) > 0:
                tentative_distance = [ V[e] for e in join_neighbors ]
                argmin_dist = argmin(tentative_distance)
                if tentative_distance[argmin_dist] < dist_min:
                    dist_min, new_step, new_step_index  = tentative_distance[argmin_dist], join_neighbors[argmin_dist], i_cc+1
        path.insert(new_step_index, new_step)
    return path

下面是我将最短路径延长 250 步得到的结果:

path_ext = extend_path(V, path, 250)
print len(path), len(path_ext)
path_ext = numpy.asarray(path_ext)
contourf(V, 40)
plot(path[:,1], path[:,0], 'w.-')
plot(path_ext[:,1], path_ext[:,0], 'r.-')
colorbar()

正如预期的那样,当我增加时,我首先开始对更深的盆地进行采样n,如下所示:

rcParams['figure.figsize'] = 14,8
for i_plot, n in enumerate(range(0,250,42)):
    path_ext = numpy.asarray(extend_path(V, path, n))
    subplot('23%d'%(i_plot+1))
    contourf(V, 40)
    plot(path_ext[:,1], path_ext[:,0], 'r.-')
    title('%d path steps'%len(path_ext))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

计算网格上两点之间恰好有“n”个节点的最短路径 的相关文章

随机推荐

  • 如何将 YAML 转换为 JSON? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找在 YAML 文件和 JSON 之间进行转换 这真的很难找到任何信息 如果不需要 Json NET 的功能 也可以直接使用 Se
  • 需要:Rikulo UXL 示例

    我想让一些 UXL 与 Dart 编辑器一起使用 我担心我感觉示例代码用户体验实验室概述 http docs rikulo org ui latest UXL Fundamentals UXL Overview html要么已经过时 要么缺
  • 龙卷风错误处理

    我希望能够处理输入错误 URL 时显示的更好的错误E g localhost 8000 AFDADSFDKFADS 我收到一条丑陋的 python 回溯消息 因为抛出了一个ornado web HTTPError 异常 我知道我可以使用正则
  • iOS 9+ 通用链接不适用于 Google 应用

    我工作的公司让我问以下问题 当在其他应用程序 原生 Apple 应用程序 Slack 等 中点击通用链接时 我们的应用程序会打开 但如果在任何 Google 应用程序 环聊 收件箱等 中点击相同链接 则不会直接打开通用链接通过我们的应用程序
  • 在 Visual Studio 2017 中删除垂直虚线缩进线

    我刚刚安装了 Visual Studio 2017 代码编辑器中出现了奇怪的垂直缩进标记 我怎样才能删除它们 附 我禁用了所有扩展 但这没有帮助 下面有一个选项Tools Options Text Editor called Show st
  • mvc3 路由设置为 id, id2 id3

    我有以下区域路线设置 context MapRoute Admin default3 Admin controller action id id2 id3 new action Index context MapRoute Admin de
  • capistrano,:db 角色,它的用途是什么?

    据我所知 卡皮斯特拉诺 db角色仅用于运行迁移 因此 在大多数情况下 它可能不应该实际上是运行数据库的服务器 为什么那里会有 ruby rails 堆栈 或者允许 ssh 登录 它只是您想要实际执行 Rails 迁移的任何服务器 并且只有标
  • 实现移动运动体

    Project 我正在制作一个简单的项目 其中我希望能够制作一个运动体并将其从 x 点移动到 y 点 创建运动体 似乎没有太多直接内容 我一直在关注一些关于实现运动体的不同教程 因为我找不到指定如何正确执行此操作的教程 Problem 这似
  • 如何使用数据列表比较并返回数据

    我是 Haskell 的新手 我正在努力寻找一种使用类成员变量来返回我正在寻找的成员变量的方法 我有这个数据 data Place Place name String north Float east Float rainfall Int
  • 奥尔森 时区 到 windows

    我需要在 Windows 中从奥尔森时区转换时区 使用PHP 我找到了这个http unicode org repos cldr trunk common supplemental windowsZones xml http unicode
  • 用于搜索 Google 云端硬盘的 Google Apps 脚本

    是否可以使用 Google Apps 脚本在 Google 云端硬盘中搜索文档和文件夹 谷歌已经取消了自己的文档 驱动器搜索小工具 因为它似乎依赖于 iGoogle 谷歌企业支持也承认了这一点 谢谢 我想你正在寻找搜索文件 https de
  • Unity使用Invoke在另一个脚本上调用方法

    我有两个脚本 其中一个重新启动场景 另一个是倒计时器 而不是在第一个脚本中调用重新启动场景方法 但是 它没有重新启动 即使没有错误 我也不明白为什么 重新启动场景的第一个脚本 using UnityEngine using UnityEng
  • 在编译时通过 constexpr 或模板函数获取多维 std::array 的大小

    我用的是三维std array 因为大小在编译时已知 但是 我注意到 size 函数不是静态的 因此 constexpr 模板函数无法访问 我已经找到了下面的演示示例 它估计一维的大小std array 然而 这不适用于二维或更多维度 有没
  • C# 中的并发集合

    我正在寻找一种方法来获得并发收集 in C 或者至少是一个支持的集合并发枚举器 现在我得到了InvalidOperationException当我正在迭代的集合发生变化时 我可以深度复制该集合并使用私人副本 但我想知道是否有更好的方法 代码
  • DisplayMemberPath 在 WPF 中不起作用

    我要显示CustomerList CustomerName财产项目ListBox using ItemsSource DisplayMemberPath仅限财产 但它不起作用 我不想使用DataContext或我的问题中的任何其他绑定 请帮
  • 实体框架 6 和集合

    我正在开发我的第一个实体框架应用程序 我正在使用 EF 版本 6 来自 Nuget 和 net 4 0 然而 我在一些对我来说似乎应该非常简单的事情上遇到了一些困难 我在互联网上发现了很多相互矛盾的建议和解决方案 但是在花了几天时间尝试解决
  • Firebase - Firestore - 使用 collection.add() 获取密钥

    我在使用 Firebase 的新 Firestore 时遇到问题 情况 我有一个collection room 我创建房间collection room add room 我正在尝试做的事情 我需要更新一个房间 为此 我使用 collect
  • 示例 urllib3 和 python 中的线程

    我正在尝试在简单线程中使用 urllib3 来获取多个 wiki 页面 该脚本将 为每个线程创建 1 个连接 我不明白为什么 并永远挂起 urllib3 和线程的任何提示 建议或简单示例 import threadpool from url
  • 将多行转换为一行,并以逗号作为分隔符[重复]

    这个问题在这里已经有答案了 如果我发出SELECT username FROM Users我得到这个结果 username Paul John Mary 但我真正需要的是one所有值均以逗号分隔的行 如下所示 Paul John Mary
  • 计算网格上两点之间恰好有“n”个节点的最短路径

    我在网格上定义了以下 3D 表面 pylab inline def muller potential x y use numpy False Muller potential Parameters x float np ndarray or