File Coverage

blib/lib/Set/Similarity/CosinePP.pm
Criterion Covered Total %
statement 41 41 100.0
branch 2 2 100.0
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 54 54 100.0


line stmt bran cond sub pod time code
1             package Set::Similarity::CosinePP;
2              
3 1     1   1592 use strict;
  1         4  
  1         89  
4 1     1   15 use warnings;
  1         4  
  1         93  
5              
6 1     1   1363 use parent 'Set::Similarity';
  1         618  
  1         8  
7              
8             our $VERSION = '0.014';
9              
10             sub from_sets {
11 21     21 1 30582 my ($self, $set1, $set2) = @_;
12 21         89 my $cosine = $self->_cosine(
13             $self->_normalize($self->_make_vector( $set1 )),
14             $self->_normalize($self->_make_vector( $set2 ))
15             );
16 21         333 return $cosine;
17             }
18              
19             sub _make_vector {
20 42     42   96 my ( $self, $tokens ) = @_;
21 42         73 my %elements;
22 42         242 do { $_++ } for @elements{@$tokens};
  122         291  
23 42         196 return \%elements;
24             }
25              
26             # Assumes both incoming vectors are normalized
27 21     21   74 sub _cosine { shift->_dot( @_ ) }
28              
29             sub _norm {
30 42     42   77 my $self = shift;
31 42         76 my $vector = shift;
32 42         76 my $sum = 0;
33 42         222 for my $key (keys %$vector) {
34 122         349 $sum += $vector->{$key} ** 2;
35             }
36 42         215 return sqrt $sum;
37             }
38              
39             sub _normalize {
40 42     42   89 my $self = shift;
41 42         93 my $vector = shift;
42              
43 42         117 return $self->_div(
44             $vector,
45             $self->_norm($vector)
46             );
47             }
48              
49             sub _dot {
50 21     21   41 my $self = shift;
51 21         35 my $vector1 = shift;
52 21         32 my $vector2 = shift;
53              
54 21         37 my $dotprod = 0;
55              
56 21         110 for my $key (keys %$vector1) {
57 64 100       277 $dotprod += $vector1->{$key} * $vector2->{$key} if ($vector2->{$key});
58             }
59 21         84 return $dotprod;
60             }
61              
62              
63             # divides each vector entry by a given divisor
64             sub _div {
65 42     42   96 my $self = shift;
66 42         70 my $vector = shift;
67 42         70 my $divisor = shift;
68              
69 42         100 my $vector2 = {};
70 42         170 for my $key (keys %$vector) {
71 122         479 $vector2->{$key} = $vector->{$key} / $divisor;
72             }
73 42         217 return $vector2;
74             }
75              
76              
77             1;
78              
79              
80             __END__