python - 从距原点给定距离的图中查找路径的所有组合

标签 python algorithm graph-algorithm

我试图从一个与原点有给定距离的图中找到所有路径的组合。
事实上,魔兽世界(军团)的新扩展将把神器系统引入游戏。
这是一个你可以升级的功能,每个级别给你一个等级,你可以花一个点在一棵树的每个等级。
你可以在wowhead上找到每个工件的计算器,我将使用这个例子:http://legion.wowhead.com/artifact-calc/rogue/subtlety/
基本上,该计划的目标是:
“我给出一个等级,比如说7,它返回给我从图中得到的每一个路径组合,我必须花费7个点才能到达那里(即,7个唯一节点的列表)”。
当我看到计算器时,我认为把它转换成一个图形是可以解决的,所以我做了一个来帮助我通过:
Graph
在这个图上,我不得不从计算器上做一些调整,例如,每一个获得3个等级的特征都必须表示为3个相互连接的节点。
另外,对于解锁两种方法的特性,我必须将它们表示为4个节点,以“模拟”3个节点的需求。(但之后我们会看到这仍然是一个问题,它并没有真正解决问题)
然后,我试图找到一个很好的方法列出每一种可能性,所以我在网上做了很多研究,以找到处理我的问题的最佳方法。
我首先尝试使用广度优先搜索来解决这个问题,但是与每个节点的起点保持距离并没有多大帮助。
然后我试着用详尽的搜索。
我目前正在使用代码的一个改编版本:codereview@stackechange上的“从给定图形中查找所有路径”(不能发布超过2个链接)

def paths(graph, v, lmax):
    """Generate the maximal cycle-free paths with a given maximum length lmax in 
    graph starting at v. Graph must be a mapping from vertices to collections of
    neighbouring vertices.

    >>> g = {1: [2, 3], 2: [3, 4], 3: [1], 4: []}
    >>> sorted(paths(g, 1, 3))
    [[1, 2, 3], [1, 2, 4], [1, 3]]
    >>> sorted(paths(g, 3, 4))
    [[3, 1, 2, 4]]

    Credit to Gareth Rees from StackExchange for the original code.
    """
    path = [v]                  # path traversed so far
    seen = {v}                  # set of vertices in path
    def search():
        dead_end = True
        if len(seen) < lmax:
            for neighbour in graph[path[-1]]:
                if neighbour not in seen:
                    dead_end = False
                    seen.add(neighbour)
                    path.append(neighbour)
                    yield from search()
                    path.pop()
                    seen.remove(neighbour)
        if dead_end:
            yield list(path)
    yield from search()

然后我创建了一个函数来对结果进行排序,并只显示具有所需长度的结果。
def artifact(graph, maxrank, start):
    for i in range(1, maxrank+1):
        print("---------")
        print("Rank: " + str(i))
        print("---------")
        # Get all the Paths at "i" Rank
        RawPaths = sorted(paths(g, start, i), key=len)
        # Remove paths that doesn't satisfact our rank requirement and sort it
        ValidPaths = [sorted(j) for j in RawPaths if len(j) == i]
        # Remove duplicates
        UniquePaths = sorted([list(j) for j in set(map(tuple, ValidPaths))])
        # Display the Paths
        for j in range(len(UniquePaths)):
            PathString = "";
            for k in range(len(UniquePaths[j])):
                PathString += str(UniquePaths[j][k]) + " "
            print(PathString)
        print("")

从那里,我从图中构建了一部分节点的相邻节点(邻居)列表我不能发布超过2个链接,但是子图结束于之前链接的图的8/7/32/31节点。
g = {
  1: [2, 38],
  2: [1, 3],
  3: [2, 4],
  4: [3, 5],
  5: [4, 6],
  6: [5, 7, 8],
  7: [6],
  8: [6],
 31: [33],
 32: [33],
 33: [31, 32, 34],
 34: [33, 35],
 35: [34, 36],
 36: [35, 37],
 37: [36, 38],
 38: [1, 37]
}

然后我调用函数:
artifact(g, 8, 1)

但使用这个列表,我面临一个重大问题事实上,算法一直走到最后,但它没有做任何回溯,以达到想要的排名(即,经过一路1-38-37-36-35-34-33-31,它不会回到2-3-如果我有10分的话。
我可以通过在38,37,…中添加一个作为邻居2来求解这个子图。分支或38到2,3,…分支。
所以我的名单变成了:
g = {
  1: [2, 38],
  2: [1, 3, 38],
  3: [2, 4, 38],
  4: [3, 5, 38],
  5: [4, 6, 38],
  6: [5, 7, 8, 38],
  7: [6, 38],
  8: [6, 38],
 31: [2, 33],
 32: [2, 33],
 33: [2, 31, 32, 34],
 34: [2, 33, 35],
 35: [2, 34, 36],
 36: [2, 35, 37],
 37: [2, 36, 38],
 38: [1, 2, 37]
}

然后我就可以得到我想要的一切。
现在我试图将我的推理扩展到整个图表。但我失败的原因主要有两个:
-当我朝一个方向走的时候,用3个等级来表示特征的4个节点是有效的,但是如果我已经填满了整个分支,然后我试着回去,我计算第4个节点。(我仍然可以在artifact函数中创建一些东西来删除第4个节点,但我认为这不是处理它的好方法,应该找到一个聪明的方法来处理它。
-我用来链接前两个分支的技巧并不直接适用于整个图。例如,按照我所做的,我将在29个邻居中添加32个,因为当我从35岁开始时,从29岁就可以访问32个邻居但是,如果我来自28岁,并且没有在路径中添加27岁,那么通常从29岁就无法访问32岁。
然后我的路就失效了。
我不确定我能不能这样解决,我希望你能帮助我。而且,我觉得我的回溯搜索方式并不完美。
我还认为:
一到分支机构的尽头,我就会回到以前的分离状态,从那里开始探索。但既然节点已经被探索过了,就不要走另一条路而停在那里。
最后,我要用其他方法来处理我的问题,我不想特别用图来解决它。
也许有另一种方法可以有效地解决这个问题(比如一步一步地构建这个图,在节点被解锁的情况下,有一些列组需要花费并逐渐使用)。是的。
提前感谢你的帮助,并为我的英语错误道歉,我是法国人:)

最佳答案

IIUC,你有一个未加权的有向图G,你正在寻找G的所有子图H的集合,这些子图具有以下2个属性:
从给定的原点顶点到h中的每个顶点都有一条路径(这意味着h本身至少是弱连接的)
边的总数(或权重)正好是给定的k。
这里有一个简单的算法,你可以维护所有子图的集合,它们的总长度正好是i,在每次迭代中,把它们增长到所有子图的集合,它们的总长度正好是i+1:
从集合s中的一个子图开始,仅由原点顶点组成。
对于0到k的i:
不变量:S包含G的所有子图,这些子图与原点弱连接,并且总长度恰好为i。
设置S'={}。
对于S中的每个子图H:
对于每个边(u,v),u在v(h)中,v在v(h)外:
形成一个子图h'由h加上边(u,v)组成。
将h'添加到集合s'。(如果这个图h'已经在s中,则不要执行任何操作。这种情况会经常发生。这就是为什么最好使用一个适合于自动处理这一问题的s'集合的数据结构,例如哈希表或二进制搜索树。)
设置S=S'。
当算法终止时,S将包含满足上述要求1和2的所有子图在最坏的情况下,它需要m倍于输出中不同子图的数目,其中m是图中的边的数目注意,输出中可能有大量的子图——考虑n个顶点上的完整图,注意可能的子图比n中k个项的组合要多,后者已经很大了。

关于python - 从距原点给定距离的图中查找路径的所有组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38111632/

相关文章:

python - 了解 pystache 中的 lambda

python - 从 HTML 文件中删除文本,但使用 python 保留 javascript 和结构

java - 解决相同任务的两种算法之间的显着运行时间差异

algorithm - 是否有一种算法可以在不重复的情况下在加权图中找到最佳的一对顶点?

python - 在 Python 中使用 open 函数和循环

python - 将数据帧结果值保存到字符串变量?

c++ - C++中的指针数组排序算法

java - 从多个列表中获取值的所有组合

c++ - 当我在平面上嵌入平面图时,如何找到包含预定义点的面

parsing - 用于在 Javascript 或 Jquery 中绘图的方程解析器