地铁线路图上的两站,看起来很近,坐过去却未必快。线可以拐成整齐的直角,站点可以被挪开,城区的形状也可能变得认不出来。可我们依然会拿着它找站、换乘。

一张图删掉了这么多东西,为什么还管用?

这个问题适合放在整个系列的开头。写程序、分析数据、训练模型,经常都要先做一件类似的事:从许多细节中,选出眼前问题需要的那一部分。选对了,复杂的事情有机会变得清楚;选错了,后面的计算再精细,也可能答非所问。

我们先不谈真实城市,用五个虚构站点画一张足够小、可以亲手算完的图。下面的线路、时间和换乘条件全部是为解释原理设定的,不代表实际出行数据。

先问你想从图上知道什么

站点记为S、A、B、C、T,S是起点,T是终点。只有下面这些直接连接,暂且都允许双向通行:

S连A,A连T;S连B,B连C,C连T。

因此,从S出发,不绕回已经走过的站,有两条到T的路线:S→A→T,以及S→B→C→T。

现在把图上方的A往左挪,把B往下挪,把直线弯成折线。只要站名没有弄错,连接也没有增减,这两条路线仍然在。你照着S、B、C、T的顺序走,每一对相邻站仍然能够直接抵达。

图1:同样五个站点、同样五条连接,可以画成不同形状。两幅图都保留S-A、A-T、S-B、B-C、C-T,不能按线段长短推断距离或用时。

这里已经有一小段可以检查的推理。假设一条路线在第一幅图里可走,那么沿路每一步都是一条保留下来的连接,所以它在第二幅图里也可走。反过来也一样。于是,两幅图对于“哪些站能够沿线路互相到达”这个问题,给出的答案相同。

注意这个结论的范围。它没有证明两站步行距离相同,也没有证明坐车时间相同。我们保留的是连接关系,纸上线段的长短没有被约定为真实距离。

如果你问“能不能坐车到T”,这张图已经很有用。如果你问“走路去T要多久”,就缺了道路、距离与步行速度。图没有突然变坏,只是问题换了,需要的信息也跟着变了。

“最好的一条路”还没有说清楚

即使终点已经确定,“选一条最好的路线”也仍然不够明确。

如果想经过尽量少的区间,S→A→T只有两段,S→B→C→T有三段,前一条更少。这里数的是相邻站之间的区间数,不是换乘次数。

如果想尽快到达,就要补上时间。我们为每段连接标一个固定的行车用时:S到A、A到T各4分钟;S到B、B到C、C到T各2分钟。

暂时假设没有额外候车、换乘和进出站时间,途中也没有延误。于是:

S→A→T:4+4=8分钟。

S→B→C→T:2+2+2=6分钟。

同一张连接图,按区间数选,答案是上面那条;按行车时间选,答案是下面那条。后者多走一段,却更快。

图2:路线P经过2个区间,共8分钟;路线Q经过3个区间,共6分钟。“区间最少”和“行车时间最少”得到不同答案。

这些附在线路上的数字,通常叫作权重。它可以表示时间,也可以表示费用,但含义要先说清楚。把一条路线经过的各段时间相加,就得到这里定义的路线代价。加权路径的这种表示是图论里常用的建模方式。1

用一个短公式写,就是T(P)=t₁+t₂+…+tₖ。P代表一条路线,k是它经过的区间数,t₁到tₖ是各段用时,T(P)是总用时。字母只是让我们不用每次都重写整句话。

这条加法也有依据:乘车在这些区间上依次发生,各段计时没有遗漏或重叠。我们把各段的分钟数加起来,仍然得到分钟。假如某条边记分钟,另一条边记公里,就不能直接相加后称为“最快”。

问题到这里才逐渐完整:从哪些路线里选,用什么数比较,哪些现实条件暂时被忽略。只有把这些说清楚,“最优”才有确定的意思。

漏掉五分钟,答案就反过来了

现在补上一条刚才没有记录的信息。

S→A→T在蓝线上,全程不换乘。S→B→C在绿线上,C→T在橙线上,乘客到C以后要换车。假设这一次换乘固定需要5分钟,包含换站台与等下一趟车;起点候车等两条路线共有的额外时间暂时记为0。

那么,下面那条路线的总时间变成2+2+5+2=11分钟,上面那条仍是8分钟。

刚才推荐的6分钟路线,现在更慢了。加法没有算错,问题出在原模型根本没有把换乘计入目标。

图3:行车时间相同,加入C站的5分钟换乘后,路线Q由6分钟变为11分钟。路线P仍为8分钟,比较结果随遗漏条件改变。

我们还可以往下推一步,看看答案对这个遗漏有多敏感。

把换乘用时记为τ,读作“tau”,并假设τ不小于0。两条路线分别用8分钟和6+τ分钟。下面那条更快,恰好要求6+τ<8,也就是τ<2。

所以,换乘少于2分钟,选下面那条;恰好2分钟,两条一样快;超过2分钟,选上面那条。

这个结果比“要考虑换乘”更具体。它告诉我们,真正影响这次选择的分界是2分钟。如果估计换乘需要5分钟,即使误差有半分钟,结论仍不会改变;如果估计需要2分钟左右,就不能把推荐说得那么确定。

这还只是一个静态小模型。现实中的候车时间可能随到站时刻变化,电梯是否可用也会影响不同乘客。那些信息要不要加进来,取决于我们希望回答什么,以及愿意接受多大的偏差。

有时要补数字,有时要重新定义对象

换乘的例子还有一层值得看看。

“到达C站”真的足以描述乘客现在的处境吗?站在绿线站台的人,和站在橙线站台的人,虽然都在C站,继续坐橙线去T的代价却不一样。

如果只记一个“C”,这两种情况会被揉在一起。一个更细的表示办法,是把C拆成“C的绿线站台”和“C的橙线站台”,两者之间画一条需要5分钟的连接。

路线就可以写成:S→B→C绿→C橙→T。两段行车各2分钟,站台间转换5分钟,最后行车2分钟,合起来仍是11分钟。

图4:把C站拆为C绿和C橙两个状态,并用5分钟换乘连接它们。物理站点只有一个,模型里的状态可以有两个,因为下一步的代价不同。

这并不是说地图一定越细越好。只问“C站能不能到T”时,站台层面的细节可能暂时不重要;一旦计算换乘代价,站台就成了不能随便丢掉的信息。一个模型里的“点”,也不必永远对应一个物理物体,它可以对应眼前问题需要区分的状态。

在软件里也会遇到同样的选择。一项任务显示“已收到”,和“已完成”,下一步允许做什么并不相同。若只存一个含糊的“成功”,程序就失去了判断后续行为所需的信息。

数学建模走到这里,已经不只是给现实配一个公式。我们在决定哪些对象需要区分,哪些关系要记录,又允许在什么条件下把几种情况看成同一种。2

从地图回到程序与AI

回头看,五个站点的小问题实际经历了三次变化:先保留连接,回答能否抵达;再加行车时间,比较快慢;发现换乘被遗漏后,补代价,必要时细分状态。

这些步骤在别的场景里也会出现,但具体规则得重新检查。

例如,一串服务调用依次执行,粗略总耗时可以按顺序相加;两个4毫秒任务若同时开始、互不争抢资源,且必须等两者都结束,理想等待时间是4毫秒,而非8毫秒。画面里都有“两项任务”,时间的组合规则却由执行关系决定。

AI也需要选择表示。把一篇文章变成一串数字时,哪些差别会被保留,哪些会被压到一起,会影响后续判断。“两个数字向量靠近”是表示空间里的关系;它是否对应我们在意的语义接近,还需要数据和实验检验。这个系列后面会认真拆开向量与距离,现在先记住这种边界就够了。

在假设确定后,我们可以证明图上哪些路线可走,也能证明τ超过2时哪条更快。但是,“换乘固定需要5分钟”来自我们的设定;如果拿去解决真实出行问题,它就得接受测量和验证。推理可靠与假设贴合现实,都需要各自的证据。

地铁图好看的地方,也正在这里:它容许形状变化,却把需要的关系留下来,让眼睛从拥挤的街道细节中看到一副清楚的结构。把对象和规则选好,原先模糊的一句“怎么走更好”,就能一步步变成可算、可比较、可检查的问题。

下一篇先把“规则”这件事讲清楚:一句“满足条件就可以”,究竟说了什么,又没有说什么。

顺手试一下

**题目1:**沿用本文两条路线,行车用时分别是8分钟和6分钟,只有后一条需要换乘。如果换乘分别需要1分钟、2分钟、3分钟,哪条路线更快?

**提示:**比较8与6+τ。相等也是一种可能的结果。

**参考答案:**换乘1分钟时,后一条共7分钟,更快;2分钟时,两条都是8分钟;3分钟时,后一条共9分钟,前一条更快。

**题目2:**如果两条路线都额外增加完全相同的3分钟进站时间,它们的快慢关系会改变吗?这一结论能用于“两条路线各增加平均3分钟、但每次实际等待不同”的情况吗?

**提示:**先给两个总用时同时加3,再区分固定值与只知道平均值。

**参考答案:**固定增加相同的3分钟不会改变比较,因为a<b时,a+3仍小于b+3。只知道平均各增加3分钟,不能保证某一次出行的快慢关系不变:平均相同,不等于那一次实际增加的时间相同。

延伸阅读

  1. MIT 6.006:Weighted Shortest Paths,了解加权连接和路径权重。本文只用它们描述问题,最短路算法留到第05篇。
  2. SIAM与COMAP:GAIMME数学建模指南,关于提出问题、作出假设、形成模型与回到现实检验的说明。

作者:Jiancheng Wang · 数学之美(独立原创)