File Coverage

blib/lib/Algorithm/SlopeOne.pm
Criterion Covered Total %
statement 51 51 100.0
branch 8 8 100.0
condition n/a
subroutine 10 10 100.0
pod 5 6 83.3
total 74 75 98.6


line stmt bran cond sub pod time code
1             package Algorithm::SlopeOne;
2             # ABSTRACT: Slope One collaborative filtering for rated resources
3              
4              
5 3     3   71746 use strict;
  3         7  
  3         107  
6 3     3   22 use utf8;
  3         5  
  3         19  
7 3     3   62 use warnings qw(all);
  3         4  
  3         114  
8              
9 3     3   13 use Carp qw(confess);
  3         4  
  3         1716  
10              
11             our $VERSION = '0.004'; # VERSION
12              
13              
14             sub new {
15 2     2 0 22 my ($class) = @_;
16 2         16 return bless {
17             diffs => {},
18             freqs => {},
19             } => $class;
20             }
21              
22              
23             sub diffs {
24 117     117 1 109 my ($self) = @_;
25 117         345 return $self->{diffs};
26             }
27              
28             sub freqs {
29 112     112 1 97 my ($self) = @_;
30 112         201 return $self->{freqs};
31             }
32              
33              
34             sub clear {
35 1     1 1 1 my ($self) = @_;
36              
37 1         4 for (qw(diffs freqs)) {
38 2         8 delete $self->{$_};
39 2         5 $self->{$_} = {};
40             }
41              
42 1         2 return $self;
43             }
44              
45              
46             sub add {
47 5     5 1 1344 my ($self, $userprefs) = @_;
48              
49 5         7 my $type = ref $userprefs;
50 5 100       19 if ($type eq q(HASH)) {
    100          
51 2         3 $userprefs = [ $userprefs ];
52             } elsif ($type eq q(ARRAY)) {
53             } else {
54 1         246 confess q(Expects a HashRef or an ArrayRef of HashRefs);
55             }
56              
57 4         7 for my $ratings (@{$userprefs}) {
  4         6  
58 8         10 for my $item1 (keys %{$ratings}) {
  8         19  
59 27         24 for my $item2 (keys %{$ratings}) {
  27         48  
60 93         140 $self->freqs->{$item1}{$item2} ++;
61 93         148 $self->diffs->{$item1}{$item2} += $ratings->{$item1} - $ratings->{$item2};
62             }
63             }
64             }
65              
66 4         9 return $self;
67             }
68              
69              
70             sub predict {
71 5     5 1 610 my ($self, $userprefs) = @_;
72              
73 5 100       119 confess q(Expects a HashRef)
74             unless q(HASH) eq ref $userprefs;
75              
76 4         6 my (%preds, %freqs);
77 4         7 while (my ($item, $rating) = each %{$userprefs}) {
  9         31  
78 5         13 while (my ($diffitem, $diffratings) = each %{$self->diffs}) {
  24         41  
79 19         32 my $freq = $self->freqs->{$diffitem}{$item};
80 19 100       43 next unless defined $freq;
81 13         25 $preds{$diffitem} += $diffratings->{$item} + ($freq * $rating);
82 13         25 $freqs{$diffitem} += $freq;
83             }
84             }
85              
86             return {
87 6         41 map { $_ => $preds{$_} / $freqs{$_} }
  9         16  
88 4         22 grep { not exists $userprefs->{$_} }
89             keys %preds
90             };
91             }
92              
93              
94             1;
95              
96             __END__