从编程序看分析和综合,以及用于写作和做报告

最近,不得不来指导一下学生编程序。除了

  1. 给程序加执行参数(例如linux命令cp后面的文件名就是用来满足适于用任何文件的要求,例如ls后面的-a就是用来显示隐藏文件等等)来增加程序的功能而不是完成非常特定的功能,然后每次不得不去修改程序本身
  2. 运行参数包含测试功能的开关,这样测试起来简单
  3. 程序尽量要做到命令行下可执行,不要依赖于集成环境IDE,可以用makefile
  4. 变量名要有意义
  5. 程序要加上说明,看的出来每一行在做什么
  6. 合适的时候,做一下优化,例如用矩阵代替循环之类的
  7. 一般的编程,以及每一种语言,基本上都会有一些风格习惯,要稍微了解和遵循

这些基本的要求之外,最重要的是Divide and conquer的思想,也就是分解和综合的思想:把每一个程序分解成合适的步骤,每一步完成特定的功能。甚至在主程序这样的高等级程序里面,完全不应该有具体的计算,只能有每一段应该完成什么的流程;甚至在比较高级的功能性模块里面,也只能由每一段应该完成什么的流程;仅仅在最底层的程序里面才应该有具体计算,核心计算。也就是程序应该长成这样:

main{
   get some run-time parameters #meaning of every parameter
   to do task1 #what is this task, why it is needed here
   to do task2 #what is this task, why it is needed here
   to do task3 #what is this task, why it is needed here
   testcode #activated when the designated run-time parameter is called
   print results #to serve what purpose
}


task1(parameters){
   to do task11 #what is this task, why it is needed here
   to do task12 #what is this task, why it is needed here
   testcode #activated when the designated run-time parameter is called
   return something back to the calling program
}


task11(parameters){
   Realcode, core code #how this task is done
   testcode #activated when the designated run-time parameter is called
   return something back to the calling program
}

这样的程序,尽管初看起来,会云里雾里,发现,每个子程序都没有在干活啊,就是在调用下一级子程序,好像只有搞懂最底层的子程序,才能看懂这个上一级程序。但是,只要稍微习惯一下,改变一下思考问题的方式,就会发现,这样的程序比把核心程序和流程程序放在一起的,要好懂的多好懂的多。关键的思考问题的方式就是分析和综合,或者叫做Divide and conquer,或者WHWM分析方法(What,How,Why,Meaningful)。具体来说,就是,在看上一级程序例如主程序的时候,每一个子程序只要明白在完成什么功能,这个功能和当前程序的目的是什么关系,就行了。不需要取搞清楚子程序是怎么做的。也就是说,What(完成什么功能)是最主要的,然后是Meaningful(起到什么作用),How(怎么做的)和Why(为什么这样做,为什么做这个)是次要的。只有当真的需要的时候才进入下一级子程序,而且就算进入下一级子程序,还是一样,先搞清楚这个子程序下面的流程,也就是每个子子程序的功能以及它们和这个子程序的功能的关系,而不去管这些子子程序是怎么实现的,有没有更好的实现。当然,这样的阅读依赖于程序员的注释,因此,每一个功能模块,都要做好注释,完成什么功能。

记住:很多细节我们都可以不懂,只要我们懂得这个东西做了什么,在整体中起到什么作用。当然,如果我们真的想搞懂整个问题,那么,自然,底下的How和Why也是重要的。

这样来做还有什么好处呢?方便测试,方便协作。测试的时候,可以单独来针对特定的子程序,而且可以设定一个针对这个子程序具有精确解的情况来测试。协作的时候,每一个贡献者可以只管当前任务的细节,而不去管这个任务之上的子程序和之下的整合,当然,在把任务分解准确以后。

只要做好分解,不断地分解——每一次都只有流程直到不得不写下来核心程序,做好注释,做好测试,无论编程水平(例如语言包的熟悉程度、算法的创造性运用)本身多烂,都能够编出来好程序。

同样,写作和阅读的时候,也是如此:首先是整篇文章想说什么主要信息,为什么说这个;接着把整篇文章分解成一个一个的部分,每一部分说了什么主要信息和整篇文章的关系是什么;再接着,还可以把每一个部分再次分成一个一个的部分,每一步分说什么主要信息和它的上一层关系是什么。也就是在每一个层次上,问What和Meaningful的问题,然后依靠在下一层问What和Meaningful的问题来回答上一个层次的How和Why。

同样,做学术报告的时候,更加要如此:首先是整个报告想说什么,为什么说这个;接着,用什么例子或者结论来展开论证和表达这个主要信息,以及反过来,在介绍这些例子和结论的技术细节的之前一定要让你的听众明白,你为什么将这些例子和结论,它们和主要信息的关系是什么;然后,对每一个例子和结论,做同样的事情,先搞清楚需要用哪些进一步的细节来展开这些例子和结论,在具体进入这些进一步的细节的具体技术细节之前,能不能交代清楚这些细节和这些例子和结论的主要信息是什么关系。不断地重复这个分解的过程、明白起到对上一级的内容什么样的支撑作用、然后才是细节的展开。为什么要这样做?因为你的听众基本上不会一下就明白最底层的细节,每一次的封装都能够降低你的听众的记忆和信息处理负担。

当然,有的时候,这个层次会有交叉。这也是为什么要依靠概念地图——整体是层次结构,但是跨越层次的联系是最重要和核心的联系。这也是系统科学,物理学,或者说科学的核心思想之一——分析和综合。除了学习物理学、系统科学,你还可以通过练习编程来体会这个分析和综合,只要完成一个需要300行以上的程序,你就不得不体会到。任何语言都可以,但是,不要直接就是图形界面的例如VB之类的,试试C、Python、Java等,尤其是Java(接口,而不是具体程序)。

光电效应为什么能够证明光的粒子性

光电效应是一个非常著名和有历史意义的实验:在能够真实地用单光子做实验之前,这个实验就逼迫物理学家们用单粒子的视角来看光(当然,后来的进一步研究证明其实把光看成波也能够解释光电效应实验,只需要把电子的部分采用量子力学,可以Wikipedia “光电效应”)。那么,为什么是这样的呢?

这是光电效应的实验装置示意图。两片连着电源的金属板构成一个腔,光照到其中一片金属板上。当光的频率比较合适的时候,就可以测量到电流——意味着有电子从左边的金属板跑到了右边的金属板上。那么,这个电子是从哪里来的呢?这个电流的强度和电压的大小和方向、光的频率和强度有什么关系呢?这样的关系怎么理解呢?
实验发现,对于给定的金属,只有光的频率大于某个值的时候,才会有电流,不管用多强的光来照,也不管什么样的电压。也就是说,单纯改变光的强度或者电压的大小和方向,不会把没有电流的情形变成有电流的情形。如果我们按照经典波来理解光,则光的强度可以看作是介质上振动的幅度的大小。大的强度就意味着大幅度的振动,于是,就会使得电子更容易被从金属中打(激发)出来。为什么改变强度会不起作用呢?

接着,实验还发现,对于能够产生电流的光,如果我们改变电压的大小和方向,则存在着饱和电流和截止电压。饱和电流的意思就是无论我们从正面——也就是帮助电子从一个金属板跑到另一个金属板的情况——怎么加强电压,只要电压大到一定程度,则电流不再增加。在那之前,电流会一直增加。截止电压的意思是,如果我们反过来加电压,也就是阻碍电子从一个金属板跑到另一个,则当电压到达一定大小之后,电流消失。在那之前,电流会逐渐减小。也就是下图的效果。a,b,c对应着不同的光强度。我们先不管。我们仅仅盯住其中一条线来看,例如a。x轴最左边就是截止电压。y轴最上方就是饱和电流。

为什么会出现饱和电流和截止电压呢?饱和电流意味着从金属里面跑出来的电子已经完全都到达对面的金属上面去了,没有浪费。截止电压意味着从金属里面跑出来的电子一个都没有达到对边的金属上面,全都被电压(电场)阻碍了。也就是说,外加电压的改变,不会对跑出来的电子的数量有影响,仅仅改变的是电子是否容易到达对面。

这个时候,我们问,这个截止电压和什么东西有关系呢?给定金属的条件下,截止电压仅仅和光的频率有关系,和光照强度没有关系。实际上,改变光照强度的话,在给定金属和光的频率的条件下,仅仅会改变饱和电流,不能影响截止电压。于是,这个就更加说明了把光的强度看作是振动幅度的大小——这样就会更加容易把电子激发出来,是错的。

当然,正面的解释为什么需要把光子看作是一个个小球才能够理解这个现象是比较难的。不过,顺着这个光的小球的模型来解释这个现象倒是比较容易:光是一个个的小球,其本身的能量状态由其频率所决定,光的不同的强度对于给定频率的光来说表现为单位时间里面通过一个截面的这样的光小球的数量不一样;电子需要依靠从光子那里吸收的能量来从金属里面跑出来。于是,当单个光小球的能量不够让电子跑出来的时候,就没有电流产生。另外,就算小球的能量够,但是,如果加上反响的电压,则电子的能量在运动过程中会逐渐降低,因此,只要反向电压足够大,则其能量在到达另一片金属之前就消耗完毕,则不产生电流。这个足够大的反向电压就是截止电压。相应地,饱和电流的产生,则是因为给定光强度和光频率,单位时间能够产生的电子的总数就是定的,于是,增加正向电压的作用仅仅使得这些电子全都能够跑到另一片金属上,而不能增加跑出来的电子。当然,如果光的强度大,则单位时间内这样的光子多,于是跑出来的电子也会多,于是电流强度大。

这样,通过把光看作是一群小球,每个小球带着一份能量,就解释了光电效应现象,并且还发现,把光看做是介质的振动于是光的强度就是振动的幅度,不能解释光电现象(再一次强调,其实,可以的,只要把电子的运动部分量子话,也就是说,光子量子化电子经典、光经典电子量子化、光和电子都量子化,这三种方式,都可以解释光电效应,但是,光经典电子也经典,这样的模型不能解释光电效应)。

在构造前面的解释的过程中,我们用到了一点电压、电场、电流的知识,但是,更多的是实验和测量(尤其是考察其他因素都不变仅仅变化其中一个因素的时候的实验现象,作对比)、联系和对比、用数学和逻辑来构建想得通的想的明白的模型。很多时候,对科学现象的理解确实依赖于科学知识,但是,最根本的,我们需要的是去问一问为什么,去想一想是不是想得通。

光是粒子又如何,光是波又如何?

之前我们讨论了能够在很大程度上说明光是粒子的实验:光电效应为什么能够证明光的粒子性。那当然,也有大量的实验佐证光是波——把光看作是介质上的振动,然后依赖介质上的Newton力学来理解光的行为。那么,为什么光不能就是这样的东西:在解释不同的实验的时候用不同的模型呢?这样有什么不可以呢?

首先,有其他实验可以很大程度上证明光的传播不需要介质。例如Michelson-Morley实验(请自行Wikipedia之)证明如果有介质并且这个介质的运动速度通过伽利略变换进入光的传播速度的话,那么,实验结果和理论结果不符合。再例如,有实验证明光是可以在真空中传播的:你想确认一下这个事实的话,只要看一下天空,看到太阳月亮星星就是这个证明——你想中间有多少什么都没有的路光要走啊。当然,你仍然可以怀疑说,这个看起来测量起来什么粒子都没有的“真空”其实不是真空,还是有某种介质的。于是,你就可以设计一个情景来让这个“介质”有自身的速度,这时候,再来测量光的行为,就回到了Michelson-Morley实验。因此,Michelson-Morley实验很大程度上说明:光的传播不需要介质,如果有介质则这个介质很神奇——其自身运动的速度不怎么影响光的传播。

既然没有介质,那么,把光看作介质上的振动,并且这个振动的传播符合Newton定律就不太行了,那怎么来建立光的心智模型?

接着,我们回顾一下那些启发了光的经典介质波的模型的实验。例如,光的折射和反射。声波、水波都会出现折射和反射,也就是一个振动传过来遇到了界面,界面上的介质会被这个传过来的振动激发,由于是不同的介质,这个受激发的振动可能会被传播到其他方向上去。如果是同一种介质,其实也会发生这个受激发振动的事情,只不过,那个时候,跑向各个方向的受激发振动刚好相互抵消。而当存在不同介质的界面的时候,某些方向上的振动会被加强而不是相互抵消。这个把介质上的多个粒子受激发振动看作新的波源然后做叠加的做法叫做惠更斯-菲涅耳原理(其本质还是波的Newton力学),或者去看看Feynman的《QED:光和物质的奇妙理论》。当然,其实,光的折射和反射也可以用直线传播的小球和半透膜的模型来解释:把光看作小球,每次遇到半透膜(开了很多小孔的筛子?)就有可能被弹回,也有可能透过。这个称作光的随机性粒子模型(有的时候也被称作几率波粒子模型)。

那我们再来看光的干涉和衍射。衍射现象是指,在光的传播路径上,有障碍物,可是,你仍然在障碍物的后续路径上观察到了光。如果光是直线传播的小球,就不太可能有这个现象了。而波的惠更斯-菲涅耳原理就可以解释这个现象,在此略过这个解释。光的干涉现象是指来自于两个振动源的光在同时能够达到的区域会出现暗条纹和明条纹。暗条纹的意思是,对于打开任何一个光源就能够照亮的区域,当同时打开两个光源的时候,反而不变暗。当然,这个时候,对光源有一定的要求。但是,这件事情用光的粒子模型是很不可理解的:你在玩植物大战僵尸的豌豆射手或者用机枪打仗,发现,有一个地方用一个豌豆射手或者一个机枪手都可以打到,但是,当你放上两个豌豆射手或者两个机枪手的时候,就打不到了。这是不可能的事情。如果是这样,就没有火力覆盖了。

那么,把光看作是介质上的振动是怎么来理解光的干涉的呢?说一个光源传过来的振动和另一个光源传过来的振动可能在振幅上不匹配,例如一个是振动最低点也就是波谷的时候,另一个正好传过来一个振动最高点也就是波峰,正好这两个振动的矢量叠加相互抵消,于是,没有照亮。这个解释非常漂亮。

那问题来了,到底我们应该把光看作是粒子还是满足Newton定律的介质上的振动波呢?我们能不能在讨论某些实验例如折射反射光电效应的时候,把光看做粒子(当然,这时候,我们也要问这个粒子是不是满足粒子的Newton定律。问题留在这里,以后再说),而在讨论折射反射衍射干涉的时候,把光看作是满足Newton定律的介质上的振动波呢?万一遇到新的现象怎么办,用什么方式来描述?或者每次都先试试用两个理论之一的结果和实验比较一下,对上了,对这个现象就用这个理论?

第一、科学的目标是希望对于给定的现象,我们的理论模型能够给出来一个结果的预期,然后和实验相比较。因此,每次来凑一凑试一试显然是不行的。如果能够对现象做一个完善的分类,遇到现象就知道用哪一个模型,倒是也可以接受。不过,这个分类,在光这个现象上,我没有见过。

第二,科学的原则有一条,希望用更少的并且相互不冲突的更具有一致性的理论来解释更多的现象。因此,用两条看起来相互冲突的理论来解释同一种东西的不同的现象是不够的,就算上面提到的完善的分类存在的话。而且,将来,我们会看到,有一个光的新的理论,它能够同时解释上面所有的现象。

顺便,我们怎么知道是同一种东西呢?只要我们做实验的时候产生光的机制是一样的,然后用来做以上两类实验就可以。另外,在这里,我特意扔掉了光的波的模型,而用更加复杂的“满足Newton定律的介质上的振动波”的模型。将来我们会知道新的模型还是一个光的波的模型,只不过不符合Newton定律,而且是振幅波,而不是几率波。后面为了语言的简单,我把这个“满足Newton定律的介质上的振动波”的模型简称为经典波模型。

那么,到底怎么办?什么样的模型可以即具有粒子性,也就是确实是一颗一颗打过来的,不会再一次把能量分离成为某个最小单位以下的,强度增加就意味着增加粒子数量的,这样的粒子,还具有波性,也就是可以发生干涉和衍射的这样的波?

再一次提醒注意这个干涉的不可思议性:如果我们用一颗一颗粒子来解释的话,就意味着有一个地方打开两个粒子源中的任意一个粒子源的时候粒子能够到达,但是同时打开粒子却不能达到。

更进一步,这个实验还可以这样做:保证在整个实验中每次仅有一个粒子,也就是一份能量,在整个实验环境中。具体的做法大概来说是这样,制备一个单光子光源,在这个光子的光路上放上分光的仪器使得这个光子可能走两条路中的一条——例如放置一个双缝或者一个偏振分束器。

这样来做,这个实验结果就更加不可思议了:空间中每次只有一个粒子,如果说不能到达某个一条路就能到达的点,也就是说,好像这两条路上的光子影响了彼此,可是,真的仅仅有一个光子啊,自己和自己是怎么影响怎么抵消的呢?回到波的模型,可以把波看作是振动分成几个部分传播到不同的路径上,将来再一次合起来,自然就可以相互抵消。可是,光子不能再一次分成更小的能量单位啊!

注意,把光看作几率波的模型也不能解释这个单光子干涉现象:要么走路径1,能够到达;要么走路径2,还是能够到达,则合起来就是能够到达,绝对不会出现不能到达的情况,除非路径1和路径2的“几率”是一个矢量,能够想振动幅度一样被加起来。

这里最大的矛盾,或者说将来的出路,就在于:一方面,光子不能分成更小的单位,不能同时走很多条路径,因此不能把不同路径上的“振动幅度”像经典波一样叠加起来;另一方面,在数学上,经典波的把来自于不同路径上的同时传播过来的波相互叠加起来,确实能够描述实验现象。

怎么办?难道我们需要一个在数学上满足“波的叠加”的但是在物理上是一个个不可再分的小球的模型来理解光子的行为?一个个的小球怎么会具有波呢?除了看作概率,就像前面的半透膜,可是概率解释不了干涉,还可以看作波,怎么可能呢?

实际上,光的心智模型正是这样的满足“波的叠加”的小球。有更多的实验会提出来挑战很大程度上说明,只有这样的模型,才能够解释这些实验现象。例如,这几个实验:
能看到光是多么神奇的事情啊
光过玻璃是一件多么神奇的事情啊
光过三个偏振片和男人女人过三道门的对比

Feynman说过,只要你能够明白双缝干涉,那么,你就明白了量子力学,并且如果你没有被量子力学苦恼过,那么,你就是不明白量子力学,更有你只要宣称明白了量子力学,那么,你就没有明白。

学习量子力学主要就是为了搞清楚为什么这个理论是这个样子的,理解上的主要困难在哪里,而不是仅仅学会怎么算。就像Feynman在《QED:光和物质的奇妙理论》,《Feynman物理学第三卷》以及吴金闪的《二态系统的量子力学》里面所强调的一样。怎么算,不好意思,你需要至少学习一个理论物理专业的硕士,甚至博士。

具体现象的知识固然有意义,但是,本文最大的目的是跟你一起从具体的科学现象的思考中体会什么是科学,体会量子力学的神奇和困难之处。

吴金闪简介

最近受读书人“逼迫”要给我自己做一个比较完整的介绍。尽管十分不愿意,不过,整理一下也好,索性就把整理的东西也发在这里得了。

这是我经常用的一个文字版简介:吴金闪,毕业于The University of British Columbia‎和北京师范大学,任职于北京师范大学系统科学学院。研究工作涉及量子输运(非平衡统计)、量子力学基本问题、量子博弈、博弈论、投入产出分析、科学学、理解型学习,系统科学。一直在实践融合学科边界的研究和教学。

下面是一个以上信息的图形的版本。

其中,我还加入了我的邮件签名档:
Live to make a difference(活着就是为了搞出点不一样)
Be ambitious, be determined (有野望,持之如初)
World spins on dreamers like you(世界因你的梦想而转)
See through connections(洞澈联系)
Teach Less, Learn More (教的更少,学得更多)
Learning for understanding the world and ourselves(为了理解世界和自己而教和学)
Don’t tell me facts, let me think; Don’t teach me knowledge, let me learn (不要告诉我事实,让我想想;不要教给我知识,让我学习)

以及我认为自己的优势或者说立足之本,除了一些知识,更加重要的是:我喜欢并且善于去用来自于科学的方式(尊重测量、用数学来构建模型和表达思考、尽可能少的假设和模型来解释尽可能多的现象,不断地追问为什么并且在合适的地方切分)问新的问题或者给问题提出来新的分析方法,而且在这之中,最重要的就是通过仔细思考这个问题内部因素之间的关系,来找到具有类似的关系的其它问题并解借鉴这样的问题的分析方法。这也就是系联性思考。这,再加上运用系联性思考来达到看到树木更看到森林,就是系统科学的典型思维方式。

大部分这些思维方式,都是来自于物理学的训练。因此,顺便,推荐所有对科学,不管是自然的科学还是社会的科学,感兴趣的学习者,无论如何,都学点物理学,而且,要从学习物理知识中学会体会物理学的大图景:典型对象、典型问题、典型思维方式、典型分析方法、和世界以及其他学科的关系。

如果你想了解我更多,有网站的渠道:“吴金闪的工作和思考”、“Big Physics研究小组”、“汉字结构网”、“吴金闪在北京师范大学的主页”,有书:《教的更少,学得更多》、《量子力学》、《系统科学导引》,有微信公众号“为了理解而教和学”,有视频课程《系统科学导引——概论》和《系统科学导引——数理基础》,还有读书人讲书的视频:“为增加对世界的理解而读书”、“网络科学”、“链接”、“爆发”、“二态系统的量子力学”、“系统科学导引”、“物理定律的本性”、“QED:光和物质的奇妙理论”、“物理学的进化”;有研究论文,见“吴金闪在北京师范大学的主页”。

获取sci-hub数据

sci-hub是学术论文检索网站,提供了从文章doi等信息找到文章下载地址(这些地址又被libgen网站收集和保存)的信息。当然,这些文章基本上是有版权的。因此,实际上sci-hub和libgen是法律的边缘:没有直接保存原文(有的文件可能有原文,不清楚),但是提供了原文下载地址的集合。不过,我真的很喜欢这个网站的理念:知识应该属于全人类,应该尽量方便大家的获取。当然,也应该给写作、制作和出版这些知识的载体——也就是文章和书——的人一些利益。所以,我自己的文章和书的处理方式是在网上免费提供没有经过出版社处理的全文,但是经过出版社处理的文档,我不管。

最近纯粹出于好奇和学术研究兴趣,想看看sci-hub和libgen这个网站在促进学术交流上的效果,还想顺便用来匹配一下一堆我们自己有的文章的doi,就去找了找下载获取sci-hub和libgen数据的方法

首先,这个数据分成三个部分:第一、保存下载地址的文件,通常是torrent文件。第二、保存文章题录数据(metadata)的文件,通常是MySQL database dump文件。第三、提供这个网站的服务的源程序。第三部分仅仅在制作镜像的时候需要使用,就不需要下载了。这三部分文件都可以直接从libgen的主页上获取。

其次,获取了文件之后,需要从torrent文件的信息里面来下载和存储相应的文件。

接着,需要把题录数据和下载的文章对应整合起来。

最后,内部使用,也可以把libgen的服务系统建起来,或者自己做一个检索系统。