“有一天,爱丽丝来到路上的叉子,在树上看到了柴郡猫。 “我采取哪条路?”她问道。 “你想去哪里?”是他的回应。 “我不知道,”爱丽丝回答道。 “然后,”这只猫说,'没关系。“
- Lewis Carroll,Alice In Wonderland
注意:到我的知识,这是第一个近似距离畸形的非学术描述。此外,这是我第一次写下图表理论。因此,如果您发现任何错误,请告诉我。
让我们假设我们有一个具有严格正面重量的无向图。让我们也假设该图表代表虚构城市 - 十个街区。这是这个城市的鸟瞰图 -
作为十个街区'地图可能会笨重可视化,对于此博客文章的其余部分,我们将使用简化版本 -
当我们以图形显示这个城市时,我们注意到它有10个顶点和11个边。每个顶点都有一个表单块n的标签,n个是任何唯一的整数(对于该博客文章的其余部分,我们将缩写为bn的块n)。边缘重量是两个块之间的距离。例如,B1和B2之间的边缘的权重为10.此外,任何两个块之间的路径的长度是连接该路径的所有边缘权重的总和。例如,路径(B1,B2,B3)的长度为10 + 5 = 15。但是,应该注意,这不是B1到B3的唯一路径。另一路径是(B1,B2,B9,B5,B3),其路径长度为10 + 50 + 75 + 10 = 145。当然是一个昂贵的一个!
关于图表的广泛研究的问题是最短的路径问题,即:在图中找到两个顶点(或节点)之间的路径的问题,使得其组成边缘的权重的总和最小化。
可以在视觉上观察到,B1和B3之间的最短路径确实是(B1,B2,B3),路径长度为10.但是我们如何在两个顶点之间进行算法找到最短路径?一种方法是使用Dijkstra' s算法。虽然对Dijkstra&#39的彻底分析超出了该博客文章的范围,但在Dijkstra' S算法上的维基百科页面中提到的算法是一个很好的开始 - 让我们开始的节点被称为初始节点。让节点y的距离是从初始节点到y. dijkstra' s算法将分配一些初始距离值,并将尝试一步一步地改进它们。
标记所有节点未经许可。创建一组名为“不受检控”集的所有未检测的节点。
分配给每个节点暂定距离值:为我们的初始节点设置为零,并为所有其他节点的无穷大。将初始节点设置为当前。
对于当前节点,请考虑所有未让邻居并通过当前节点计算其暂定距离。将新计算的暂定距离与当前分配的值进行比较并分配较小的距离。例如,如果当前节点A用距离标记为6,并且将其与邻居B连接的边缘具有长度2,则到B到B到B的距离将为6 + 2 = 8.如果B先前标有6 + 2 = 8.然后距离大于8,然后将其更改为8.否则,将保持当前值。
当我们完成考虑当前节点的所有未检测的邻居时,将当前节点标记访问并从未检测到的集合中删除它。访问过的节点将再次再次检查。
如果已被标记为访问的目标节点(在规划两个特定节点之间的路由)或者在未检测到的集合中的节点之间的最小暂定距离时(在规划完整的遍历时;在初始节点之间没有连接时发生并剩下不受检测的节点),然后停止。该算法已完成。
否则,选择具有最小暂定距离的未检测的节点,将其设置为新"当前节点",然后返回步骤3。
规划路线时,实际上没有必要等到目标节点是"访问"如上所述:算法一旦目的节点在所有&#34之间具有最小的暂定距离,就可以停止;未公开"节点(因此可以选择为下一个"当前")。
为了在实践中可视化上述Dijkstra' S算法,这里是一个使用十个块图的示例 - 在先前的博客文章中,我描述了Dijkstra的变种是如何称为最佳首次搜索的算法(使用它启发式功能)可用于伪代码到代码生成。因此,可以说dijkstra' s算法不是唯一解决最短路径问题的唯一算法。一个好奇的读者可以读取关于类似算法,例如Bellman-Ford算法。
我们上面描述的工作是单对最短路径问题的一部分。这是因为,我们主要对一对之间的最短路径感兴趣(在上面的例子中是(B1,B5))的最短路径。然而,Dijkstra' S算法可用于更常见的问题,称为单源最短路径问题。该变体可以定义为:我们必须从源顶点V到图表中的所有其他顶点找到最短路径的问题。
让我们假设在图3中,没有端点。相反,我们希望找到B1到所有其他9个点的最短路径。在这种情况下,根据上面提到的算法,当我们访问(完全一度)图中的每个节点时,我们停止(以b1开始)停止。这是一个逐步的过程 -
假设n是图中的顶点的数量,dijkstra' s算法不超过(n-1)步骤,每个步骤都需要不超过(n-1)比较来检查是否未访问顶点。 ,并且不超过(n-1)比较在每个步骤中更新标签。总而言之,它使用O(n 2)操作来添加和比较单源最短路径问题。
单源最短路径问题的自然继承是全对最短路径问题(APSP),其定义为:我们必须在每对顶点V,V&#39之间找到最短路径的问题;在图表中。
保持我们以前的假设有效(图形是无向并具有正的边缘权重),最简单的解决方案是上述问题的方法是在图中的每个顶点上运行Dijkstra' s算法。在这样做时,我们将获得以下矩阵:如图5所示,所产生的数据结构是尺寸O(n 2),其保持距离的n x n矩阵。一旦生成此矩阵,两个顶点之间的最短路径的任何未来查询都需要O(1) - 恒定的时间。然而,正如我们所观察到的那样,产生这样的矩阵可以采用O(n 3)时间(用于单源最短路径的单源最短路径的击穿-O(n 2),这被重复为n顶点)。解决全对最短路径问题的另一种方法是弗洛伊德战争算法。该算法如下:
维基百科包含上述算法的逐步示例。可以观察到,该算法具有O(n 3)的时间复杂度。此时,一个好奇的读者可能会想知道 - 弗洛伊德 - 战争和基于Dijkstra的APSP之间的运行时间相同吗?这是史蒂文斯皮恩的教授在算法设计手册中说(第二版,第6.3章 - 最短路径):弗洛伊德 - 战争全对最短路径在O(n 3)时间内运行,这渐近地没有比n调用Dijkstra的算法。但是,循环是如此紧张,程序如此之短,即在实践中运行更好。它是值得注意的,作为比邻接列表更好地在邻接矩阵上工作的稀有图算法之一。
关于上述声明的相关讨论是关于弗洛伊德战争算法的堆叠流程时间复杂性。詹姆斯·劳森的最高答案的摘要如下:这里的关键词是"在实践中,"请记住,渐近分析ISN' t完美。它'绩效的数学抽象/近似。当我们实际来运行代码时,有许多实际因素它没有考虑到。处理器具有复杂的低级架构,用于获取和运行指令。 .....事实证明,处理器喜欢优化嵌套循环和多维阵列!这是Skiena在这里暗示的。阵列的循环最佳使用时间和空间位置,并适用于低级处理器优化。另一方面,Dijkstra' S也是如此,所以处理器优化Don' T工作。因此,Dijkstra确实在实践中可能会慢。
有趣的故事:Floyd-Warshall算法背后的历史与算法本身一样令人着迷。从Jeff Erickson的算法(第9章):在1962年提出了两次去除这种对数因子的最短路径的不同配方,首先由Robert Floyd和以后独立地由Peter Ingerman独立,略微概括了斯蒂芬马什尔之前发表的斯蒂芬战争算法同年。事实上,Warshall的算法于1959年由Bernard Roy发现,1951年,斯蒂芬克莱琳使用了潜在的递归模式。Warshall(和Roy's和Kleene)的洞察力是在动态编程复发中使用不同的第三个参数。
Kleene' S算法(1956年发布)用于将确定性有限自动机转换为正则表达式。有趣的是,本文旨在通过神经网络识别的模式正是正则表达式。此外,Warshall' S变型用于有效地计算关系的传递闭合。
此外,Nodari Sitchinava教授提到了APSP问题的以下迷人用例:未加权的最短路径也用于社交网络分析,以计算演员之间的中心中心。 (重量通常是绑定力量而不是SNA中的成本。)演员出现的其他演员之间的最短路径越多,所以中心性越高。这通常由可能的路径数标准化。这项措施是演员的一个估计和在其他演员之间的潜在控制或影响其他演员之间的潜在控制或影响。
此时提出的自然问题是 - 以上任何现实世界应用程序的上述APSP算法有多少? Surender Baswana教授在他的随机算法中提到了关于经典APSP算法的以下内容:当前最先进的RAM大小:8 GBS可以' T处理甚至10 5个顶点的图表(带RAM尺寸)
请注意,根据谷歌,这些讲座幻灯片是2014年2月。然而,观察如此巨大的限制令人惊讶。 Mikkel Thorup和Urizwick在他们的近似距离令人垂涎欲滴的论文中进行了以下意见:然而,有几个严重的反对意见。首先,\(\ widetilde {o}(mn)\)的预处理时间可能太长。其次,即使我们愿意等待那么长,所产生的\(n \ times n \)矩阵可能太大而无法有效地存储(通常是\(m \ ll n ^ 2 \),然后这个表比较大得多比网络本身)。
在上述声明中,这是指经典的APSP算法。此外,与上面配制的术语一致,n是指顶点的数量。此外,上面以及该博客文章的其余部分,M是指图中的边缘的数量。符号\(\ widetilde {o})指的是“忽略”对数因子的大o的变体。
提供的参数和Zwick提供了以下内容:我们对大型网络进行了描述,例如互联网或大型道路网络,例如美国道路网络。 .....我们对所有距离并不真正感兴趣,我们只需要能够快速检索它们,如果需要。例如,美国可能在美国的距离对没有人感兴趣的许多地址。 .....我们表明如果网络无向,并且如果我们愿意满足于近似距离,而不是确切的,则存在更好的解决方案。
通过这个论点,我们将注意力转向不同类别的问题,称为全对近似最短路径问题。如上所述,这些解决方案提供了任何一对顶点之间的最短路径的近似值。这种解决方案背后的一个灵感是现实生活空中/道路旅行(在Baswana&#39教授中提到):在上面的图中,想象着印度有许多操作飞行路径,其中一些是 - 坎普尔-lucknow,坎普尔 - 德里和德里班加罗尔。从坎普尔到勒克瑙到达的是直截了当的,我们直接飞行。但是,如果我们想从坎普尔到班加罗尔到达什么?在这种情况下,我们首先找出来自坎普尔的最近城市,飞往班加罗尔的航班。让我们假设这个城市是德里。因此,而不是创建距离班加罗尔的较短路线(伴随着其运营费用),而是通过德里前往班加罗尔旅行。正如我们选择最近的城市(德里)到班加罗尔的飞行,我们确保距离最近的路径最近(理论上是直接飞往班加罗尔)的所有操作路径。
要了解这一点更好,从三角不等式的角度来看待这个问题:从上面的图中明显,如果x变小(在我们的例子中是Kanpur之间的距离和连接到班加罗尔的城市),总距离通过这座最近的城市到目的地将更接近最短的路径(Kanpur到班加罗尔)。如果一个人密切观察这个例子,一个整洁的想法会呈现自己:从每个顶点,如果我们将距离信息存储到少量顶点,我们仍然可以在任何一对顶点之间报告距离吗?
上述示例显示,在附近的顶点上具有距离信息,其又具有许多其他顶点的距离信息肯定是一个有用的特征。上述BlockQuote来自第39章(用于近似最短路径的随机图表数据结构),在数据结构和应用程序的手册中,第2版。
那么Thorup和ZWICK在近似距离Oracles上展示了什么?为什么重要?来自同一章节:在设计用于计算全对近似最短路径的所有数据结构和算法中,近似距离oracles在它们的情况下实现了运行时间(子立方)的同时改进以及空间(子二次),仍然在恒定时间内回答任何近似距离查询。对于任何\(k \ ge 1 \),它需要\(o(kmn ^ {1 / k})\)时间来计算(2k - 1) - 大小\(O(kn ^ {1+ 1 / k})\)将在O(k)时间内回答任何(2k-1)的距离查询。
首先,为什么这个名称包含Oracle这个词? Oracle的文字定义是"寻求神圣建议或预言的地方。"从原始纸张' s摘要:我们的数据结构最令人印象深刻的功能是它的常量查询时间,因此名称“Oracle”。
通过直观地理解称为3近似距离oracles的更简单版本的算法,让我们开始。任何近似距离Oracle都需要两种算法 - 一种预处理/构建算法和距离查询算法。预处理算法构造在恒定时间内可以在其上应答距离查询的基础。这类似于Floyd-Warshall算法中矩阵的制定。假设我们已有的一组顶点被标记为V.例如,在十个街区城市中,V = {B1,B2,B3,.....,B10}。在研究此主题的同时,找到的最直观的预处理算法是由Baswana和Sen教授所描述的(第39章):让\(r \ subset v \)是通过随机独立挑选每个顶点来形成的顶点的子集概率\(\ gamma \)(\(\ gamma \)的值将稍后修复)。
对于每个顶点\(v \),将距离存储到样本集R的所有顶点。
对于每个Vertex \(v \),让\(p(u)\)是所有采样顶点中最近的顶点\(u \),并且让\(s_ {u} \)成为集合图表G的所有原装都比顶点\(p(u)\)更靠近U.存储SET \(S_ {U} \)的顶点以及它们的距离\(u \)。
在直观地理解算法之前,首先让'第一次看到它。我们首先选择\(\ gamma = n ^ { - 1/2} = 1 / \ sqrt {n} \)。我们稍后会理解为什么这是选择的最佳价值。步骤1可以以下列方式实现:基于十个块的导入随机,数学#10V =范围(1,n + 1)伽马= 1 / math.sqrt(n)#gamma来自大约0.316r = [ Vartex在V中的顶点,如果Aquary.choices([true,false],权重= [gamma,1-gamma])[0] == true]
让我们假设在我们运行上面的代码后,我们获得了[1,10]。
虽然上述算法对步骤2中的距离度量模糊不清,但实际上,我们希望将来自V的所有顶点的最短距离存储在样本集R中的所有顶点。这些距离可以使用Dijkstra' s单源最短路径算法。但是,请注意这里的差异!我们只需要使用子集R计算Dijkstra' S子集R作为我们的源顶点(即,对于我们的情况,我们需要执行两次算法,其中一个带有源顶点的一个,另一个带有源顶点的另一个源顶点为10)。以下是我们在步骤2之后获得的结果矩阵:
密切观察,步骤3有两个子部分。对于每个\(v \):查找\(p(u)\),它是所有采样顶点中的最近的顶点到\(u \)。
对于每个顶点U,查找\(s_ {u} \),它是图表g的所有顶点的集合,它比顶点\(p(u)\)更近。
可以使用步骤2同时解决子部分。以下是上述矩阵的修改版本:表示上面突出显示的单元格,我们创建一个名为\(\ delta(u,p(u))\的新术语)。例如,\(\ delta(b3,p(b3))= \ delta(b3,b1)\)= 15和\(\ delta(b6,p(b6))= \ delta(b6,b10)\) = 50.解决子部分II需要一些思考。我们不能直接将Dijkstra' s算法应用于每个顶点,因为它与解决经典APSP问题相同。然而,这里有两个观察结果:我们只需要计算\(v \)和\(v \ setminus r \)的每个顶点的对之间的最短距离。这是为了避免任何冗余计算,因为我们已经发现了在步骤2中的每个顶点和Set r之间的每个顶点之间的距离。符号\(\ setMinus \)代表Set-minus,用于设定理论以找到相对任何设置WRT A组B的补充。例如,如果a = {1,2,3,4}和b = {3,5,7},则\(a \ setminus b \)= {1,2 ,4}。在我们的情况下,\(v \ setminus r \)= {2,3,4,5,6,7,8,9}。
对于任何对\((u,w)\)其中\(u \ in v \)和\(在v \ setminus r \中),我们可以在那双的距离时停止计算dijkstra的算法(让此距离是\(\ delta(u,w)\))超过值\(\ delta(u,p(u))\)。也就是说,当\(\ delta(u,w)\ ge \ delta(u,p(u))\)。
由于上述观察有点数学,让我们用十个块图来敏感它们。正如我们可以在上图中观察到的那样,我们从未遍历7个顶点,因为它们意味着从B3到该顶点的距离将增加15.让我们现在可视化执行最终步骤3之后形成的矩阵图11,而不是计算90个最短路径(丢弃起始点计算),就像F的经典APSP算法一样
......