How to measure similarity between two python code blocks?
<p>Many would want to measure code similarity to catch plagiarisms, however my intention is to cluster a set of python code blocks (say answers to the same programming question) into different categories and distinguish different approaches taken by students. </p>

<p>If you have any idea how this could be achieved, I would appreciate it if you share it here.</p>

<p>You can choose any scheme you like that essentially hashes the contents of the code blocks, and place code blocks with identical hashes into the same category.</p>

<p>Of course, what will turn out to be similar will then depend highly on how you defined the hashing function.   For instance, a truly stupid hashing function  H(code)==0 will put everything in the same bin.</p>

<p>A hard problem is finding a hashing function that classifies code blocks in a way that seems similar in a natural sense.   With lots of research, nobody has yet found anything better to judge this than <em>I'll know if they are similar when I see them</em>.</p>

<p>You surely do not want it to be dependent on layout/indentation/whitespace/comments, or slight changes to these will classify blocks differently even if their semantic content is identical.   </p>

<p>There are three major schemes people have commonly used to find duplicated (or similar) code:</p>

<ul>
<li><p>Metrics-based schemes, which compute the hash by counting various type of operators and operands by computing a metric. (Note: this uses lexical tokens).  These often operate only at the function level.   I know of no practical tools based on this.</p></li>
<li><p>Lexically based schemes, which break the input stream into lexemes, convert identifiers and literals into fixed  special constants (e.g, treat them as undifferentiated), and then essentially hash N-grams (a sequence of N tokens) over these sequences.   There are many clone detectors based on essentially this idea; they work tolerably well, but also find stupid matches because nothing forces alignment with program structure boundaries. 
The sequence </p>

<pre><code> return ID; }  void ID ( int ID ) {
</code></pre></li>
</ul>

<p>is an 11 gram which occurs frequently in C like languages but clearly isn't a useful clone). The result is that false positives tend to occur, e.g, you get claimed matches where there isn't one.</p>

<ul>
<li>Abstract syntax tree based matching, (hashing over subtrees) which automatically aligns clones to language boundaries by virtue of using the ASTs, which represent the language structures directly.   (I'm the author of the original paper on this, and build a commercial product CloneDR based on the idea, see my bio).   These tools have the advantage that they can match code that contains sequences of tokens of different lengths in the middle of a match, e.g., one statement (of arbitrary size) is replaced by another.</li>
</ul>

<p>This paper provides a survey of the various techniques: <a href="http://www.cs.usask.ca/~croy/papers/2009/RCK_SCP_Clones.pdf" rel="nofollow">http://www.cs.usask.ca/~croy/papers/2009/RCK_SCP_Clones.pdf</a>.   It shows that AST-based clone detection tools appear to be the most effective at producing clones that people agree are similar blocks of code, which seems key to OP's particular interest; see Table 14.</p>

<p>[There are graph-based schemes that match control and data flow graphs. They should arguably produce even better matches but apparantly do not do much better in practice.]</p>

python compilation comparison abstract-syntax-tree