Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Python解决图形问题_Python_Algorithm_Graph_Path_Networkx - Fatal编程技术网

用Python解决图形问题

用Python解决图形问题,python,algorithm,graph,path,networkx,Python,Algorithm,Graph,Path,Networkx,我有一种情况,我想用Python来解决这个问题,但不幸的是,我没有足够的图形知识。我发现一个库似乎非常适合这个相对简单的任务,networkx,但我在做我想要的事情时遇到了问题,这应该是相当简单的 我有一个节点列表,可以有不同的类型,和两个“类”的邻居,向上和向下。任务是查找两个目标节点之间的路径,同时考虑一些约束: 只能遍历特定类型的节点,即,如果起始节点的类型为x,则路径中的任何节点必须来自另一组路径y或z 如果节点具有类型y,则只能通过一次 如果节点的类型为z,则可以通过两次 如果访问类

我有一种情况,我想用Python来解决这个问题,但不幸的是,我没有足够的图形知识。我发现一个库似乎非常适合这个相对简单的任务,
networkx
,但我在做我想要的事情时遇到了问题,这应该是相当简单的

我有一个节点列表,可以有不同的类型,和两个“类”的邻居,向上和向下。任务是查找两个目标节点之间的路径,同时考虑一些约束:

  • 只能遍历特定类型的节点,即,如果起始节点的类型为x,则路径中的任何节点必须来自另一组路径y或z
  • 如果节点具有类型y,则只能通过一次
  • 如果节点的类型为z,则可以通过两次
  • 如果访问类型为z的节点,则出口必须来自不同类别的邻居,即如果从上访问,则出口必须从下
所以,我尝试了一些实验,但正如我所说的,我一直在努力。首先,我不确定这实际上代表什么类型的图形?这不是方向性的,因为从节点1到节点2,或者从节点2到节点1都无关紧要(除了最后一个场景中的,所以这会让事情变得有点复杂…)。这意味着我不能仅仅创建一个简单的多向图,因为我必须记住这个约束。其次,我必须遍历这些节点,但指定只有特定类型的节点才能用于path。另外,如果发生最后一个场景,我必须记住入口和出口类/方向,这使它处于某种定向状态

以下是一些示例样机代码:

import networkx as nx

G=nx.DiGraph()
G.add_node(1, type=1)
G.add_node(2, type=2)
G.add_node(3, type=3)
G.add_edge(1,2, side="up")
G.add_edge(1,3, side="up")
G.add_edge(2,1, side="down")
G.add_edge(2,3, side="down")
for path in nx.all_simple_paths(G,1,3):
    print path
输出相当不错,但我需要这些约束。那么,您是否有一些建议,我如何实现这些,或者给我一些关于理解这类问题的更多指导,或者为这类问题提出不同的方法或库?也许一个简单的基于字典的算法可以满足这个需求


谢谢

我认为最好的方法是计算源S和每个其他节点之间长度最多为k的所有有效路径,然后使用该信息计算长度最多为k+1的所有有效路径。然后重复这个过程,直到得到一个固定点,在这个固定点上没有路径被修改

实际上,这意味着您应该在每个节点上设置路径列表。在每一步中,您依次选取每个节点U,并查看在上一步中终止于U的某个相邻V的路径。如果这些路径中的任何一条可以扩展为U的新的、不同的路径,请扩展它并将其添加到U的列表中

如果在执行步骤时未找到新路径,则为终止状态。然后可以检查目标节点T处的路径列表

伪代码(采用非常松散的C#形式):

var path=graph.nodes.ToDictionary(node=>node,node=>newlist())
路径[S].Add(新列表{S})//将启动我们的普通路径。
bool notAFixedPoint=true;
while(非固定点)
{
notAFixedPoint=false//假设我们不会找到任何新路径。
foreach(图中的var节点)
{
var pathsToNode=路径[节点]
foreach(节点中的var邻居。邻居)
{
var pathsToNeighbour=路径[邻居]
//ExtendPaths是所有关于如何识别有效路径的逻辑所在。
var newPathsToNode=extendPath(pathsToNeighbour,节点)
//这里使用“除外”是为了说明目的,它实际上不起作用,
//因为大多数语言中的集合都是按引用而不是按值进行比较的。
if(newPathsToNode.Except(pathsToNode.IsNotEmpty())
{
//我们找到了一些新的路径,所以还不能终止。
notAFixedPoint=true
pathsToNode.AddMany(newPathsToNode)
}
}
}
}
返回路径[T]

在我看来,这似乎是一个优化问题——请查阅《旅行推销员》中的一个经典示例,它与您想要做的有点接近


我很幸运地使用“模拟退火”来解决优化问题,但您也可以看看“遗传算法”。

如果您以不同的方式构造图形,您可能可以使用all_simple_path()函数来解决您的问题。简单路径是那些没有重复节点的路径。因此,对于您的约束,这里有一些构建图的建议,这样您就可以不经修改地运行该算法

  • 只能遍历特定类型的节点,即,如果起始节点的类型为x,则路径中的任何节点必须来自另一组路径y或z
给定一个起始节点n,请在找到路径之前删除该类型的所有其他节点

  • 如果节点具有类型y,则只能通过一次
这是简单路径的定义,因此它会自动满足

  • 如果节点的类型为z,则可以通过两次
对于类型为z的每个节点n,添加一个新节点n2,该节点n2的边与指向n和从n开始的节点的边相同

  • 如果访问类型为z的节点,则出口必须来自不同类别的邻居,即如果从上访问,则出口必须从下

如果边缘按照您的建议定向,那么如果您确保到z的边缘都是同一方向的话,就可以满足这一要求-例如,向内表示向上,向外表示向下…

很难理解您想要什么。你能为这个问题提供一些背景吗?不同类型的节点代表什么?您想要两个节点之间的所有路径,还是只需要最短的路径?它必须有多快?(“所有路径”可能会在打印输出时将其推到指数时间)让我们假设节点代表城市或车站,某种具有特定“类型”的位置,表示
var paths = graph.nodes.ToDictionary(node => node, node => new List<List<node>>())
paths[S].Add(new List<node> {S}) // The trivial path that'll start us off.


bool notAFixedPoint = true;

while (notAFixedPoint)
{
    notAFixedPoint = false // Assume we're not gonna find any new paths.

    foreach (var node in graph)
    {
        var pathsToNode = paths[node]

        foreach (var neighbour in node.Neighbours)
        {
            var pathsToNeighbour = paths[neighbour]

            // ExtendPaths is where all the logic about how to recognise a valid path goes.
            var newPathsToNode = ExtendPaths(pathsToNeighbour, node)

            // The use of "Except" here is for expository purposes. It wouldn't actually work,
            // because collections in most languages are compared by reference rather than by value.
            if (newPathsToNode.Except(pathsToNode).IsNotEmpty())
            {
                // We've found some new paths, so we can't terminate yet.
                notAFixedPoint = true 

                pathsToNode.AddMany(newPathsToNode)
            }
        }
    }
}

return paths[T]