我正在考虑以下问题(非常粗略的描述):
假设我们有一个图,其中边被分配了一些非负成本,一个起始节点s
和一些成本常数C
。找出:
N
,可从s
到达,其中从起始节点s
到N
中任何节点的最短路径成本不大于C
e
,上面是最短路径的成本
基本上是有成本限制的Dijkstra。
我的主要问题是:图论中关于这个问题的正确术语是什么?
我一直在看“可访问性”或“可达性”,但这些似乎是错误的关键词。
最终,我正在寻找一种算法,它可以在一个(不可修改的)但相当大(可能约1亿条边)的图上高效地并行回答许多这样的查询。我想查看文献,但需要关于正确关键字的提示。
更新:我的实际问题如下。
假设我们有一个大陆大小的道路网络(建模为有向图,在边缘和节点上有一些属性,如人行道或高速公路)。边际成本是旅行时间。
我想回答如下用户查询:从某个给定位置(图节点)开始,哪些节点在1小时内可以到达?
我也想很快回答这些问题(
我认为至少应该有两种可能的优化:
我自己有一些想法,但我首先想检查一下文献,以避免重新发明轮子。
加权图中的最短路径距离给出了图的度量空间结构。在度量空间术语中,你试图找到以s为中心的半径c的闭合球。也许有一些研究将图视为计算上可处理的离散度量空间。偏心率的概念也可以发挥作用——节点的偏心率是从该点到任何其他点的最大距离。似乎你正在试图找到一个最大子图,它的性质是子图中s的偏心率以c为界。
Dijkstra的算法可以很明显地进行修改,以满足您的需求。如果Dijkstra的算法在任何时候都要在访问节点集(已知最终距离的节点)中包含一个顶点,但结果距离超过c,则丢弃该节点,而不是将其添加到访问节点列表中。这实际上会删减从s到达的节点树。应该是合理有效的。
我一直在看“可访问性”或“可达性”,但这些似乎是错误的关键词。
是的,你是对的。这些是错误的关键词。
首先,让我更准确地重新定义这个问题。给定一个图G(V, E),一个节点s和一个常数c,我们要求集合R={(n, d)|s和n之间的距离是d
这个问题是可达性问题的一个推广版本,其中c是无穷大的,考虑大型图要困难得多。
现在,作为预计算的一部分,要找到集合R,必须确定s和所有其他节点之间最短路径的长度。这是伪装的所有对最短路径(APSP)问题。
因此,第一步,预计算,是在研究库中搜索一个真正快速的APSP算法,它适合您正在处理的图形类型。该算法及其实现决定了预计算的运行时间。
第二步是从算法的结果中找到一种尽可能多、尽可能高效地存储数据的方法,因为您在这里选择的数据结构和算法将决定查询的运行时间。考虑到10亿个顶点,该算法计算的最短路径数大约为10^18(从,到,距离)个三元组。如果每个值的大小为4字节,那么如果我们将所有这些数据存储在分布式哈希表中(需要额外存储),则需要大约7 EB。在这种情况下,我们最多可以实现几毫秒的查询时间。
否则,如果无法存储所有这些数据,则必须压缩数据和/或丢弃其中一些数据。现在这是一个不同的问题。您可能希望将图划分为许多小直径的子图(直径必须通过实验确定),然后仅存储子图中心节点的最短路径信息,并且在查询时必须重新运行非常有效的实现的SSSP(单源最短路径)。还有许多其他优化技术可以轻松地跨越一本书。无论你做什么,实现
在DRAM和本地磁盘中缓存查询结果是一个好主意。如果很大比例的查询是相同的,这会有很大帮助。
关于用户数,由于图是静态的,您可以并行化所有查询。您可以利用高度并行的CPU和GPU。
您正在处理的问题的正确术语是“最短路径算法”。可达性问题(即Warshal)处理的问题是“节点a和B之间是否存在路径?”它有一个二元答案,在这种情况下你不需要权重,你只需要寻找边。但在您的情况下,您需要考虑在每种情况下从节点A到节点B所需的时间。
现在,没有“确切”适合这个问题,因为Dijktra、Floyd、BFS或DFS的一个小变化可以用来解决这个问题,但是你有一个额外的复杂性,因为图的大小,这对于理解如何构建很重要你的解决方案。使用哪种算法取决于您的时间限制和可用硬件的具体组合。
您的问题有两种算法解决方案(我假设您已经将所有边存储在某个位置,并且您可以以某种方式查询此数据库):
>
在一个理想的(想象的)世界中,你会运行弗洛伊德算法,将结果矩阵保存在像Redis这样的东西中,仅此而已,你可以在不到10毫秒的时间内服务你的请求,如果客户端数量增加,你可以添加更多Redis服务器根据需要,因为图形不太可能经常更改(因为在您的特定问题中,您有道路信息)。这个问题是解决方案的空间复杂度,最好的一点是所有的东西都是预计算的,这意味着您对请求的响应时间是最小的。为了能够实现一些变化,你需要大量的空间,即使是一个redis集群,数据库存储在磁盘上(是的,磁盘,不是内存),所有带有SSD的服务器都应该足够了,当并发客户端的数量增加时,这个选项可以很好地扩展增长和时间反应相当快。但是你是否可以使用这个解决方案取决于你的图中节点的数量:即使你需要使用每个边预先计算距离,你只需要空间来存储一个NxN的矩阵,即图中节点的数量,如果这个矩阵适合redis,然后你可以使用这个算法,预计算所有节点之间的“距离”(在你的情况下,这是成本的总和,也就是“旅行时间”)。稍后,当你收到一个请求时,你需要查询得到的矩阵来获取旅行时间小于给定值的所有节点,在redis中存储这个矩阵时,还有一个额外的优化,可以让你很快地获取节点编号使用排序集。
然后你有第二个解决方案,就是修改Dijktra,BFS或DFS,根据成本来削减搜索,仅此而已。在这种情况下,您已经放弃了Floyd,因为空间复杂度很高,这意味着您的图在节点和边上都相当大。在这种情况下,使用任何算法的变体,解决方案几乎是相同的,这使得不同之处在于您如何存储图形。所有3种算法都可以修改,以便在所需时间内高效响应,但为了支持10k客户端,用于存储图形的数据库会有所不同。这里你有另外两个选择:
希望有帮助!
我有一个场景 我想从一个特定的节点(比如ID:7)开始运行BFS 如果有无法从该节点访问的节点,我想重新启动BFS(使用任何剩余节点),直到访问图的所有顶点 到目前为止,我得到的是从节点0开始并用另一个未访问的顶点重新启动的代码(部分): 如何有效地更改此代码以满足我的要求?
我们得到了一个有序线程的二叉树。这意味着,如果一个节点没有左子节点(右子节点),左线程(右线程)将从该节点链接到其索引前一个节点(索引后一个节点)。 你能帮我找到一个节点的父节点的伪代码或算法吗?例如(见下图),给定的节点是Q,父节点必须是I。(我们应该利用给定的想法,即二进制是有序线程) TMI:我实际上需要这个伪代码/算法来创建另一个算法,它将获得二叉树的后序继承者。
我目前正在研究一个在有向图中寻找由选定节点组成的圈的问题。 对于这里描述的实例: 在节点1,2,3内有一个循环,在1,2,4内没有发现循环。我已经尝试用下面的操作来实现算法: null 但是,这个实现并不适用来自我正在使用的在线判断的所有测试数据。我发现我的算法不同于深度优先搜索,深度优先搜索使用白、灰、黑数组来存储未访问、正在访问或不需要访问的节点,我想知道这是否是导致问题的原因。 希望在您的帮
给定单链表的最后一个节点,我们如何找到头节点? 假设给定JSON: {“id”:“A”,“next”:“B”},{“id”:“B”,“next”:“C”}{“id”:“C”,“next”:“D”}{“id”:“D”,“next”:“null} 现在假设上面没有排序,我们需要算出HEAD元素“A”。
我试图想出一个密码查询,可以返回某些父母的孩子节点,其中孩子的父母都是期望的父母。 我在这个控制台上有一个示例数据集:http://console.neo4j.org/?id=nsq8c1 在该示例中,我们有包含父节点的组节点,以及正好有2个父节点的子节点,并且所有组中的所有父节点与每个其他父节点都有一个子节点。现在我想要回父母都在第一组的孩子。 我尝试的示例查询是
我有一个XML文件,我正试图解析它以获得名为的标记。 使用xpath和,我可以看到有10个子节点,每个节点都被命名为。但如果我使用以下任何一种XPath,就没有匹配项: 我所做的一切都不是返回任何标记。但是我知道有10个。我可以通过获得,所以我知道我正在连接到这个文件。我如何生成一个xpath来到达每个? XML结构(缩写):