anchor.diff:  display_clones_2([{{File, StartLine, StartCol}, {File, EndLine, EndCol}}|Rs], Str) ->
       Str1 = case Rs == [] of 
   	       true ->
  -		   Str ++ File++io_lib:format(":~p.~p-~p.~p:  \n", [StartLine,StartCol-1,EndLine, EndCol]);
  +		   Str ++ File++io_lib:format(":~p.~p-~p.~p:  \n", [StartLine,lists:max([1, StartCol-1]),EndLine, EndCol]);
   	       _ ->
  -		   Str ++ File++io_lib:format(":~p.~p-~p.~p:  \n", [StartLine, StartCol-1, EndLine, EndCol])
  +		   Str ++ File++io_lib:format(":~p.~p-~p.~p:  \n", [StartLine, lists:max([1,StartCol-1]), EndLine, EndCol])
   	   end,
       display_clones_2(Rs, Str1).
  -		    
  -    
  -				    
  -				    
  -    
  -    
  +
  +		
  +get_anti_unifier([]) ->
  +    throw({error, anti_unification_failed});
  +get_anti_unifier([Expr])-> generalise_expr(Expr, []);
  +get_anti_unifier([Expr|Exprs]) ->
  +    Nodes =lists:usort(lists:flatmap(fun(E) ->
  +					     expr_unification(Expr, E)
  +				     end, Exprs)),
  +    generalise_expr(Expr, Nodes).
  + 
  +
  +expr_unification(Exp1, Exp2) ->
  +    case {is_list(Exp1), is_list(Exp2)} of 
  +	{true, true} ->   
  +	    case length(Exp1) == length(Exp2) of 
  +		true ->
  +		    lists:flatmap(fun({E1,E2}) ->			      
  +					  expr_unification(E1,E2)						
  +				  end, lists:zip(Exp1, Exp2));
  +		_ ->
  +		    throw({error, anti_unification_failed})
  +	    end;
  +	{false, false} ->  %% both are single expressions.
  +	    T1 = refac_syntax:type(Exp1),
  +	    T2 = refac_syntax:type(Exp2),
  +	    case T1  of 
  +		atom -> case (T2 == atom) andalso (refac_syntax:atom_value(Exp1) == refac_syntax:atom_value(Exp2)) of 
  +			    true -> [];
  +			    _ -> case variable_replaceable(Exp1) of 
  +				     true ->[Exp1];
  +				     _ -> throw({error, anti_unification_failed})
  +				 end
  +			end;
  +		char -> case (T2==char) andalso (refac_syntax:char_value(Exp1) == refac_syntax:char_value(Exp2)) of 
  +			    true -> [];
  +			    _ -> [Exp1]
  +			end;
  +		integer -> case (T2==integer orelse T2==float) andalso 
  +			       (refac_syntax:integer_value(Exp1) ==refac_syntax:integer_value(Exp2)) of 
  +			       true -> [];
  +			       _ -> [Exp1]
  +			   end;
  +		string -> case (T2==string) andalso refac_syntax:string_value(Exp1) == refac_syntax:string_value(Exp2) of 
  +			      true -> [];
  +			      _ -> [Exp1]
  +			  end;
  +		float -> case (T2==float orelse T2==integer) andalso 
  +			     refac_syntax:float_value(Exp1) == refac_syntax:float_value(Exp2) of 
  +			     true -> [];
  +			     _ -> [Exp1]			 
  +			 end;
  +		_ -> 
  +		    SubTrees1 = erl_syntax:subtrees(Exp1),
  +		    SubTrees2 = erl_syntax:subtrees(Exp2),
  +		    expr_unification(SubTrees1, SubTrees2)				    
  +	    end
  +    end.
  +
  +generalise_expr([], _) ->
  +    "";
  +generalise_expr(Exprs = [H| _T], NodesToGen) ->
  +    case refac_syntax:type(H) of
  +      function -> generalise_fun(H, NodesToGen);
  +      _ -> FunName = refac_syntax:atom(new_fun),
  +	   FVs = lists:keysort(2, refac_util:get_free_vars(Exprs)),
  +	   EVs = lists:keysort(2, refac_util:get_var_exports(Exprs)),
  +	   NewExprs = generalise_expr_1(Exprs, NodesToGen),
  +	   NewExprs1 = case EVs of
  +			 [] -> NewExprs;
  +			 [{V, _}] -> E = refac_syntax:variable(V),
  +				     NewExprs ++ [E];
  +			 [_V| _Vs] -> E = refac_syntax:tuple([refac_syntax:variable(V) || {V, _} <- EVs]),
  +				      NewExprs ++ [E]
  +		       end,
  +	   NewVars = sets:to_list(sets:subtract(collect_vars(NewExprs), collect_vars(Exprs))),
  +	   Pars = lists:map(fun ({V, _}) ->
  +				    refac_syntax:variable(V)
  +			    end,
  +			    FVs)
  +		    ++ lists:map(fun (V) ->
  +					 refac_syntax:variable(V)
  +				 end, NewVars),
  +	   C = refac_syntax:clause(refac_util:remove_duplicates(Pars), none, NewExprs1),
  +	   refac_prettypr:format(refac_syntax:function(FunName, [C]))
  +    end.
  +
  +generalise_fun(F, NodesToGen) ->
  +    FunName = refac_syntax:function_name(F),
  +    Cs = refac_syntax:function_clauses(F),
  +    {Cs1, NewVars} = lists:unzip(lists:map(fun (C) ->
  +						   C1 = generalise_expr_1(C, NodesToGen),
  +						   NewVars = sets:to_list(sets:subtract(collect_vars(C1), collect_vars(C))),
  +						   {C1, NewVars}
  +					   end, Cs)),
  +    NewVars1 = lists:append(NewVars),
  +    NewCs = lists:map(fun (C) ->
  +			      Pats = refac_syntax:clause_patterns(C),
  +			      NewPats = Pats ++ lists:map(fun (V) ->
  +								  refac_syntax:variable(V)
  +							  end,
  +							  refac_util:remove_duplicates(NewVars1)),
  +			      Guards = refac_syntax:clause_guard(C),
  +			      Body = refac_syntax:clause_body(C),
  +			      refac_syntax:clause(NewPats, Guards, Body)
  +		      end, Cs1),
  +    refac_prettypr:format(refac_syntax:function(FunName, NewCs)).
  +
  +
  +generalise_expr_1(Expr, NodesToGen) when is_list(Expr)->
  +     refac_syntax:block_expr_body(generalise_expr_1(refac_syntax:block_expr(Expr), NodesToGen));
  +generalise_expr_1(Expr, NodesToGen) ->
  +    generalise_expr_2(Expr, NodesToGen).
  +
  +generalise_expr_2(Expr, NodesToGen) ->
  +    Pid = start_counter_process(),
  +    {Expr1, _}= refac_util:stop_tdTP(fun do_replace_expr_with_var_1/2, Expr, {NodesToGen,Pid}),
  +    stop_counter_process(Pid),
  +    Expr1.
  +
  +do_replace_expr_with_var_1(Node, {NodesToGen,Pid}) ->
  +    case lists:member(Node,NodesToGen) of
  +	true ->  NewVar = gen_new_var_name(Pid),
  +		 {refac_syntax:variable(NewVar), true};
  +	_ -> {Node, false}
  +    end.
  +
  +collect_vars(Node) when is_list(Node) ->
  +    collect_vars_1(refac_syntax:block_expr(Node));
  +collect_vars(Node) ->
  +    collect_vars_1(Node).
  +collect_vars_1(Node) ->
  +    F = fun(N,S) ->
  +		case refac_syntax:type(N) of 
  +		    variable ->
  +			sets:add_element(refac_syntax:variable_name(N), S);
  +		    _  -> S
  +		end
  +	end,
  +    refac_syntax_lib:fold(F, sets:new(), Node).
  +		
  +			   
  
positive.code: 
  -export([init/1]).
  
  -compile(export_all).
  %% TODO:  
  %% 1) does recusive function calls affect the result?
  %% 2) does qualifed names affect the result? 
  
negative.code: 	_ -> display_clones_1(Cs, Str)
      end.
  display_clones_1([], Str) -> Str ++ "\n";
  display_clones_1([{Ranges, _Len, F, Code}| Cs], Str) ->
      [{{File, StartLine, StartCol}, {File, EndLine, EndCol}}| Range] = lists:keysort(1, Ranges),
      NewStr = compose_clone_info({File, StartLine, StartCol}, {File, EndLine, EndCol}, F, Range, Str),
      NewStr1 = NewStr ++ "The duplicated expression/function after generalisation:\n\n"++ io_lib:format("~s", [Code]) ++ "\n",
      display_clones_1(Cs, NewStr1).
  
  compose_clone_info({File, StartLine, StartCol}, {File, EndLine, EndCol}, F, Range, Str) ->
      case F - 1 of
  	1 -> Str1 = Str ++ "\n" ++ File ++ io_lib:format(":~p.~p-~p.~p: This code has been duplicated once:\n",
  							 [StartLine, lists:max([1, StartCol-1]), EndLine, EndCol]),
  	     display_clones_2(Range, Str1);
  	2 -> Str1 = Str ++ "\n" ++ File ++ io_lib:format(":~p.~p-~p.~p: This code has been duplicated twice:\n",
  							 [StartLine, lists:max([1, StartCol-1]), EndLine, EndCol]),
  	     display_clones_2(Range, Str1);
  	_ -> Str1 = Str ++ "\n" ++ File ++ io_lib:format(":~p.~p-~p.~p: This code has been duplicated ~p times:\n",
  							 [StartLine, lists:max([1, StartCol-1]), EndLine, EndCol, F - 1]),
  	     display_clones_2(Range, Str1)
      end.
  
  