钱老师的实验室在三楼。走廊的窗户对着一片白杨树,九月的叶子还绿着,风一吹哗哗响,像下了一场看不见的雨。
实验室的门牌是手写的——"水资源与管网优化实验室",字写在一张A4纸上用透明胶贴在门框旁边,胶的边角已经翘起来,黄了。推门进去,左边靠墙一排铁皮柜,柜里塞着往届的毕业论文和期刊合订本,纸页的边被虫蛀了几个小洞。右边是四张实验桌,桌面是被化学试剂腐蚀过的灰白色,中间两张摆着台式电脑——显像管的,屏幕厚得像一本字典。最里面的那张桌是钱老师的,桌上永远整整齐齐:一台笔记本电脑、一个白色马克杯、一摞A4纸、一支黑色签字笔。笔帽扣着,笔尖朝左。
钱老师站在黑板前面。他瘦,颧骨高,戴一副厚框眼镜,镜片后面的眼睛很小——不是因为眼睛真的小,是因为镜片太厚把眼睛缩了。他说话声音轻,轻到坐在最后一排也能听见——不是因为他嗓门大,是因为他说的每句话里没有多余的字。字和字之间的空隙被他用粉笔的沙沙声填满了——他在黑板上写字的速度和说话的速度一样,一笔一画,横平竖直,每一个符号占的空间一样大,像在排一队永远不走散的士兵。
"遗传算法,"他在黑板上写下这四个字。粉笔在玻璃黑板上走的时候有很轻的吱嘎声,每个字的最后一笔他都顿一下,像在钉钉子。"模拟自然选择。个体、变异、交叉、选择。一代一代地迭代——差的被淘汰,好的留下来。留到最后的,就是最优解。"
他在"最优解"三个字下面画了一道横线。横线很直。
课题是把遗传算法用在给水管网优化上。
给水管网优化——说简单了,就是用程序找出一组管径和压力分配,让管网的建设成本最低、水压最均匀、供水最可靠。输入是管网拓扑、需水量、节点标高;输出是最优的管径组合和压力分布。三四十个节点的管网,每个节点有三四种管径可选,全部组合排列起来是一个天文数字——靠人脑算不完,用一个一个试的穷举法也试不完。遗传算法把管径组合当成染色体,每一次迭代让好的组合交叉、变异、产生下一代,一代一代筛,筛到最后剩下来的那个——生存下来的那个——就是最优解。
生存下来的就是最优解。
我在笔记本上写了一句:"自然选择 / 市场选择 / 最优路径。"写完之后看着那两道斜线——它们真的是同一件事吗?遗传算法在程序里筛,市场在社会里筛,水在管道里走阻力小的地方。三样东西,三套系统,中间有相似的影子,但还不能直接画等号。
赵启明在大二那封信里写的话又浮出来了——"有效市场假说"。市场是有效的,因为市场一直在做自然选择——不合理的定价会被套利者吃掉,留下来的都是合理的。给排水的管网也是:水从高压往低压流,走阻力最小的路径——水不做选择,水只是在所有可能的路径里自然地走了最短的那条。
自然选择 / 市场选择 / 最优路径。
我把这一行字用蓝色钢笔写在笔记本空白页的正中间。写完把笔帽扣上。笔尖朝左——和钱老师桌上那支签字笔的方向一样。
实验室的灯在晚上六点之后空了。
钱老师五点半走的。走之前他把黑板擦了一遍——从左上角擦到右下角,粉笔灰落在黑板下面的槽里。他走的时候脚步很轻,门关上才听见走廊里的回声。实验室里只剩我一个人。电脑的散热风扇嗡嗡响,窗外白杨树的叶子在夜色里变成了一整片黑,只看得见树冠的轮廓——像一团没剪边的毛毡贴在窗户上。
遗传算法的程序写了三天。第一天写框架——初始化种群、适应度计算、选择算子、交叉算子、变异算子。第二天写管网拓扑的输入——三十三个节点,四十八根管段,需水量和标高从Excel表里读进去。第三天写输出——每迭代一代在屏幕上打印当前最优适应度值,看它从大变小。
我看着屏幕上的数字一代一代地降:
第1代:适应度 2487.3
第10代:适应度 1934.6
第50代:适应度 1356.2
第100代:适应度 987.4
第200代:适应度 821.5
前五十代降得快——差的染色体被淘汰,好的基因被保留,每一代的改进很大。一百代之后降得慢了——好的染色体已经差不多留下来,迭代只是在微调。两百代之后几乎不动——最优解已经收敛了。
收敛。这个词在程序里很安静——答案不再变化,屏幕上的数字停下来,好像终于同意了某个结果。
屏幕上的数字停在第987.4的时候我看了一眼墙上的挂钟。十一点四十分。实验室外面走廊的灯灭了,只有安全出口的绿牌亮着。我把程序存盘,文件名叫"GA_pipe_v1.0.c"。关掉电脑之前看了一眼屏幕——黑色的命令行窗口上最后停着那个数字,987.4。明天再迭代一千代试试。
十月中旬。钱老师在黑板上画了一个管网简图——六个节点,七根管段,水源在最上面。
"优化问题有三个约束,"他用粉笔在约束条件的编号旁画圈。"第一,节点压力不能低于最低服务水头。第二,管段流量不能超过最大允许流速。第三,水压平衡——任意一个闭合环路的压力损失之和等于零。"
第三个约束他画了两遍——第一遍画得偏了,擦掉,第二遍画正了。粉笔在黑板上走的时候他侧着身子,右手抬高到肩膀的位置写字,像在墙上钉一幅画。他在约束条件的右边画了一个方程组,方程组的最后一个等式是:
ΣΔh = 0
"水从起点流到终点,不管走哪条路,水头损失加起来都一样。这是能量守恒——水在管网里和电在电路里是同一件事。克希霍夫定律,管网和电路都适用。"
他放下粉笔,拍了拍手上的灰。灰落在他的深蓝色西装袖口上,他没注意。
我在笔记本上画了三行等式:
水管网 → 遗传算法 → 最优管径 = 最小成本
电路网 → 克希霍夫定律 → 最优电流 = 最小能耗
金融市场 → 有效市场假说 → 最优定价 = 最小风险
三行等式写完之后,我在最后一行的"最小风险"底下又画了一道横线。然后又加了一行:
管网 → 算法 → ?
问号后面没有写东西。但笔记本翻到这一页的时候,那三行字平行排列着——"管网""电路""市场","成本""能耗""风险"。我看了很久,没把问号补上。
十一月。第一次组会。
钱老师的组只有三个研究生——我、张伟和李楠。张伟做管网可靠性分析,李楠做供水调度优化。组会在实验室开,钱老师坐在他自己那张桌后面,面前摊着他用铅笔写的笔记——铅笔字很细、很轻,压在纸面上不凹不凸,和签字笔的深重截然相反。
三个人各讲二十分钟。张伟讲了节点的冗余度分析,画了一张管网拓扑的故障树——根节点是"管网失效",往下分叉出"管段破裂""阀门失灵""水源中断"三个子节点,每个子节点再往下分。我看着他的故障树,心里想:这是一棵倒长的二叉树——根在上面,叶子在下面,和管网拓扑一模一样。给排水的管网也是一棵倒长的树——水源在上面,干管往下分,支管再往下分,末端的用户在最下面。树的结构是自然的结构——根向下找水,枝向上找光。管网把这两棵树拼在了一起:在地下,水从根往叶子流;在地上,光从叶子往根走。
轮到我讲的时候,我把遗传算法的初步结果投影到墙上——迭代两百代的适应度曲线,从高处落到低处,像一条瀑布从悬崖上冲下来,先是急降,然后变缓,最后几乎平了。
钱老师看了十秒钟。他推了一下眼镜。
"收敛太快。"
"管径选择空间太小——我只设了五种规格。"
"五种太少了。你的染色体编码太短,变异的操作空间不够。"他拿铅笔在纸上画了两下——不是写字,是画了一条线,线上点了几个点。"把管径选项从五种加到十种。迭代次数从两百加到一千。再跑一次。"
张伟在我旁边小声说了一句:"钱老师看十秒就能看出问题。"
李楠点头。"他做题从来不用橡皮。写错了直接划掉。"
组会散了。钱老师走的时候把椅子推回原位——椅子和桌子之间的距离刚好是人坐下之后腿能放进去的宽度。实验室又空了。我在电脑前坐下,把管径的选项从五种改成十种,迭代从两百改成一千,重新运行。
这次迭代跑了一整夜。
十二月初的一个深夜。实验室只有我的电脑开着的荧光照着半面墙。遗传算法的程序跑完了——一千代,十种管径选项,三十三个节点。
屏幕上最后一行:
第1000代:适应度 763.2
比第200代又降了将近六十点——但降的幅度已经很小了。曲线在尾部几乎是一条水平线,像河道在入海口铺开成一片平坦的三角洲——水还在流,但看不出来了。
我把屏幕上的适应度曲线抄到笔记本上。从左看右——先陡后缓,从高到低。在曲线的最右端,适应度值收敛的平坦区域像一条河到了入海口,再往前就是海。
自然选择。市场选择。最优路径。
赵启明的那句话——有效市场假说——像一颗种子,在遗传算法的土壤里发芽了。我还不懂市场,只能从屏幕上那些被淘汰、被保留的数值里,看见一点相似的影子。程序在一代代试错,最后留下成本更低的管径组合。量化交易——如果有的话——也许是在另一张表里做类似的事。
我在笔记本上写了一行字:
"管网→算法→?"
问号后面是空的。但问号已经在了——问号本身就是一个方向。方向不需要标明终点,方向只需要指明出路。