先写一个快速原型

Terence Tao 2007-05-14

先写一个快速原型

最好的性能改进是从不工作状态到工作状态的转变。 ——约翰·奥斯特豪特

发现数学问题的解决方案只是战斗的一半。实际上把你发现的论证正式写下来也可能是一项艰巨的任务,特别是当论证很长且没有文献中现有模型可借鉴时。虽然论证的每个细节对作者来说可能都很清楚,但论证的整体结构可能不会立即显而易见。特别是,通常很难在论文的大部分内容已经写完之前就做出关于以下内容的重要决定:

到那时,组织或符号的任何更改通常都变得难以实施。(过去很多时候,我在没有充分考虑整体结构的情况下开始写论文,花了很多时间建立一些我认为重要的引理,结果后来意识到实际上并不需要这个引理,从而浪费了大量时间。)

我发现软件工程中的快速原型技术有助于缓解这些困难。根据这种技术,人们不按线性顺序写论文,也克制住先写最简单或最直接部分的诱惑。相反,人们按照以下顺序写论文。

快速原型过程

第一阶段:骨架

首先,尽可能快地写出一个精简的”骨架”或”原型”;这个原型包含所有关键引理、命题和定理的(近似)陈述,以及所有关键定义,但所有证明都被省略,或者用非常不正式的”给自己看的笔记”来勾勒。在写作过程的主要阶段,优先考虑的是把”大局”弄对——论文的逻辑组织,以及每个重要命题或符号的一些半精确描述。这些描述的模糊性将允许人们轻松地移动论证的部分内容来改进这个大局。

第二阶段:精确陈述

在组织达到满意程度后,第二个目标是写下足够的证明,以便能够使所有引理、命题、定理和定义的陈述变得精确。

第三阶段:关键论证

一旦完成这一点,第三个目标是仔细写出论证的关键部分,例如从两个先前的关键引理推导出一个关键命题,以确保结构确实按预期工作。

第四阶段:常规填充

最后,填充论文的所有”常规”方面,例如标准引理的证明,或主要定理的快速应用。通常,到这个阶段,论文中剩余的空白是如此不连贯,以至于基本上可以按任何顺序填充。这也是**写引言** 和类似 论文动机 的好时机。

实际实施技巧

任何不影响大局的决定都应该推迟到这个过程的后期。例如,如果你有一个小量,可能等于x或者可能是y,但还不知道确切是哪一个,你可以暂时写”令???”,并在证明中使用???作为这个量的占位符,直到你到达证明中确切弄清楚???应该是什么的点,那时你可以编辑单行来完成证明。(与此相对的是在证明中的两打地方写x,然后在写作过程的后期发现必须回去把这两打地方中的x改为y(以及x^2改为y^2等)。即使有现代的搜索替换工具,这也可能是一项令人恼火的耗时任务。)

协作好处

这种方法的一个好处是它可以与合著者分工。例如,一位作者可以写出证明的非正式草图,省略许多细节,然后另一位合著者可以调整组织和符号,然后填充细节,然后第一位作者可以审阅论文并添加一些评论和写引言。许多其他排列也是可能的;这在很大程度上取决于协作的性质。使用版本控制软件(例如 Subversion)可以极大地促进这个过程,我建议投入一些时间学习如何使用这类软件(例如从这个链接开始)。

写作过程中的想法管理

当你在写论文的某一部分时,经常会得到关于如何处理论文另一部分的好想法;例如,在写下引理时,可能会有一个例子或评论的想法来阐明该引理。当这种情况发生时,我不建议忽略那个想法,也不建议放下当前正在做的事情来完全充实那个想法;相反,花一分钟时间在论文的相关位置为那个想法写一个”存根”(只需足够在回到那个位置时唤起记忆),然后回到之前正在做的事情,以免打断你的注意力或动力。然后可以暂时安全地忘记那个想法,在写作过程更合适的阶段,在闲暇时重新审视它。

注意事项和替代方案

快速原型策略通常很难完美遵守,我必须承认有时(特别是对于较短的论文)我采取非常不同的方法,先写论文”容易”和”有趣”的部分(例如引言,或一些简单的引理),并试图利用产生的动力来快速写出论文的其余部分。如果你非常确信论文的大规模结构将如何安排,这种方法往往效果很好,但当我在写作过程中发现完全不同的组织方式会好得多时,我后悔使用了这种更仓促的方法。

相关阅读

关于应用于阅读论文这一对偶问题的类似技术,请参见此页面

Write a rapid prototype first

The best performance improvement is the transition from the nonworking state to the working state. (John Ousterhout)

Discovering a solution to a mathematical problem is only half of the battle. Actually writing down the argument that you’ve discovered formally can also be a daunting task, especially if the argument is lengthy and is not modeled on an existing one in the literature. While every individual detail of the argument may be clear to the author, the overall structure of the argument may not be immediately obvious. In particular, it is often difficult to make the (important) decisions about the organisation of the argument, and selection of good notation, until a large part of the paper is already written, at which point any changes in the organisation or in the notation often become painful to implement. (Many times in the past, I have started to write a paper without devoting enough thought to the overall structure, and spent a lot of time establishing some lemmas which I thought were important, only to realise later that one did not actually need the lemma, thus wasting quite a lot of time.)

I found that the technique of rapid prototyping from software engineering is useful in ameliorating these difficulties. According to this technique, one does not write the paper in linear order, and one also refrains from the temptation of writing the easiest or most straightforward portions first. Instead, one writes the paper in the following order.

  1. First, one writes a bare-bones “skeleton” or “prototype” of the paper as quickly as possible; this prototype has the (approximate) statements of all the key lemmas, propositions, and theorems, as well as all key definitions, but all the proofs are omitted, or sketched in very informal “notes to self”. At this primary stage of the writing process, the priority is to get the “big picture” right – the logical organisation of the paper, and some semi-precise descriptions of each important proposition or piece of notation. The fuzzy nature of these descriptions will allow one to easily move parts of the argument around to improve this big picture.
  2. After the organisation is completed to one’s satisfaction, the second objective is to write down just enough of the proof so that one can make the statements of all the lemmas, propositions, theorems and definitions precise.
  3. Once this is done, the third objective is to carefully write the key portions of the argument, for instance deducing one key proposition from two previous key lemmas, to make sure that the structure actually works as expected.
  4. Finally, one fills in all the “routine” aspects of the paper, such as proofs of standard lemmas, or a quick application of the main theorem. Usually, by this stage, the remaining gaps in the paper are so disconnected that they can be filled out in basically whatever order one pleases. This is also a good time to write the introduction and similar motivational sections.

Any decisions which do not impact the big picture should be deferred until late in this process. For instance, if you have a small quantity which is probably going to equal or maybe , but do not know exactly which it is yet, you could write “let ” for now, and use as a placeholder for this quantity until you get to the point in the proof where you figure it out exactly what??? should be, and which point you can edit a single line to complete the proof. (Contrast this with writing in two dozen places in the proof, then discovering much later in the writing process that you have to go back and change to (and to , etc.) in those two dozen places. Even with modern search-and-replace tools, this can be an irritatingly time-consuming task.)

One nice feature of this approach is that it can be divided with a coauthor. For instance one author may write an informal sketch of the proof, with many details omitted, then the other coauthor may tweak the organisation and notation, and then fill in the details, and then the first author might then review the paper and add in some remarks and write the introduction. Many other permutations are possible; it depends very much on the nature of the collaboration. Using version control software (e.g. Subversion) can facilitate this process immensely, and I recommend investing some time in learning how to use such software (e.g. starting with this link).

While one is writing one part of the paper, one often gets some good ideas regarding what to do for another part of the paper; e.g. when writing down a lemma, one may have an idea for an example or remark which will illuminate that lemma. When that happens, I do not recommend ignoring that idea, nor do I recommend dropping what you are currently doing to fully flesh out that idea; instead, devote a minute to write down a “stub” for that idea in the relevant location of your paper (just enough to jog your memory when you return to that location), and then return to what you were doing before, so as not to break your concentration or momentum. That idea can then be safely forgotten about for the moment, and revisited at one’s leisure, at a more appropriate stage of the writing process.

The rapid prototyping strategy is often hard to adhere to perfectly, and I must admit that sometimes (especially for shorter papers) I take a very different approach, writing the “easy” and “fun” parts of the paper first (e.g. the introduction, or some simple lemmas), and try to use the momentum generated to then write the rest of the paper quickly. This tends to work well if one is very confident as to how the large-scale structure of the paper will be arranged, but I have regretted using this hastier approach when I found, halfway through the writing process, that a radically different organisation would have been much better.

For the analogous technique applied to the dual problem of reading a paper, see this page.