如何衡量两个python代码块之间的相似性?

时间:2016-09-28 05:42:32

标签: python compilation comparison abstract-syntax-tree

许多人希望衡量代码相似性来捕捉抄袭,但我的目的是将一组python代码块(比如同一个编程问题的答案)聚类成不同的类别,并区分学生采用的不同方法。

如果你知道如何实现这一点,如果你在这里分享,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

一种方法是计算函数,对象,关键字的数量,这些关键字可能分为类别,例如分支,创建,操作等,和每种类型的数字变量。不依赖于被称为相同名称的方法和变量。

对于给定的问题,类似的方法往往会得出相似的分数,例如:使用决策树的学生将拥有大量的分支语句,而使用决策表的学生则会有更低的分数。< / p>

这种方法比解析代码结构和比较结果要快得多。

答案 1 :(得分:2)

您可以选择任何您喜欢的方案,它基本上会隐藏代码块的内容,并将具有相同哈希值的代码块放入同一类别中。

当然,结果类似的东西将在很大程度上取决于你如何定义散列函数。例如,一个真正愚蠢的散列函数H(代码)== 0会将所有内容放在同一个bin中。

一个难题是找到一个散列函数,它以一种在自然意义上看似相似的方式对代码块进行分类。通过大量的研究,没有人发现任何更好的判断这一点,而不是我知道当我看到它们时它们是否相似

您肯定不希望它依赖于布局/缩进/空格/注释,或者对这些内容进行细微更改会对块进行不同的分类,即使它们的语义内容相同也是如此。

人们常常使用三种主要方案来查找重复(或类似)代码:

  • 基于度量的方案,通过计算度量来计算各种类型的运算符和操作数来计算哈希值。 (注意:这使用词法标记)。这些通常仅在功能级别运行。我知道没有基于此的实用工具。

  • 基于词汇的方案,将输入流分解为词汇,将标识符和文字转换为固定的特殊常量(例如,将它们视为无差别),然后基本上哈希N-gram(N个令牌的序列)这些序列。基本上基于这个想法有许多克隆探测器;它们工作得相当好,但也找到了愚蠢的匹配,因为没有任何东西强迫与程序结构边界对齐。 序列

     return ID; }  void ID ( int ID ) {
    

是一种11克,经常出现在C语言中,但显然不是一个有用的克隆)。结果是误报倾向于发生,例如,你声称匹配的地方没有。

  • 基于抽象语法树的匹配(在子树上进行散列),它通过使用直接表示语言结构的AST自动将克隆与语言边界对齐。 (我是关于此的原始论文的作者,并根据这个想法构建了商业产品CloneDR,请参阅我的简历)。这些工具的优点是它们可以匹配包含匹配中间不同长度的令牌序列的代码,例如,一个语句(任意大小)被另一个语句替换。

本文提供了各种技术的调查:http://www.cs.usask.ca/~croy/papers/2009/RCK_SCP_Clones.pdf。它表明,基于AST的克隆检测工具似乎是最有效的克隆,人们认为这些克隆是类似的代码块,这似乎是OP特别感兴趣的关键;见表14.

[有基于图形的方案匹配控制和数据流图。他们应该可以说产生更好的比赛,但实际上并没有做得更好。]