许多人希望衡量代码相似性来捕捉抄袭,但我的目的是将一组python代码块(比如同一个编程问题的答案)聚类成不同的类别,并区分学生采用的不同方法。
如果你知道如何实现这一点,如果你在这里分享,我将不胜感激。
答案 0 :(得分:2)
一种方法是计算函数,对象,关键字的数量,这些关键字可能分为类别,例如分支,创建,操作等,和每种类型的数字变量。不依赖于被称为相同名称的方法和变量。
对于给定的问题,类似的方法往往会得出相似的分数,例如:使用决策树的学生将拥有大量的分支语句,而使用决策表的学生则会有更低的分数。< / p>
这种方法比解析代码结构和比较结果要快得多。
答案 1 :(得分:2)
您可以选择任何您喜欢的方案,它基本上会隐藏代码块的内容,并将具有相同哈希值的代码块放入同一类别中。
当然,结果类似的东西将在很大程度上取决于你如何定义散列函数。例如,一个真正愚蠢的散列函数H(代码)== 0会将所有内容放在同一个bin中。
一个难题是找到一个散列函数,它以一种在自然意义上看似相似的方式对代码块进行分类。通过大量的研究,没有人发现任何更好的判断这一点,而不是我知道当我看到它们时它们是否相似。
您肯定不希望它依赖于布局/缩进/空格/注释,或者对这些内容进行细微更改会对块进行不同的分类,即使它们的语义内容相同也是如此。
人们常常使用三种主要方案来查找重复(或类似)代码:
基于度量的方案,通过计算度量来计算各种类型的运算符和操作数来计算哈希值。 (注意:这使用词法标记)。这些通常仅在功能级别运行。我知道没有基于此的实用工具。
基于词汇的方案,将输入流分解为词汇,将标识符和文字转换为固定的特殊常量(例如,将它们视为无差别),然后基本上哈希N-gram(N个令牌的序列)这些序列。基本上基于这个想法有许多克隆探测器;它们工作得相当好,但也找到了愚蠢的匹配,因为没有任何东西强迫与程序结构边界对齐。 序列
return ID; } void ID ( int ID ) {
是一种11克,经常出现在C语言中,但显然不是一个有用的克隆)。结果是误报倾向于发生,例如,你声称匹配的地方没有。
本文提供了各种技术的调查:http://www.cs.usask.ca/~croy/papers/2009/RCK_SCP_Clones.pdf。它表明,基于AST的克隆检测工具似乎是最有效的克隆,人们认为这些克隆是类似的代码块,这似乎是OP特别感兴趣的关键;见表14.
[有基于图形的方案匹配控制和数据流图。他们应该可以说产生更好的比赛,但实际上并没有做得更好。]