程序还是要尽量开源。
这句话说出来,好像并不新鲜。可真正做过科研计算的人,大概都知道,它并不是一句轻飘飘的口号。一个程序写到能够稳定运行,背后常常有很多年琐碎的劳动。公式推过,积分算过,边界条件试过,输入文件改过无数遍,夜里盯着屏幕上一行报错,反复怀疑是程序错了,还是自己哪里想错了。到最后,程序终于跑通,人对它便难免有一点私心。
像亲手打磨的一件器物,虽不名贵,却舍不得随便递给旁人。
许多科研工作者也是这样。好容易写了一个计算程序,便小心收着,掖着藏着。外人问起来,文章可以给,公式可以讲,图也可以画给你看;至于源码,便像箱子最底层的东西,轻易不肯拿出来。生怕别人偷去了,生怕别人很快做出更多体系,生怕自己多年积累,被人一下载、一运行,就变成了别人的成果。
这种心情,我并不陌生。
科研评价体系并不总是宽厚。文章、项目、排名、引用,都在那里压着。一个课题组若好不容易有了自己的程序,便容易把它看成家底。家底薄时,更舍不得亮出来。可是科学若总靠这样藏着,路往往也会越走越窄。
一个方法真正有生命,不只在于它的理论形式漂亮,也在于它能不能被别人使用、检验、修正和继续发展。
我想到一个切身的例子。
用变分法处理电子与分子散射,过去大体有几条重要路径。
- V. McKoy 等人创建了多通道 Schwinger 法;
- P. Burke 等人创建了 $R$-matrix,也就是 \(R\) 矩阵方法;
- 还有我的导师在美国的导师 C. McCurdy 等人创建的 Complex Kohn,也就是复科恩方法。
这三种方法,各有来路,也各有自己的气质。
若只看一九七九年国际学术年会时的情况,$R$-matrix 法的结果并没有后来那么显赫,甚至远远谈不上压过另外两个方法。那时若有人站在会场里,凭当时的论文和报告来判断,也许未必会觉得 $R$-matrix 日后会有今天这样的局面。学术的发展有时很像一条河,起初几股水都差不多,甚至有的还更急一些,后来能不能汇成大流,常常还要看它途中接纳了多少支流。
今天再看,$R$-matrix 法几乎有了一统江湖的气象。
原因当然不止一个。Burke 一系的持续推进,Tennyson 等人的大量工作,电子碰撞、光电离和分子过程等实际问题的需求,都在里面。但我始终觉得,其中最要紧的一点,是他们把自己开发的 $R$-matrix 程序包公开在网上,让别人可以自由索取,也可以继续开发。
这一点看似平常,其实极难得。
理论文章公开,并不等于方法真的公开。做过计算的人都知道,从一篇文章到一个可用程序,中间隔着很长的路。一个矩阵元怎样排布,一个积分怎样截断,一个边界面条件怎样落实,一个数值不稳定的地方怎样处理,文章里常常只写几句话。真正的经验,往往藏在源码里,藏在注释里,藏在输入文件里,也藏在那些失败过很多次之后才留下来的默认参数里。
程序不公开,外人即使读懂理论,也只能站在门口。
$R$-matrix 法公开以后,事情便不一样了。一个学生或研究者可以下载代码,跑一个简单例子,看输入怎样变成输出;也可以沿着程序读回理论,知道某个符号在论文里出现时,到了计算机里究竟怎样落地。若遇到问题,还能修改、比较、扩展。有人补一个 bug,有人加一个模块,有人把它用到新的体系,有人写新的文档。每个人添的柴也许不多,可柴多了,火就自然旺起来。
众人拾材,火焰才高。
另外两个方法,就显得有些可惜。
Complex Kohn 法理论上并不弱,甚至在某些问题上很漂亮。可是到了现在,除了 McCurdy 自己和他的学生,其他人几乎很少用这个方法做出好的工作。方法像一把磨得很好的刀,却长期挂在自家墙上。外人知道它锋利,也读过刀法,可拿不到刀,最后只能换一条路走。
多通道 Schwinger 法也大致如此。
这个方法后来似乎传到了巴西,Bettega 课题组用它发表了不少文章。我曾写信去请教,希望了解一些程序和实现细节,可惜没有任何回音。那种感觉,做学问的人都懂。不是怨,只是有一点轻微的失落。门在那里,里面也许有灯,你轻轻敲了几下,没有人来开。时间久了,便只好转身。
而 $R$-matrix 法给我的经验,完全不同。
我从网上下载了所有源代码,又仔细研读 Burke、Tennyson 等人的文章。许多起初不明白的地方,反而是在程序里慢慢清楚的。某一段矩阵组装,某一个边界条件,某个输入参数为什么敏感,某次收敛为什么不好,论文里未必写得那么细,可源码在那里,不说话,却很诚实。你愿意花时间,它便一点点把门打开。
后来,我竟然也可以用 $R$-matrix 方法计算实际体系,并发表了 SCI 论文。
这件事对我触动很深。
若没有公开程序,我大概只能停留在“知道这个方法”的层面。读几篇文章,了解大致思想,偶尔在综述里见到它的名字,然后把书合上。可是源码一旦在手,学习便从旁观变成了进入。你可以失败,可以查错,可以改一个参数看结果如何变化,也可以通过错误反过来理解理论。对一个研究者来说,这种进入,比单纯阅读重要得多。
所以我常常觉得,开源并不是把成果白白送人。
相反,它是让一个方法脱离最初课题组的狭窄边界,进入更长的时间里。一个课题组再强,人数也是有限的,精力也是有限的,能想到的问题也是有限的。世界上总有人会遇到你没有遇到的体系,发现你没有发现的错误,补上你来不及补的细节,提出你未曾想到的改进。程序公开以后,它就不再只是某几个人桌上的工具,而有机会成为一个领域共同使用的器物。
这样的器物,用的人越多,越有可能被磨亮。
当然,开源并不意味着没有风险。
别人可能用错,可能不署名,可能只会跑程序而不理解方法,也可能把粗糙结果匆忙写成文章。这些担心都是真实的。可解决这些问题的办法,不该是把程序锁起来,而是把文档写清楚,把引用方式说明白,把测试例子留下,把适用边界标出来。科学共同体不能靠猜疑来成长,只能靠公开、规范和反复校正来成长。
我读研究生时,见过一些相反的做法。
有些课题组的教授,不知道从哪里拷来一个程序,自己也未必完全懂,却当作宝贝一样藏着。更荒唐的是,连自己的学生都不给看源码。学生只被允许改输入文件,跑几个体系,取几组数据,画几张图,再写成文章。程序成了一只黑箱。学生站在黑箱外面,像在庙门口摇签,签落下来,便努力替它解释一番。
这样的训练,实在让人忧心。
一个学生若看不见源码,就很难真正理解方法的骨架。他不知道结果从哪里来,不知道误差藏在哪里,也不知道程序在哪些地方可靠,在哪些地方危险。久而久之,他会把计算当作操作,把理论当作说明书,把科研当作数据生产。文章也许能发几篇,人却没有真正长起来。
科学训练最重要的地方,是让人面对真实结构。
会就是会,不会就承认不会。程序错了,要知道可能错在哪里;结果不稳,要回去查近似、查基组、查积分、查边界条件。一个好的程序,若源码开放,至少给了后来者一种诚实学习的可能。它让人知道,结论不是从天上掉下来的,也不是从某个权威硬盘里神秘长出来的。它是一行一行写出来,一次一次检查出来,又被许多人慢慢修正出来的。
做物理的人,尤其该明白这一点。
自然界并不会因为我们把公式藏起来,就额外给我们优待。一个理论若真有价值,别人迟早会检验它;一个程序若真可靠,也只有放到更多问题里,才知道它的可靠究竟到什么程度。把东西藏起来,短期也许护住了一点利益,长期却常常连自己也关在里面。
许多年前,那些把程序看得比学生成长还重要的人,如今回头看,也不过是尘世间一粒灰尘。
这话说得有些冷,却不是刻薄。时间对人的小算盘一向不太客气。当年以为不得了的占有,几年后可能没人记得;当年舍不得给人看的程序,后来连编译环境都找不到;当年怕别人超过自己,最后却发现真正把自己留在原地的,正是这份害怕。
学术史不会长久记住谁把门锁得最紧。
它更愿意记住那些把路修宽的人。
开源并不能保证一种方法必然成功。有些程序公开了,也许仍无人问津;有些方法门槛太高,后来者不多;有些领域本身狭窄,火再添柴,也烧不到很远。但不开源,机会便更少。公开至少给了一种可能:远处有一个年轻人,下载了你的代码,读懂了一小段,算了一个你没有算过的体系,又把自己的修改留给更后来的人。
这条链一旦接上,人的有限工作便被稍稍延长了。
我现在越来越觉得,科研里的贡献不能只看一篇文章当时有多少引用,也不能只看某个结果是否漂亮。还有一种贡献,是留下工具,留下路标,留下别人可以继续工作的地基。这样的工作有时不耀眼,却很耐久。像一座桥,修桥的人未必天天被人称颂,可后来走过的人越多,桥的意义就越清楚。
程序尤其如此。
一套好的科学程序,如果开放、可读、可复现、可扩展,它本身就是一种学术作品。它凝结了理论理解,也凝结了数值经验;它让抽象方法变成可以动手的东西,也让后来的学生能在实践中理解理论。论文把门画出来,程序若写得好,便让人真正推门进去。
所以,若有年轻学生问我,自己写的程序该不该公开,我多半还是会劝他:能公开,就尽量公开。
公开之前,把该整理的整理好。不要把一堆临时脚本随手扔出去,也不要只放一个只能在自己电脑上运行的版本。写清楚依赖,写清楚输入输出,给几个小例子,说明适用范围,标明引用方式。做这些事很费时间,有时比自己多算几个结果还烦。可这也是科研的一部分。你希望别人认真对待你的方法,就要给别人一条认真进入的路。
一个人做研究,总不能只想着眼前那几篇文章。
文章发出来,热闹一阵,很快便会过去。真正留下来的,可能是一种方法,一个工具,一点可被后来人继续使用的诚实劳动。火若只在自己炉子里烧,当然也能取暖;可是科学的火,本来就不该只照一个屋子。
柴交出去,也许别人会添得更旺。
到那时,最初拾柴的人,并不会因此失去什么。火焰高起来,照见的是所有人。