知道如何为TCS编程有多重要?


66

来自更数学的背景,我从未真正学会过编码。我正在TCS攻读博士学位,许多人对我对编程(以及一般计算机)了解甚少感到惊讶。我可以用伪代码编写算法,但是我真的不知道任何编程语言。

我可以想象有一天我可能必须为我的工作实现一些算法,但是我可以等待这一刻吗?还是还有其他东西?

知道如何在TCS中编码(在不直接涉及编程的领域中)有多重要:是否有某些原因可能会使CC理论家(例如)知道如何编码?值得花费大量时间学习如何编码吗?如果有的话,是否有更适合的编程语言类别(函数式,命令式,面向对象..)?


12
您应该已经编写了一些程序,以便编写有意义的代码,即确定的,反映运行时间的伪代码。数学家通常都不做。另外,如果您想实际使用自己开发的理论,那么您很有可能必须实施一些东西。对于语言,最好学习一些功能。C的性能不错,但在许多方面却很难推理和混乱。(如您所见,YMMW)
拉斐尔

6
我同意“数学家通常都不做”。描述数学算法的数学家是否曾经真正编程过的一个简单测试是问“ 给出X ... 到底是什么意思?”。
Jeffε

4
编程,那是什么?定理是我的程序。烹饪程序与烹饪工艺不同。抱歉,超过20年我无法读取任何程序代码。实际上,我讨厌这种“在PC上实现”的混乱局面。(这种表示法已经病倒了。)Euclid无法编程。然而,他做了几个世纪的节目。
Stasys

6
@StasysJukna:Euclid实际上是一个非常糟糕的程序员。他不仅从未实现过自己的算法,甚至从未手动在中等复杂的测试用例上运行它们。
Jeffε

3
@Jɛff E:是的,Euclid是一个cr脚的程序员,我想说的正是这个。在TCS中,我们倾向于不区分烹饪书籍和公鸡艺术。欧几里得可以。我非常尊重可以编程的人。但是我不认为此功能意味着“ TCS中只有一个CAN”。它不会受伤。
Stasys

Answers:


55

理论计算机科学是一个广阔的领域,编程的重要性取决于您在TCS中所做的工作。我将提到编程可以帮助您的两种方式,但并不意味着这是唯一的方式。

首先,如果您针对具有实际重要性的问题设计算法,那么实现您的算法并将代码提供给其他人可能是一大优势。例如,凸包问题出现在许多领域,人们用诸如软件包CDD通过公明福田和LRS由大卫·阿维斯来解决这个问题。如果他们只在论文中发表算法,那么使用该算法的人可能会更少。更多的用户意味着更多的反馈,可能还会有更多的合作机会,这是无价的。

其次,即使您不使用算法,编写一次代码也可以帮助您在适合于数值计算的情况下测试简单的猜想。例如,如果您想知道三个正定矩阵的乘积是否始终具有正迹线,那么很容易编写代码以对2×2或3×3个正定矩阵的一些随机选择进行测试,并找到一个反例。尽管您并没有宣传自己编写了任何程序来测试这种猜想,但编程可以节省那些徒劳无益地试图证明错误陈述的时间。

选择的编程语言取决于您要进行编程的工作,在我看来,这可能是整本书的主题。但是,如果您设计算法并想实现自己的算法,以便其他人可以使用该实现,那么一个重要因素就是可用性。尽管可以期望代码的大多数潜在用户可以访问C编译器,但是不能期望同一个人可以访问Haskell编译器。对于一次性程序,选择更多是基于可用的库,并且包括Matlab等环境。

顺便说一句,编程也很有趣。


2
@SureshVenkat:实际上,如果编程很有趣,那么“编程有多重要?”这个问题可能并不太相关。但是,我的大部分答案将变得无关紧要。多么悲伤!:)
伊藤刚(Tsuyoshi Ito)

我以前没有想过您的第二个论点,确实,用短程序测试一个猜想似乎是一个非常好的主意!至于编程,可能看起来很有趣,但是我还没有看到整个漫长的周末学习=)。
Gopi

@Gopi:也就是说,很多猜想都不适合这个“用简单程序测试”框架。例如,我们通常不能测试渐近行为(至少通过一个简单的程序)。但是,如果您有一些可以测试的猜想,那么稍微编程就可以成为一个强大的工具。至于娱乐,是的,我了解。我只是不想仅仅通过列出“有用性”观点中的一些动机而忽略“有趣”观点。
伊藤刚(Tsuyoshi Ito)

3
克努斯关于问题解决类的笔记有一个很好的例子,说明了猜想与代码之间的相互作用(请参阅问题1):www-cs-faculty.stanford.edu/~knuth/papers/cs1055.pdf(我特别喜欢某人的形象冲着教室冲进教室)
Suresh Venkat

47

我感到不得不在此引用Doron Zeilberger:

意见37:编程比证明更有趣,而且更重要的是,它提供了很多(如果不是更多的话)洞察力和理解力。

阅读该意见,其中充满了宝石(但他倾向于故意挑衅)。例如,“了解某物的最好方法是教它。但是比对人类教它更好的是将其教给计算机”。

我的个人经验是,即使仅做理论性的工作,也需要一些计算工具。我避免使用Mathematica进行许多繁琐的常规代数运算。我通过在Matlab或Python上强行强制小实例来测试半生不熟的猜想。我与他人合着了一篇纯粹的组合学论文,而这项工作受益于运行大量的计算机实验以了解正在发生的事情而受益最大。欧拉制作了大量冗长的计算表,以深入了解问题。我们应该归功于他在进行数学运算时使用我们的工具来自动化该过程。

除此之外,如果您要研究算法和数据结构,编程将在效率和可用性问题上提供无可替代的观点。我在这里的观点与其他人有所不同。我认为学习功能性语言以使您能够正确地写出类型正确的证明是浪费时间(我认为拥有强类型语言经验的人可能倾向于编写更仔细的结构化证明是很重要的一点;我只是不愿意认为您不值得花时间进行这项练习)。函数式编程模糊了算法设计和运行时间,并强调了逻辑和语义问题(当然,学习函数式编程可能是必须的,如果您对逻辑/ PL语义感兴趣的话,会自然而然地出现)。同样,我认为进入Java和C ++的OO详细信息也不是花费时间的最佳方式,因为OO的目的是编写模块化可重用代码。如果您要生成供他人使用的代码,这就是方法。但是如果您想深入了解效率和运行时间,如果您关心真正高效的算法和数据结构,我建议您考虑使用C。它可以使您在保持接近机器的同时仍提供合理的抽象水平。 。通过这种方式,您可以了解快速和慢速,什么是合理的数据结构等。但是如果您想深入了解效率和运行时间,如果您关心真正高效的算法和数据结构,我建议您考虑使用C。它可以使您在保持接近机器的同时仍提供合理的抽象水平。 。通过这种方式,您可以了解快速和慢速,什么是合理的数据结构等。但是如果您想深入了解效率和运行时间,如果您关心真正高效的算法和数据结构,我建议您考虑使用C。它可以使您在保持接近机器的同时仍提供合理的抽象水平。 。通过这种方式,您可以了解快速和慢速,什么是合理的数据结构等。


10
“功能编程模糊了算法设计和运行时间的问题,并强调了逻辑和语义问题”。好斗的话:)
Suresh Venkat

3
“功能编程模糊了算法设计和运行时间的问题,并强调了逻辑和语义问题。” 因此,如果您在TCS的逻辑或语义方面工作,它是一个不错的选择。:)
Radu GRIGore


3
@Sasho:所有普通技术仍然可以在功能语言中使用。唯一的“问题”是函数式编程鼓励了一种编程和数据结构设计的风格,而算法分析的普通技术还不足以解决这些问题。(例如,函数组合的大O是什么?运算很简单,但是完全打破了渐近复杂性的假设-函数输入没有大小的简单数字度量。)
Neel Krishnaswami

3
@SashoNikolov:每当我教研究生数据结构课程时,我真的很希望我能够假设每个人都有一定的函数式编程经验。与其花三场90分钟的讲座来解释持久性,不如说“嘿,您是否注意到您的数据结构已经做到了这一点?”
Jeffε

33

您无需编程即可成为非常成功的理论计算机科学家。对于少数人来说,编程是非常困难的,如果您是其中的一员,则不要绝望和切换字段。

但是,对于大多数数学和计算机科学专业的研究生来说,学习编程并不是特别困难,并且是一项非常有用的技能。您应该学习一种编程语言,并且如果喜欢的话,应该尝试进行足够的练习以变得相当熟练。然后,当谈到(并且将会)在您的研究中编写程序很有用时,您就可以做到。

如果您现在不学习编程,那么很有可能在您最终需要编写程序时,您将没有时间学习,因此您可能实际上没有编写程序,最终在您的工作中效率降低了。研究。虽然让一个研究生或一个本科生为您做这件事并不难,但在很多情况下,自己做而不是向他们解释问题要容易得多,耗时少。

您应该学习哪种语言?我建议使用一种面向对象的语言,因为这些是当前使用最多的语言,我怀疑将来这会更加正确。也许是Python或Java,它们都是面向对象的语言,尽管在实践中它们的使用量少于C ++,但我的印象是它们都非常容易学习。(注意:尽管我在Bell Labs工作过,但我并不了解C ++,所以也许我对此有误。)


2
我在你的第三段中看到了真相:)。
Gopi

1
“但是,对于大多数人而言,学习编程并不是特别困难”-我的经验使我不同意这一点,但是大多数人都不是TCS研究人员。
最多

2
随着Sage的兴起,可以使用一种不错的流行语言(如Python)工作,同时仍然可以立即使用Mathematica / Maple / Matlab风格的数学库。
安德拉斯·萨拉蒙

1
除了Lisp语言家族之外,C ++具有我所见过的所有主流通用编程语言中最先进的类型/元编程系统。因此,如果您是类型理论,语言设计或编译器理论的作者,或者更广泛地是形式语义的专家,则可能需要熟悉它。如果您想从事实验计算机科学方面的研究,或者希望获得该行业的程序员或软件工程师的工作,那么除了C ++之外,还必须使用Java和C#。Python应该在高中中教授:D
Antonio Valerio Miceli-Barone

4
@ AntonioValerioMiceli-Barone:我必须不同意,至少在类型理论,语言设计,形式语义和编程语言理论(PLT)方面是不同的:C ++ 不是在这些领域学习的语言。TT和形式语义几乎只与函数式编程有关,而PL社区则更加多样化,但更喜欢比C ++更优雅的语言。Haskell是具有最先进的类型系统的“主流”语言,其次是Scala(较弱的语言,更为主流)。C ++确实具有有趣的功能,但是对于现代品味来说太低级了。
Blaisorblade 2012年

33

还有一个答案,没有人真正提出过。编程实际上可以导致有趣的理论。散列(尤其是制表散列)方面的许多最新发展并不是出于理论上的考虑,而是由于理论上最优的算法在实践中并不那么出色。除非您可以编写代码,否则这当然是您不知道的。

即使在精确的指数时间算法领域,一种动机仍然是产生可以实际起作用的算法。SAT求解器就是一个典型的例子。

简而言之,编码能力使您可以了解最佳理论结果中的缺点和不足,从而为理论研究开辟了新的方向。


您的答案可能会有助于解决TCS中的经验结果问题。
Gopi

也许:但是那个线程早就消失了:)
Suresh Venkat

确实,我没有查看日期,而是在我收到的最新新闻中的“前几周最热门” =)中查看日期。
Gopi

18

三点:

1)有一种称为“ 实验数学”的数学方法(另请参阅Wikipedia://计算机辅助证明),您可以在其中使用计算机程序来研究对象的模式和结构,以便得出有关这些对象的分析证明。对于这种方法,您最好知道如何编程。您可以确定您将需要这种方法来证明非常理论上的陈述。我相信,反对编程的势利往往不会对TCS研究产生真正的帮助。

AL(X,Y)BL(Y,C)

3)当您说“至编程”时,是指“至线性程序 ”还是“至半定程序 ”?:)


2
我认识的人中,没有人将“编程”用于“线性编程”或“半定程序”。您会说“构造/求解线性程序”。
彼得·索尔

2
@PeterShor Point 3并不严重
Alessandro Cosentino

3
当然,您还应该学习线性编程和半确定编程……这两种有用的技能。
彼得·索尔

3
对于第2点+1,虽然我只用了一年,但实际上我还是一个本科生,虽然我被教了一点OCaml,但我还是习惯检查自己的证明类型。
Gopi

4
动态编程!
Jeffε

16

谢谢Gopi这个问题。我想在一个尚未提及的维度上扩展许多有趣的答案。

研究不是我们在大学里唯一要做的事情:如果您想留在学术界,最终将不得不教书。如果幸运的话,您必须教授与专业领域相距甚远的课程。您很可能会被分配具有实质性编程内容的课程。在这里,即使是中等的编程能力也可以大大帮助您:如果您知道如何编程,您会成为更好的老师。首先,您将对材料更加熟悉,将能够更好地回答学生的问题,并且您将了解自己在学习编程过程中遇到的困难,因为您自己经历了这一学习过程。此外,您可以制作更好的教材。例如,您可以在将编程练习提供给学生之前自己进行测试,

还有一个实用的方面:教学涉及熟练的程序员经常可以自动化的各种重复性任务,例如快速建立一个网站供学生用来提交课程并对其进行自动评分(根据代码通过的自动测试的数量)。


“如果幸运的话,您将必须教授与您的专业领域相距甚远的课程。”幸运吗??
伊藤刚(Tsuyoshi Ito)

3
@ Tsuyoshi:好吧,它迫使您熟悉新的学科领域。在短期内,这意味着很多工作(从长远来看,这笔费用会摊销,因为您可能会不止一次地讲授此材料)。同时,它大大拓宽了您的知识视野。
Martin Berger

@TsuyoshiIto:是的!
Jeffε

13

编程是提高您对各种概念的理解的好方法,但是它也是一个危险的时间消耗。

反对编程的一个典型论点是,它使您花费大量时间花费不重要的细节。一个典型的说法进行编程是它让你意识到你认为细节是不重要的其实都是很重要的。擅长编程主要意味着能够迅速处理不重要的部分。成为好人需要长时间。

至于要学习的编程语言:“所有人”都是我的回答(嘲笑)。


2
最后一个反对编程的论点:)。
Gopi

1
@Gopi,我认为编程可能会很有趣,而更好地了解您的知识非常重要。其他答案给出了很好的例子,说明编程如何帮助理解。因此,我鼓励您学习编程,如果企业似乎没有很快获得回报,就不要放弃。
Radu GRIGore

6
证明定理也是增进您对各种概念的理解的一种好方法,但这也是一个危险的时间消耗。
Jeffε

@Jɛff E,我的意见由替换保留[伪代码->纸上证明,代码->证明助手中的证明]。
Radu GRIGore 2011年

12

我来晚了,这些都是很好的答案,但是我还有另一个原因:

可视化。

是的,通常您将使用无法可视化的内容,但是通常您将使用可以可视化的内容。知道如何编程对于该任务是必不可少的,而可视化可以使您对问题有很多了解。


3
我知道如何编程,并且在可视化方面绝对没有希望。我还怀疑有些工具可以使您无需进行大量编程就可以直观地看到事物。如果没有,应该有,也许会在几年后。
彼得·索尔

@PeterShor:因为您不使用C ++!(开个玩笑)
伊藤刚

1
@PeterShor:我指的不是任何特定的语言或环境;MATLAB在这里计数。但是,知道如何编程可以为您带来可视化效果,否则将带来极大的不便。例如,二维正定矩阵的空间是三维的,我想在该空间中可视化一系列构造。我必须提出一个转换,然后对其进行编码以真正看到我的对象。
John Moeller

@约翰...你是对的,我不认为你可以用其他方式做到这一点。
Peter Shor

7

只是一个快速点:知道如何编程会为我提供理论研究方面的另一种工具。当我有一个我认为会起作用的算法时,如果它很简单,我可能会对其进行编码并检查它是否确实有效。如果我的想法在实践中行不通,那么在理论上就不太可能奏效,这种方法通常使我免于花费大量时间来证明错误的东西。


伊藤刚(Tsuyoshi Ito)在回答中也提出了类似的论点(第二点:))。
Gopi

糟糕,您是对的-我错过了。
列夫Reyzin

5

这里没有人解决过一些实际的问题,即为什么学习TCS的人应该学习编程。

如果您打算在计算机科学系的TCS攻读博士学位,那么您很有可能需要参加一些非理论课程,而且这些课程几乎肯定是编程密集型课程。根据您所修读的课程,您可能还需要非理论科目的知识才能通过资格考试。

完成博士学位后,TCS的大多数工作机会都来自学术界。如果您在学术界工作,就应该教书,并且可能要教入门级的本科CS课,这比理论编程要重要得多。即使您正在向本科生讲授理论课,例如“算法”,您也可以期望您的学生会比理论了解更多的编程知识,并且不了解学生的知识,就很难弥合他们在理解方面的差距。我对CS本科生被一个不懂编程的人所教的想法感到震惊!

如果您不关心这些实际问题,那么您可能无需真正了解编程就可以进行研究。当然,您在TCS社区中有很多公司,但是里程会根据您所从事的理论的确切领域而有所不同。例如,如果您在进行纯计算复杂性理论,则证明没有人拥有的类的下限听说过,那么编程可能对您毫无用处。但是,如果您正在做更多的算法工作,那么我认为能够编写出良好而干净的工作代码将增强您的直觉。

我建议学习C(不是C ++)。拿起K&R的副本并从头到尾阅读。C没有现代语言的许多奇特功能,但确实具有简单但优雅的语法和语义,您应该可以全面学习。但是,即使您完全理解该语言,仍然需要实践才能熟练地用C编写精美的无错误代码。但是,如果您可以熟练地使用C进行编码,则您将能够掌握所遇到的任何编程语言。此外,该学科将帮助您思考硬件的想法,这在设计算法时将是有益的。

指针之类的思想对于进行算法设计的任何人都非常重要,但是不幸的是,Java和Python之类的语言使您难以理解它们,因此,我不建议将其作为具有数学背景的人的第一语言。对于必须维护大型软件项目的人员,而不是设计算法的人员,OOP更为重要。


0

我建议您不要等待课程的开始,因为任何水平的计算机科学都涉及通过计算机实现算法,以便完成/验证/解决您在整个课程中必须面对的任何理论,尤其是在您的水平上。

我必须首先在10年级(高中)编程,而且我已经知道如何使用命令行,这确实有所帮助(这是向您展示如何在CS中考虑“基本”编程技能)。

同行的惊讶是有充分根据的,因为伪代码和算法是编程的第一要学的知识。

但是,您不会在即将开始的课程中完全迷失,因为您可以利用自己的广泛数学技能(自己)来跳过面向对象的编程,从而更快地学习函数式编程语言。

  • 函数式编程是非常面向数学的,因其所需的数学背景而被认为更难学习,被认为非常强大(以“简单”的数学方式,通过优雅和“干净”的方式解决难题)。
  • 当您不想了解底层的算法和实现原理而只想“重用”已经存在的对象时,面向对象是很好的选择。

我认为您可以解决Haskell(通常不是第一语言),因为它纯粹是数学,函数式的,基本上可以完成您想要的任何事情。学习Haskell将使您处于一个无需学习更多知识即可掌握的水平,甚至会使您处于对课程的控制和控制之下。如果您喜欢统计学,那么学习R是一个加分,但没有Haskell多。我看到数学家的报告说,他们对它对数学的亲近感以及它如何接受他们的思维方式感到惊讶。

另外,一个值得解决的挑战(使您快速适应编程环境)将是安装和使用Linux(Ubuntu Linux会做到)。相信我,您会通过学习而学到很多东西...

对于计算机科学领域的数学家来说,这些建议是我所知道的快速,可靠地赶上的最佳方式。此外,开源社区非常友好且乐于助人,如果您受阻,IRC是通过专门渠道(在FreeNode上连接)谈论任何主题的最直接方法。请记住:提问是解决问题的唯一方法,无论是对自己,论坛,搜索引擎还是在聊天室中。


4
我不知道您在回答最初的问题有多少:我不是在问“怎么做”,而是在问“该做什么”。
Gopi

0

以下论文是交互式证明系统的C ++实现的一个示例:贾斯汀·泰勒(Justin Thaler)的用于电路评估的时间最优交互式证明。可从http://people.seas.harvard.edu/~jthaler/获得。这似乎是朝着开发通用交互式证明系统的实际实现这一目标迈出的一步。

类似的论文和相关的源代码出现在上述网站上。


3
您能否解释一下本文与以下问题的关系,即了解如何为TCS编程有多重要
scaaahu

即使这是从编程中受益的理论结果的一个例子,它也不会回答最初的问题吗?
杰里米

该问题询问是否需要复杂性理论家来了解编码。上面提到的论文清楚地利用实验结果来补充理论概念。这需要编码。无论如何,我花了很长时间才找到与理论计算机科学中的核心概念如此紧密相关的编程项目。我希望这篇文章可能对类似搜索的人有用。
lgidwani
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.