熵的概念可以用于有用的方式来分析源代码吗?


19

在我看来,可以为静态源代码分析定义一个上下文,其中包括可以产生相对价值的规则。我知道这不是物理意义上的,因为源代码没有“能量”,但是我敢打赌,精湛的学术界已经做出了类似的努力。有谁知道这件事,如果知道,它产生了什么作用?


我对此没有任何具体知识。但是,作为一名工程师,我确实相信您可以将这一概念应用于宇宙中任何您想要的东西。“一切”就是能量。您的代码可以建模为具有能量的实体。
wleao 2011年

3
已经存在代码复杂度的度量-循环复杂度,类长度(LOC),方法长度(LOC),字段数,方法参数数,n路径复杂度,扇入/扇出和数据流分析(DU / DD链)。已经将这些与缺陷密度,维护工作和易于理解相关联。与这些相比,您的需求如何?
Thomas Owens

@Thomas Owens:我认为这正是OP所要的,请发布它作为答案!
blubb 2011年

@Simon,好的,如果您这么认为。我不确定100%。
Thomas Owens

1
对于一种非常常规的方法,您可以直接计算源代码的数据压缩率,也可以在某种标准化后计算数据压缩率。(例如c2.com/doc/SignatureSurvey)-我不知道这将是多么有意义或有用,但是当与更传统的指标结合使用时,它可能会提供一些见识。
William Payne 2012年

Answers:


22

已经有许多衡量代码复杂性的方法:

  • 圈复杂度
  • 班长
  • 方法长度
  • 栏数
  • 方法参数数
  • N路径复杂度
  • 扇入和扇出
  • 数据流分析(DU / DD链)

已经将这些与缺陷密度,维护工作和易于理解相关联。根据您要从分析中学到的知识,有些比其他的更有意义。我对物理科学中的熵的概念并不熟悉,但是我想知道,随着时间的推移,跟踪诸如我命名的度量和度量并将其与缺陷关联起来,是否与您所寻找的类似。

您可能还对Ivar Jacobson对软件熵rot 的定义感兴趣。这些主题的总体思想是,随着时间的流逝,随着代码以及执行环境的变化,软件系统开始退化。重构被视为一种最小化熵或腐烂的方法,并且至少在我的经验中,我上面提到的度量和度量将指示系统或子系统中可能需要重构。


13

我认为您正在尝试在热力学熵和“复杂性”之间划清界限。事实是,熵是无序的一种度量,而不是复杂性。我不认为两者是等效的和可互换的。

与热力学熵最接近的类似物是Shannon熵,它测量随机变量中的无序量。该概念主要与消息中“信息”的数量有关。

在这方面,一段代码可以具有很多信息(高熵),但是复杂度却非常低。考虑一个简单地打印出很长的任意字符字符串的程序。它具有大量信息,但复杂度较低。


1
源代码的熵不会与非结构化文本的熵通过同一模型进行计算。使用适合于源代码模型,计算对于任意情况(例如您描述的长字符串)不会广泛变化的熵应该是有意义的。
马修·罗达图斯

那么,您如何评价给定程序的熵和复杂性呢?我认为无论您使用哪种模型,它都包含很多信息。尽管复杂性的定义还不清楚。
tskuzzy 2011年

1
就像计算自然语言文本的热力学熵没有意义一样,将Shannon熵用于计算机源代码也没有意义,因为程序的含义是在一组不同的规则和模式(即:句法)。自然语言具有自己的语法。该模型必须对应于域的语法。热力学熵的单位是焦耳/开尔文。香农熵以位为单位。源代码熵将完全...不同维度进行度量。我对我的答案中的模型看起来有些怀疑。
马修·罗达图斯

我喜欢您的答案-例如,我在想,当引入“不良”代码时,整个环境的熵增加了,即包括必须加倍努力的编码人员-这样一来,如果不是与热力学的科学联系?
亚伦·奥诺德

2

是“无序[或]不可预测性的度量”。信息中范围更广的独特模式(即,大致“更有意义”)表示更高程度的熵。

我认为将这一原理应用于计算机源代码可能会有用。但是,有必要为源代码设计一个概率模型用该模型来计算熵。(容易想到的数据结构是具有不同边类型的图形:调用,类继承等)

一旦设计了模型,然后使用软件应用程序的源代码(即,节点/边缘的频率)填充了模型,就可以计算出熵。

我对此尚无任何研究,但我的直觉是,较低的熵意味着源代码会在整个应用程序(即DRY)中重用通用模式。相反,高度的熵意味着源代码复杂度很高,并且没有被很好地分解。


2

考虑熵的一种方法是“获取平均信息”,因此我认为最好回到建模信息的角度。我知道两种对信息进行数学建模的基本方法。(原谅我提供了维基百科参考,但恕我直言,它们还不错。)

  • Shannon Information,它查看符号集,符号集的概率分布,可以在符号集之间传递信息的代码以及这些代码的长度。香农信息理论阐述了代码效率,噪声,通过冗余进行错误检测和纠正等一般概念。表达信息的一种方法是说它是可以表示符号的最短二进制代码的长度。这是基于概率的,概率是某些观察者分配给符号或事件的数值。

  • Solomonoff(或Kolmogorov)信息。这是另一个解释。在这种表述中,符号或事件的信息内容由可以计算符号或事件的最短程序的长度表示。同样,这不是与观察者的分配概率有关,而是与可以执行程序的通用机器有关。因为每个通用机器都可以由通用图灵机模拟,所以从某种意义上讲,这意味着符号或事件的信息内容不是相对的,而是绝对的。

如果我可以自由地说出我认为这是我写过的一本书的日常用语,那仅意味着程序的复杂性就是程序的长度,而当诸如功能规范和语言之类的东西保持适当时,留有余地,例如注释和姓名长度。但是,这里存在一个问题-“ APL特快报”,其简洁程度等于不可理解的程度。

最好考虑一下(就像我在学习AI时一样)程序的功能规范包括一个心理模型,该模型不仅是真实的,而且是有效编码的,也就是说,冗余度很小,足以改变人们对需求的看法可以在没有太大内部不一致的危险的情况下完成此操作-即具有“错误”。然后编程的过程是一个信息通道,该通道将心智模型作为输入,其输出是有效的源代码。然后,当心智模型发生变化时,必须在编程过程中输入该增量,并在源代码中将其转换为相应的增量。该增量很容易测量。在应用该增量之前和应用该增量之后(完全解决所有错误),在源之间进行区分,并计算插入,删除和替换的代码块的数量。值越小,源代码语言就越能代表心理模型所代表的语言(就名词,动词和结构而言)。如果以某种方式在可能的功能更改的空间上对该度量进行平均,则这是源语言的熵的概念,且越少越好。这个有一个名词-领域特定语言(DSL)

很抱歉,如果参考文献不充分/个人,但我认为这一总体问题非常重要。


+1和Shannon Kolmogorov都相关...
Alex Feinman

@Alex:我认为Shannon在运行时适用。因此,例如,您可以根据决策点的熵来了解算法的性能,并且可以根据最少的代码来了解数据结构的规范化。算法信息似乎更加语言化,出于表达目的而适用于一种语言,而您试图提高效率的算法就是您编程时脑海中不可思议的算法。
Mike Dunlavey

2

乔恩·贾格尔Jon Jagger)奥尔夫·莫达尔(Olve Maudal)对代码熵的看法略有不同,可以从他们2011年的Accu会议上看到代码熵和软件物理

他们谈论代码的稳定性与将来的开发人员/维护人员是否可能更改该代码有关。

为了证明这一点,他们用大量代码片段进行了调查,结果非常有趣。

  • 似乎对一个真实的民族风格有强烈的偏见。
  • 但是,如果采用单条陈述,则存在强烈偏见。
  • 强烈反对使用临时变量。
  • 在添加括号以使运算符优先级变得明显时存在很大的偏见。

加上其他16个人。

总体趋势似乎是使代码更易于理解,更难于理解。

他们还研究了多年来对大型代码库所做的一些更改。

尽管幻灯片本身并不是会议的笔录,但仍有一些有趣的地方。


1

我研究了下教授谁使用熵作为程序复杂的措施(我们的课本是较旧版本的这一个,他的一些酒吧都在这里)。FAU上有许多学位论文,这是主要措施之一,但是自从我上次看过以来,学校的网站已经改变了,我无法找到学生论文/学位论文现在所在的位置。

信息论与软件测量就是其中之一。


0

如果您希望以熵的方式定义一个“数学”,那么您可能想看看Kolmogorov复杂度,它以可能要做的最少代码量来衡量复杂度。但是,这不是代码的复杂度,但是您正在尝试使用该代码。但是您可能认为这很重要,因为从理论上讲,您可以将一段特定的代码与最少的一段代码进行比较。然而,这目前不是用于测量真实世界代码的复杂性的有用技术。


0

我认为这是不可行的,有人可能会认为编写良好的代码库应具有较高的熵(无序)。考虑一个反复重复代码段的代码库,由于重复部分(较低的熵/文件大小),可以以较高的压缩率对其进行压缩,但是如果将代码移至单独的函数,则压缩率会降低(较高的熵/文件大小)。

因此,可能有人会想到,然后我可以使用压缩率作为系数来计算熵/代码行之类的内容,以测量代码质量,但是这样的问题是,总的随机输入看起来似乎不是世界上最好的代码。

确实,压缩率是衡量代码熵的好方法,但是对于代码质量而言,两者都不是好方法。


0

嗯,熵一词不仅出现在热力学和信息论中,而且还出现在数据压缩的现实世界中。在这种情况下,压缩器看到的熵等于其产生的位数。(请注意,我说的是“压缩器看到的熵”,因为认为熵取决于压缩器用来描述输入数据的模型。这就是为什么不同的压缩器生成大小不同的文件的原因:一个是对另一个的可利用结构。)

原则上,这可以很好地应用于源代码的复杂性:“只需”编写一个压缩器,该压缩器只能在完全符合标准的源代码上工作,并且像压缩编译器一样对它进行实际解析以生成相应的语法树。然后,它可以遍历此语法树,并在每个节点处确定在每个点上可能有哪些节点,并使用该知识对该节点进行编码。

因此,例如,如果该语言允许使用一个现有的标识符,或者使用括号括起来的东西或某个特定点的产品,那么压缩器将考虑可能的类型信息,对可能的现有标识符进行计数(例如,您有3个这样的标识符),并为两个可能的子表达式加2,从而提供5种可能性。因此,该节点将使用lb 5 = 2.32位进行编码。在两个可能的子表达式的情况下,将需要更多的位来对其内容进行编码。

实际上,这确实可以非常准确地衡量代码的复杂性。但是,此措施仍然没有用!出于所有代码复杂度测量均无用的原因,它是无用的:它们失败确实在测得的代码复杂度(无论可能是多少)与代码解决的问题的复杂度之间建立了联系。您总是可以找到解决编程问题的极其复杂的解决方案,以LOC数量打动您的雇主,但是没有任何代码复杂性度量可以告诉您,只需花费一小部分精力就可以解决该任务。


-2

代码的熵与数字π一样多。

代码维护和更改可能会引入熵(因为可能涉及状态更改)。

但是代码只是一个很大的数目。用二进制表示。


这么想,您不能说gzip压缩后所有代码都具有相同的熵吗?
亚伦·奥诺德

@Gabriel:那是另一回事。当把那个数字看作一个比特序列时,熵就是比特之间的噪声量。不能以一个静态数字查看。源代码是一个单一的静态数字,例如42。只有更多的位。
S.Lott

只是好奇,在这种情况下,十进制42和二进制42的熵是否相等?或者该评论是说数字没有熵,这就是重点吗?
亚伦·奥诺德

“数字没有熵”。他们就是。视为符号流的表示形式可能具有熵,但是作为一个整体的数字只是一个数字。
S.Lott
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.