File Coverage

blib/lib/Algorithm/HITS/Lite.pm
Criterion Covered Total %
statement 70 70 100.0
branch 6 6 100.0
condition 2 2 100.0
subroutine 10 10 100.0
pod 2 2 100.0
total 90 90 100.0


line stmt bran cond sub pod time code
1             package Algorithm::HITS::Lite;
2 2     2   10517 use Spiffy -Base;
  2         14518  
  2         17  
3 2     2   9482 our $VERSION = '0.04';
  2     2   5  
  2         316  
  2         26  
  2         4  
  2         3769  
4              
5             =head1 NAME
6              
7             Algorithm::HITS::Lite - HITS algorithm implementation not requiring PDL
8              
9             =head1 SYNOPSIS
10              
11             my $ah = Algorithm::HITS::Lite->new(network => $adjm);
12             my ($hub,$auth) = $ah->iterate(10);
13              
14             =cut
15              
16             field 'network';
17             field nodes => -init => '$self->_collect_nodes';
18              
19             =head1 APIs
20              
21             =head2 new(network => $adjm)
22              
23             The required parameter $adjm is the 'Adjency Matrix' presentation of
24             network, must be a hashref of hashref.
25              
26             =head2 iterate($k)
27              
28             Iterate the process for $k timesm, default to 10 if it's not given.
29             Return a ($hub,$auth) weight pair. Each is a hashref with
30             keys are the same as keys in $adjm.
31              
32             =cut
33              
34 3     3 1 1894 sub iterate {
35 3   100     15 my $k = shift || 10; # iter k times
36 3         67 my $nodes = $self->nodes;
37 3         15 my $xi = $self->_build_z(@$nodes);
38 3         7 my $yi = $self->_build_z(@$nodes);
39 3         4 my ($xj,$yj) = ($xi,$yi);
40 3         17 for(1..$k) {
41 50         95 $xj = $self->_op_T($xi,$yi);
42 50         91 $yj = $self->_op_O($xj,$yi);
43 50         89 $xi = $self->_normalize_xy($xj);
44 50         113 $yi = $self->_normalize_xy($yj);
45             }
46 3         11 return($xi,$yi);
47             }
48              
49             # Collect adjency matrix nodes.
50             # (All hash keys)
51 2     2   16 sub _collect_nodes {
52 2         42 my $adjm = $self->network;
53 2         10 my %nodes;
54 2         7 for my $k1 (keys %$adjm) {
55 3         7 $nodes{$k1} = 1;
56 3         5 for my $k2 (keys %{$adjm->{$k1}}) {
  3         10  
57 1         4 $nodes{$k2} = 1;
58             }
59             }
60 2         9 my @n = keys %nodes;
61 2         44 $self->nodes(\@n);
62 2         24 return [@n];
63             }
64              
65 6     6   6 sub _build_z {
66 6         7 my $z = {};
67 6         22 $z->{$_} = 1 for(@_);
68 6         15 return $z;
69             }
70              
71 100     100   128 sub _normalize_xy {
72 100         102 my $x = shift;
73 100         195 my @vs = values %$x;
74 100         168 my $sq = sqrt($self->sqsum(@vs));
75 100 100       167 if($sq == 0) {
76 40         71 for(keys %$x) {
77 80         114 $x->{$_} = 0;
78             }
79             } else {
80 60         110 for(keys %$x) {
81 120         202 $x->{$_} /= $sq;
82             }
83             }
84 100         239 return $x;
85             }
86              
87              
88 50     50   94 sub _op_T {
89 50         58 my ($x,$y) = @_;
90 50         47 my $nx;
91 50         921 my $g = $self->network;
92 50         961 my $nodes = $self->nodes;
93 50         256 for my $h (@$nodes) {
94 100         138 $nx->{$h} = 0;
95 100         117 for my $p (@$nodes) {
96 200 100       464 $nx->{$h} += $y->{$p} if($g->{$h}->{$p});
97             }
98             }
99 50         93 return $nx;
100             }
101              
102 50     50   54 sub _op_O {
103 50         56 my ($x,$y) = @_;;
104 50         48 my $ny;
105 50         823 my $g = $self->network;
106 50         980 my $nodes = $self->nodes;
107 50         261 for my $p (@$nodes) {
108 100         148 $ny->{$p} = 0;
109 100         114 for my $h (@$nodes) {
110 200 100       519 $ny->{$p} += $x->{$h} if($g->{$h}->{$p});
111             }
112             }
113 50         97 return $ny;
114             }
115              
116              
117             =head2 sqsum(@list)
118              
119             Internally used, return Square Sum of all numbers in @list.
120              
121             =cut
122              
123 100     100 1 119 sub sqsum {
124 100         99 my $sum = 0;
125 100         317 $sum += $_*$_ for(@_);
126 100         180 return $sum;
127             }
128              
129              
130              
131             =head1 SEE ALSO
132              
133             L, L
134              
135             =head1 COPYRIGHT
136              
137             Copyright 2004 by Kang-min Liu .
138              
139             This program is free software; you can redistribute it and/or
140             modify it under the same terms as Perl itself.
141              
142             See
143              
144             =cut