第一百四十八章 算法能算出什么
方小满带回一个消息的时候,是第三天。
"有人找我们。"
林知行从键盘上抬起头。方小满站在折叠桌对面,手里攥着手机,表情不太对——不是焦虑的那种不对,是那种压着兴奋又不敢放出来的不对。
"谁?"
"王建国。长沙的。做物流的。"
林知行没听过这个名字。
"他怎么找到我们的?"
"刘总介绍的,"方小满说,"就是那三家续签门店的刘总。上礼拜我去长沙跑数据,顺便请刘总吃了顿饭。席间我提了一嘴——我们现在在做决策支持服务,不止做库存,什么行业问题都能接。刘总说他有个老同学在长沙开物流公司,正好有个头疼的问题。"
"什么问题?"
方小满在手机上翻了一下聊天记录。
"车辆调度。三十辆货车、五条固定线路、每天要决定哪辆车走哪条线。他说现在全靠人工排,调度员干了八年,经验丰富,但人一多就排不过来。旺季的时候一天要排四趟,调度员排到最后脑子都糊了,经常把车派错线路——本来该走沪昆高速的走了京港澳,多烧三百块油。"
林知行在脑子里快速拆解了一下——
三十辆车、五条线路、每条线路每天最多四趟、每辆车每天最多两趟。
这是一个约束满足问题。比排课简单——排课有上千个教师、几十个校区、复杂的时空约束。车辆调度的变量少、约束明确、目标函数单一(最小化总里程或总油耗)。
"他想什么时候看demo?"林知行问。
方小满咽了一下口水。
"下周一。"
林知行算了一下——今天是周四,还有四天。
"来得及。"
第一天,林知行没有写代码。
他让方小满跟王总要了一份数据——三十辆车的基本信息(车牌、车龄、载重、油耗)、五条线路的路况(距离、限速、收费、堵车概率)、以及过去三个月的调度记录。
数据拿到手之后,他在笔记本上画了一张图。
纵轴是五条线路,横轴是三十辆车。每个格子里填的是历史油耗数据。
他盯了这张图看了二十分钟。
然后他把图撕掉,重新画了一张。
这一次,纵轴还是五条线路,横轴换成了约束条件——时间窗口、载重限制、司机偏好、路况波动、维修记录。
这张图更复杂,但更有用。
因为他发现了一个规律:五条线路里,有两条线路的堵车概率在工作日早高峰超过60%,而调度员的排班表上没有考虑这个变量。这意味着如果系统能接入实时路况数据,光是避开早高峰这一项,就能省下15%的油耗。
他在笔记本上写了一行字:核心思路:不是"让算法排车",是"让算法理解路"。
第二天,林知行开始写代码。
他用了一种他在排课系统上验证过的方法——分层调度。先根据历史数据给每条线路生成一个"最优车辆池"(哪些车最适合跑哪条线),再根据当天的实时约束(载重、维修、司机出勤)做二次匹配。
核心算法不复杂,但数据清洗花了大半天。王总公司的数据格式跟长沙超市的一样混乱——有些司机用纸质记录,有些用Excel,有些用微信群截图。方小满帮忙把截图里的数据一条条录进去,录到晚上十点,眼睛都红了。
"这活该让周然干,"方小满揉着眼睛说。
林知行没接话。他盯着屏幕上的一行代码——一个循环嵌套,外层遍历线路,内层遍历车辆,约束条件用if-else叠加。
逻辑清晰,结构干净。
他在本地跑了一组测试数据——过去三个月的调度记录做回测。算法给出的调度方案和人工方案对比,总里程减少了23%,油耗减少了18%。
准确率89%。
剩下那11%的误差,主要是因为算法无法预测临时堵车和突发维修——这两项属于不可控变量,需要接入实时数据才能解决。
林知行把测试结果截图发给方小满。
方小满过了三分钟回了一条消息:牛逼。这个数字拿去演示够了。
林知行盯着"89%"看了几秒,然后关掉测试窗口,继续优化代码。
他没有告诉方小满的是——这89%的准确率,是用过去三个月的历史数据回测的。历史数据是干净的、完整的、可预测的。
真实世界的调度,比历史数据脏得多。
演示安排在周一上午十点。
王总的公司在长沙郊区的一个物流园区,三栋仓库、一个调度中心、一个停车场。停车场里停着二十多辆货车,有些在装货,有些在等出车指令。
调度中心是一间不大的办公室,墙上贴着五张线路图,每张图上用不同颜色的笔标注了限速路段、收费站位置、加油站分布。线路图旁边是一块白板,上面写满了当天的调度安排——哪辆车几点出发、走哪条线、几点到。
白板上的字迹潦草,有些地方被擦掉重写了三四遍。
王总五十出头,头发花白,穿着一件旧的冲锋衣,看起来更像一个长途货车司机而不是物流公司老板。他旁边站着一个四十来岁的男人,介绍说是运营总监,姓李。
林知行打开笔记本电脑,接上投影仪。
"王总,李总,"他说,"我们先看一下过去三个月的调度数据。"
投影仪亮了。屏幕上跳出一张数据面板——三十辆车的历史轨迹、油耗数据、线路匹配度评分。
"我们用这些数据训练了一个调度模型,"林知行说,"回测准确率89%。意思是,如果用我们的算法重新排过去三个月的调度,总里程可以减少23%,油耗减少18%。"
王总的眼睛亮了一下。
"18%?"
"对,"林知行说,"主要是两个优化点。第一,避开早高峰堵车路段。你们现在的调度员排班没有考虑实时路况,我们的算法接入了地图API,能根据时间段自动调整路线。第二,车辆匹配优化。你们有三辆老车油耗特别高,如果只跑短途线路,可以省不少油。"
王总转头看了李总一眼。李总点了一下头。
"演示一下实际排车?"王总说。
林知行切换到调度界面。
"好。假设明天——周三,五条线路都要跑。我输入今天的车辆状态和线路数据,让算法自动生成明天的调度方案。"
他敲了几下键盘,算法跑了起来。
三秒后,屏幕上跳出一张调度表——三十辆车的分配方案,每辆车的出发时间、线路、预计到达时间、油耗预估。
表的底部有一行汇总:总里程:1,247公里 | 预计油耗:892升 | 节省比例:19.3%
王总盯着那张表看了十几秒。
"这个数字,"他指了指节省比例,"准吗?"
"回测是准的,"林知行说,"实际运行还需要一到两周的数据积累来微调。"
王总点了点头,没有立刻说话。
李总在旁边看着那张调度表,忽然开口了。
"林总,我问一个问题。"
"您说。"
李总指了指调度表上的一行——
沪昆高速段:张建国(车牌湘A·38762)| 出发时间 06:30 | 预计到达 14:20
"张师傅走沪昆高速?"
林知行看了一下数据。"对,张师傅的车油耗最低、车龄最短,沪昆高速是五条线路里最长的,需要一辆状态好的车。算法匹配的结果是张师傅最合适。"
李总沉默了两秒。
"张师傅的老婆今天生孩子。"
林知行的手指在键盘上停住了。
"他今天请了假,"李总说,"但他明天也想休息一天。他不想走长途——沪昆高速单程八小时,来回就是一整天。他想留在家里陪老婆孩子。"
办公室里安静了两秒。
林知行的脑子里在飞速运转——
张师傅请假的数据,没有录入系统。
他老婆生孩子这个变量,不在任何数据库里。
算法不知道。
算法只知道张师傅的车油耗最低、车龄最短、适合跑最长的线路。算法不知道张师傅是一个有老婆、有孩子、有家庭需求的人。
"这个好解决,"林知行说,声音比他预想的平稳,"我在系统里加一条人工干预规则——调度员可以在算法推荐的基础上手动调整,比如把张师傅的沪昆段换给李师傅,系统会自动重新计算匹配度。"
他打开代码编辑器,现场改了几行代码。
三分钟后,调度表刷新了——张师傅的沪昆段换成了李师傅(车牌湘A·41203),总油耗从892升变成了907升,节省比例从19.3%变成了18.1%。
"看,"林知行指着屏幕,"损失了1.2个百分点,但张师傅可以休息。"
李总点了一下头。
"这个功能好,"他说,"我们调度员经常要临时改车。你这个手动调整功能,如果能做得再方便一点——比如点一下就能换车、自动算成本变化——我们就能用。"
王总在旁边没有说话,但他的手已经伸向了桌上的合同。
离开物流园区的时候是中午十二点半。
方小满在停车场里蹦了两下。
"签了?"
"没签,"林知行说,"王总说回去商量一下,下周给答复。"
方小满的脸垮了一秒,又绷住了。
"但李总说了'我们就能用',"他说,"这四个字比合同还管用。"
林知行没有接话。他走到车旁边,拉开车门,坐进副驾驶。
方小满发动了车,开出停车场。
"你怎么不高兴?"他从后视镜里看了林知行一眼,"89%准确率,现场改代码,李总那句'我们就能用'——这不挺好的吗?"
"挺好的,"林知行说。
"那你干嘛一脸——"
"我想回去了,"林知行说,"帮我订今天晚上的高铁。"
方小满看了他一眼,没有再问。
回到北京的时候是晚上九点。
林知行没有直接回合租房。他在小区门口的便利店买了一瓶水,坐在路边的台阶上,从背包里翻出了那个三块钱的笔记本。
他翻到新的一页。
没有犹豫,写了一行字——
算法能算出最优路线,但算不出人心。
他盯着这行字看了很久。
然后在下面又写了一行——
张师傅的老婆今天生孩子。这个变量不在数据库里。
他把笔放下,把笔记本合上,攥在手里。
台阶上坐了两分钟,手机震了。方小满的消息:
高铁到了吗?
林知行回了一个字:到了。
然后他站起来,往合租房走。
合租房的灯亮着。方小满在折叠桌前坐着,面前摆着两碗泡面,一碗已经泡开了,另一碗还没倒水。
"饿了吧,"方小满把没倒水的那碗推过来。
林知行坐下,把水壶拎过来倒上。
两个人吃面,没说话。
方小满先吃完了,把碗推到一边,擦了擦嘴。
"说吧,"他说,"你今天在王总办公室里那个表情,我见过。"
林知行抬起头。
"什么表情?"
"就是那种——表面在笑、心里在算的表情,"方小满说,"李总说完'张师傅的老婆今天生孩子'之后,你笑了一下。但你的眼睛没笑。"
林知行的筷子停了。
"你知道我在算什么?"他问。
方小满摇头。
"我不知道。但我知道你在想什么。"
"想什么?"
"你在想——这跟排课系统上犯的错,一模一样。"
林知行盯着方小满看了两秒,然后低下头,继续吃面。
碗里剩最后几根面条的时候,他放下筷子。
"对,"他说,"一模一样。"
方小满等着。
"排课系统上线的时候,"林知行说,"三个校区的老师集体投诉——系统把怀孕的女教师排了满课表。因为系统里没有她们的健康信息。AI不知道她们怀孕了,AI只看课表冲突和教学时长。"
他顿了顿。
"今天又犯了同样的错。算法推荐张师傅走沪昆高速——八小时的长途。算法不知道他老婆今天生孩子。算法只看油耗、车龄、线路长度。"
方小满点了点头。
"所以你当场加了手动调整的功能。"
"对,"林知行说,"补得很快。三分钟。"
方小满看着他。
"那为什么这次又犯了?"
林知行的嘴巴张开,又合上。
他想说什么——想说"这个问题没法避免",想说"人的信息不可能全部录入系统",想说"算法的边界就是这样"。
但这些话他都没有说。
因为他知道方小满问的不是这个。
方小满问的是——你三年前在排课系统上就犯过同样的错,你当时写了人工审核层,写了"在AI做决策之前必须有人类检查数据完整性",你甚至在笔记本上记了"人的问题。补。"
三年了。
你补了什么?
林知行盯着桌面上那碗吃了一半的泡面,很久没有说话。
方小满没有催他。
窗外的车流声透过玻璃传进来,四环路上的车灯在天花板上划出一条一条的光痕。
"我以为我已经学会了,"林知行说。
他的声音很轻,像是在跟自己说。
"排课系统出问题之后,我加了人工审核层。灵犀的可信度评分,我加了解释层。开源之后的产品,我加了纠错反馈。每一层都是在补——补算法看不见的东西。"
他顿了顿。
"但今天在王总办公室里,李总说'张师傅的老婆今天生孩子'的时候,我愣了两秒。"
方小满看着他。
"两秒不多。"
"不多,"林知行说,"但这两秒说明一件事——我没有在写代码的时候就想到这个问题。我是等到问题出现了才反应过来。"
他抬起头,看着方小满。
"排课系统的教训,我以为我学会了。但其实我只是学会了'出了问题怎么补'。我没有学会'在问题出现之前就看到它'。"
方小满沉默了。
林知行把笔记本翻开,翻到刚才写的那一页。
算法能算出最优路线,但算不出人心。
张师傅的老婆今天生孩子。这个变量不在数据库里。
他在这两行字下面又加了一行——
三年了。我还是在等别人告诉我变量是什么。
方小满伸过头看了一眼,没有评价。
两个人又沉默了一会儿。
"那怎么办?"方小满问。
林知行把笔记本合上。
"不知道,"他说,"但我知道一件事——光加规则不够。加一条规则补一个洞,永远补不完。"
他站起来,走到窗边。
"得换一种方法。"
"什么方法?"
林知行看着窗外。四环路上的车灯还在流动,每一辆车都有自己的目的地、自己的时间表、自己的故事。算法能把这些车排成最优的线路,但算法不知道每一辆车里坐着什么人、那个人今天经历了什么。
"我不知道,"他说,"但我知道我还没学会。"
他转过头,看了方小满一眼。
"这是好事还是坏事?"
方小满想了想。
"坏事,"他说,"因为你都创业148天了,还在犯三年前的错。"
他顿了顿。
"好事,因为你至少知道自己还没学会。最怕的是那种觉得自己已经学会了的人。"
林知行没有说话。
他回到折叠桌前,把泡面碗收拾了,走到厨房洗碗。
水龙头哗哗响着,他盯着碗里的泡沫,脑子里在转——
排课系统的怀孕女教师。灵犀的外包标签。长沙门店的数据质量。今天张师傅的老婆。
每一次,都是算法看不见的东西。
每一次,都是别人告诉他之后他才知道。
每一次,他都以为自己学会了。
每一次,他都没有。
他把碗冲干净,放到沥水架上。
回到客厅的时候,方小满已经进卧室了。门半掩着,里面传来方小满翻被子的声音。
林知行在折叠桌前坐下,把笔记本翻到新的一页。
他想了很久。
然后写了一行字——
算法能算出什么?
他在下面画了一条线。
线的左边,他写了:最优路线、油耗、匹配度、准确率。
线的右边,他写了:人心、情绪、家庭、选择。
两列之间,他画了一个箭头,从左指向右。
箭头旁边,他写了一个字:补。
然后他把"补"字划掉。
在旁边重新写了一个字:换。
他盯着这个字看了很久。
换什么?怎么换?用什么换?
他不知道。
但他知道,光靠算法——不管多准确的算法——永远算不出张师傅今天想陪老婆孩子。
这不是技术问题。
这是视角问题。
他把笔记本合上,关掉灯,躺在折叠桌旁边那张临时搭的行军床上。
黑暗里,他盯着天花板。
天花板上什么都看不见。
但他知道,方小满贴在墙上的那张A4纸还在——团队稳定倒计时:90天。
现在是第148天。
倒计时87天。
林知行闭上眼睛。
他没有睡着。
脑子里在跑一个循环——
张师傅。沪昆高速。八小时。
老婆。生孩子。陪一天。
算法。89%。最优解。
人心。不在数据库里。
他把这个循环跑了十几遍,每一遍都卡在同一个地方——"人心不在数据库里"。
凌晨两点,他翻了个身。
行军床的弹簧吱嘎响了一声。
黑暗里,方小满的声音从卧室传出来——还没睡。
"还在想?"
"嗯。"
"想出来了吗?"
"没有。"
方小满那边安静了两秒。
"那就明天再想。"
林知行没有回答。
他闭上眼睛。
但"算法能算出什么"这个问题,像一行没有注释的代码,一直跑到了天亮。
(本章完)