Skip to content

Instantly share code, notes, and snippets.

@hwatkins
Forked from russelldb/recomendations.erl
Created September 26, 2009 23:35
Show Gist options
  • Save hwatkins/194498 to your computer and use it in GitHub Desktop.
Save hwatkins/194498 to your computer and use it in GitHub Desktop.
%%% File : recomendations.erl
%%% Author : Russell Brown <russell@pango.lan>
%%% Description : The first chapter of Programming Collective Inteligence, but in elrang, like.
%%% Created : 15 Jun 2009 by Russell Brown <russell@pango.lan>
-module(recomendations).
-compile(export_all).
%%
%% @spec data() -> List
%% A list of prefernce data for use in the recomendations functions
%%
data() ->
[{"Lisa Rose", [{"Lady in the Water", 2.5}, { "Snakes on a Plane", 3.5}, {"Just My Luck", 3.0}, {"Superman Returns", 3.5}, {"You, Me and Dupree", 2.5}, {"The Night Listener", 3.0}]},
{"Gene Seymour", [{"Lady in the Water", 3.0}, {"Snakes on a Plane", 3.5}, {"Just My Luck", 1.5}, {"Superman Returns", 5.0}, {"The Night Listener", 3.0}, {"You, Me and Dupree", 3.5}]},
{ "Michael Phillips", [{"Lady in the Water", 2.5}, {"Snakes on a Plane", 3.0}, {"Superman Returns", 3.5}, {"The Night Listener", 4.0}]},
{ "Claudia Puig", [{"Snakes on a Plane", 3.5}, {"Just My Luck", 3.0}, {"The Night Listener", 4.5}, {"Superman Returns", 4.0}, {"You, Me and Dupree", 2.5}]},
{ "Mick LaSalle", [{"Lady in the Water", 3.0}, {"Snakes on a Plane", 4.0}, {"Just My Luck", 2.0}, {"Superman Returns", 3.0}, {"The Night Listener", 3.0}, {"You, Me and Dupree", 2.0}]},
{ "Jack Matthews", [{"Lady in the Water", 3.0}, {"Snakes on a Plane", 4.0},{"The Night Listener", 3.0}, {"Superman Returns", 5.0}, {"You, Me and Dupree", 3.5}]},
{ "Toby", [{"Snakes on a Plane",4.5},{"You, Me and Dupree",1.0},{"Superman Returns",4.0}]}
].
%%
%% @spec euclidean_similarity(Data::prefs(), Person1::string(), Person2::string()) -> float()
%% @type prefs()
%% Figures out how close Person1 and Person2 are using the Euclidean Distance Score.
%%
%%
euclidean_similarity(Data, Person1, Person2) ->
Person1s = proplists:get_value(Person1, Data),
Person2s = proplists:get_value(Person2, Data),
SumOfSquares = lists:sum( [ math:pow(X - Y, 2) || {T, X} <- Person1s, {T1, Y} <- Person2s, T =:= T1] ),
1 / ( 1 + math:sqrt( SumOfSquares ) ).
%%
%% @spec pearson_similarity(Data::prefs(), Person1::string(), Person2::string()) -> float()
%% @type prefs()
%% Figures out how close Person1 and Person2 are using the Pearson Correlation Score.
%%
%%
pearson_similarity(Data, Person1, Person2) ->
Person1s = proplists:get_value(Person1, Data),
Person2s = proplists:get_value(Person2, Data),
{Xs, Ys} = lists:unzip([ {X, Y} || {T, X} <- Person1s, {T1, Y} <- Person2s,
T =:= T1]),
N = length(Xs),
Sum1 = lists:sum( Xs),
Sum2 = lists:sum(Ys ),
Sum1Sq = lists:foldl( fun(X, Acc) -> Acc + math:pow(X, 2) end, 0, Xs),
Sum2Sq = lists:foldl( fun(Y, Acc) -> Acc + math:pow(Y, 2) end, 0, Ys),
SumProd = lists:sum( lists:zipwith(fun(X,Y) -> X * Y end, Xs, Ys) ),
Num = SumProd - (Sum1 * Sum2 /N),
Den = math:sqrt( (Sum1Sq - math:pow(Sum1, 2) / N) * ( Sum2Sq - math:pow(Sum2, 2) / N )),
case Den of
0 ->
0;
_ ->
Num/Den
end.
%%
%% @spec top_matches(Data::prefs(), Person::string, SimalarityFun:function()) -> List
%% returns a list in order of closeness for Person against all others in Data, measured by SimalarityFun
%%
top_matches(Data, Person, SimalarityFun) ->
Peeps = [ Peep || {Peep, _} <- Data, Peep =/= Person ],
Similarities = lists:foldl(fun(X, Acc) -> [{X, SimalarityFun(Data, X, Person)}|Acc] end, [], Peeps),
lists:sort(fun( {_,A}, {_,B} ) -> A>B end, Similarities).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment