如果你要问我对公路旅行的痴迷是从哪里开始的,我不得不说这可能是在我和妻子驾驶 I-40 从弗吉尼亚州布莱克斯堡到新墨西哥州阿尔伯克基开始我毕业后的第一份工作后不久开始的学校。 也许看到不断变化的风景和参观新的地方让我感到兴奋。 不过,老实说,这更有可能是因为“完成路线”并在两端驾驶 I-40 的其余部分。 我会妥协并说两者兼而有之。
最初,我对公路旅行的迷恋主要集中在穿越美国所有主要州际公路(那些以 0 或 5 结尾的州际公路),因为我几乎已经完成了一个。 然而,当我仔细阅读各种旅游书籍时,我发现公路旅行社区倾向于将州际公路视为商业和全方位“繁忙”的途径,而不是更喜欢美国其他主要公路更安静、更慢的步伐:美国高速公路系统。 绘制出其中几条高速公路引发了新地方和新景观的兴奋。 我的新梦想是在美国的每条主要高速公路上行驶,也就是说,所有那些仍然有效的两位数名称的高速公路,唯一的例外是加利福尼亚州的 101 号高速公路。
The stuff dreams are made of... (image from Wikipedia: https://commons.wikimedia.org/wiki/File:Map_of_current_US_Routes.svg)The stuff dreams are made of... (image from Wikipedia: https://commons.wikimedia.org/wiki/File:Map_of_current_US_Routes.svg)The stuff dreams are made of... (image from Wikipedia: https://commons.wikimedia.org/wiki/File:Map_of_current_US_Routes.svg)The stuff dreams are made of... (image from Wikipedia: https://commons.wikimedia.org/wiki/File:Map_of_current_US_Routes.svg)梦想是由...组成的 (图片来自维基百科:https://commons.wikimedia.org/wiki/File:Map_of_current_US_Routes.svg)
自从最近担任研究统计学家测试员以来,我在JMP , 我对软件的了解比我想象的要多。 我对自己学习 JMP 脚本语言的速度如此之快感到惊讶(尽管我肯定还在学习 JSL),这为我打开了更多的可能性。 但是,一旦我发现拖放图形生成器有能力绘制地图?! 好吧,你可能会猜到这是怎么回事(如果标题不是一个死赠品)。
在克服了最初的兴奋之后,出现了片刻的怀疑。 您真的可以使用 Graph Builder 规划公路旅行吗? 我知道您可以绘制区域,但是线条和道路呢? 好吧,我很高兴地说,在花费了比我愿意承认的更多的时间之后,答案是肯定的! 它不是谷歌地图或 AAA Trip Tik,但我认为它绝对值得一看。
铺设道路
所以第一个要回答的问题是这将是怎样的公路旅行? 好吧,我的梦想是走遍美国的每条高速公路,所以为什么不来一次这样的旅行呢! 具体来说,目标如下:
找到一条通过美国高速公路系统的路径,连接每条活跃的美国主要高速公路。
虽然我内心的完美主义者会犹豫不走构成特定高速公路的每一英里人行道的可能性,但必须做出一些妥协,无论如何这仍然是一个巨大的挑战。 但首先,一些基本规则:
- 目标是尽可能多地在美国高速公路上行驶。 也就是说,我想直接从一条高速公路到另一条高速公路,而不必在可能的情况下在两者之间走非高速公路。
- 高速公路必须当前处于活动状态(抱歉,66 人公路)并作为高速公路系统的主要成员(两位数名称,101 除外)
- 每条高速公路只能行驶一次。
看起来很简单,对吧? 第一步是编制高速公路交叉口数据库,显示哪些高速公路与哪些其他高速公路相连,以及这些交叉口的位置。 我花了很多时间试图找到这样一个现成的数据库,但没有这样的运气。 所以我决定自己制作一个数据表。
Example of the process I used to get the coordinates for each intersection. A true labor of love.Example of the process I used to get the coordinates for each intersection. A true labor of love.Example of the process I used to get the coordinates for each intersection. A true labor of love.Example of the process I used to get the coordinates for each intersection. A true labor of love.我用来获取每个交叉点坐标的过程示例。 真正的爱的劳动。
值得一提的是,高速公路经常会多次相交,甚至并发。 我只记录了从北或东向南或西沿高速公路行驶时发生的第一个交叉路口,从而使我的网络具有固有的方向偏差。 事实上,这正是我正在构建的:基于交叉点“边缘”的美国高速公路“节点”网络。一旦这个网络完成,目标就是找到一条通过网络的路径,连接每个节点,路径中没有重复的节点(如果可能)。
对于那些熟悉图论的人来说,这听起来像是我在处理著名的“旅行商问题”。你几乎是对的。 旅行推销员实际上是所谓的一个特例哈密顿路径,这是一条连接每个节点的路径,没有重复(不要与欧拉路径,这是一条不重复地使用网络中每条边的路径,并且与著名的相关联柯尼斯堡桥问题). 使旅行推销员成为特例的是边缘具有权重(例如,时间或距离),因此存在路径必须最小化总权重的附加条件。 有趣的事实:哈密顿路径得名于 William Rowan Hamilton,他正在努力寻找连接十二面体所有顶点的路径。 有一次,他假装顶点是著名的城市,他正在寻找“世界之旅”。我有一种感觉,我们会相处得很好。
Traditional example of a Hamiltonian path on a dodecahedron (image by Christoph Sommer published to Wikipedia: https://commons.wikimedia.org/wiki/File:Hamiltonian_path.svg)Traditional example of a Hamiltonian path on a dodecahedron (image by Christoph Sommer published to Wikipedia: https://commons.wikimedia.org/wiki/File:Hamiltonian_path.svg)Traditional example of a Hamiltonian path on a dodecahedron (image by Christoph Sommer published to Wikipedia: https://commons.wikimedia.org/wiki/File:Hamiltonian_path.svg)Traditional example of a Hamiltonian path on a dodecahedron (image by Christoph Sommer published to Wikipedia: https://commons.wikimedia.org/wiki/File:Hamiltonian_path.svg)十二面体上哈密顿路径的传统示例(Christoph Sommer 的图片发布到维基百科:https://commons.wikimedia.org/wiki/File:Hamiltonian_path.svg)
这条哈密顿路径正是我一直在寻找的! 既然是众所周知的对象,应该有一个高效的算法来找到它吧? 好吧,没那么快。 你看,通过任意图找到哈密顿路径的问题就是所谓的 NP-hard 问题。 这只是一个奇特的术语,它表示很容易验证一条路径是否为哈密顿量,但除了少数例外情况外,要找到这样一条路径非常困难。 换句话说,没有通用的快速算法可以为每种情况找到哈密顿路径。 因此,我再次独自出发,看看是否可以为我的案例开发一个算法。
我首先开始将我的网络转换为 JSL 中的关联数组然后调查同事写的一个在小型网络中寻找路径的简单算法. 该算法使用深度优先搜索,它涉及从网络中的一个节点开始,然后跟随您遇到的每个节点的第一个连接,直到您用完所有连接,此时您返回到另一个非连接节点并继续前进。 虽然这个算法不能保证哈密顿路径,但我发现我仍然可以用它来尝试接近。 我采用这种方法得出的算法如下:
近哈密顿路径查找器
- 提供起始节点。
- 对于每个连接节点,运行单通道深度优先搜索(即,一旦用完连接就不要返回,即使您错过了一些连接)并查看哪个节点具有最长路径。
- 将该连接节点添加到路径中。
- 重复步骤 2-3,直到没有更多可用节点添加到路径中。
该算法背后的想法是,从理论上讲,添加具有最长潜在路径的节点应该可以通过降低路径提前终止的风险,使您更接近整个网络的整体路径。
填补空白
现在我可以获得初始路径,下一步是确定如何“移植”初始运行中遗漏的任何缺失节点。 我想出了三种可能的方法:
- 选择第一个丢失的节点,强制它连接到当前路径中最早可能的连接,然后从那里重新开始搜索——当然,您不必选择第一个缺失节点(事实上,可能不一定有“第一个”缺失节点),但思路是一样的。 本质上,这种方法将缺失的节点“嫁接”到路径中,然后假装它在算法运行期间到达了这一点(重启部分)。 这种方法的一个风险是您可能会发现自己陷入了一个永无止境的循环;由于基本搜索算法的局限性,您可能永远无法到达包含每个节点的路径。 您可以通过尝试在路径搜索中包含更多随机选择来调整此方法,但仍然不能保证更快地找到路径。
- 如果只有一个缺失节点,探索将其拟合到当前路径的每一种可能组合,并返回成功这样做的那个 -从本质上讲,这种方法简单地相当于对所有可能的路径进行详尽搜索,其中包括给定当前路径布局的缺失节点。 这种方法的一个风险是如果丢失的节点有很多连接;可能性的数量可能会很快超过您机器的计算限制。 这就是为什么我只在丢失的节点少于 10 个连接时才使用它。 当然,如果有多个节点,但每个节点的连接很少,你也可以使用这种方法。
- 使用一些肘部润滑脂并手动将缺失的节点输入到路径中 –这似乎是一种逃避,但如果算法很难找到路径,这可能是必要的,而且不一定那么困难。 这也是将专家判断纳入路径的好方法;与纯基于计算机的解决方案相比,通过人工的少量输入,也许可以找到一条风景更优美的路径。 人与机器为实现共同目标而和谐工作的完美典范。
在寻找我的哈密顿路径时,我实际上最终至少使用了这些方法中的每一种。 在下一篇,你可以看到我的劳动成果。