File Coverage

lib/Graph/Algorithm/HITS.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Graph::Algorithm::HITS;
2              
3 1     1   928 use strict;
  1         2  
  1         42  
4 1     1   32 use 5.008_005;
  1         4  
  1         59  
5             our $VERSION = '0.02';
6              
7 1     1   2762 use Moo;
  1         39583  
  1         6  
8 1     1   1974 use Graph;
  1         2  
  1         22  
9 1     1   426 use PDL;
  0            
  0            
10             use Carp;
11              
12             has graph => (is => 'ro', required => 1);
13             has adj_matrix => (is => 'ro', lazy => 1, builder => '_adj_matrix_builder');
14             has trans_adj => (is => 'ro', lazy => 1, builder => '_trans_adj_builder');
15             has trans_x_adj => (
16             is => 'ro',
17             lazy => 1,
18             default => sub {
19             my $self = shift;
20             $self->trans_adj x $self->adj_matrix;
21             }
22             );
23              
24             has hub_matrix => (
25             is => 'rw',
26             lazy => 1,
27             default => sub {
28             my $self = shift;
29             my $size = $self->graph->vertices;
30             ones 1,$size;
31             }
32             );
33              
34             has auth_matrix => (
35             is => 'rw',
36             lazy => 1,
37             default => sub {
38             my $self = shift;
39             my $size = $self->graph->vertices;
40             ones 1,$size;
41             },
42             );
43              
44             sub BUILD {
45             my $self = shift;
46             # make sure it's directed graph
47             unless ($self->graph->is_directed) {
48             croak 'Graph needs to be directed';
49             }
50             }
51              
52             #Create adjacency matrix from graph
53             sub _adj_matrix_builder {
54             my $self = shift;
55             my $matrix = [];
56             for my $v1 (sort $self->graph->vertices ) {
57             my @row = ();
58             for my $v2 (sort $self->graph->vertices ){
59             if ($v1 eq $v2) {
60             push @row, 0;
61             }else {
62             if ($self->graph->has_edge($v1, $v2)){
63             push @row, 1;
64             }else {
65             push @row, 0;
66             }
67             }
68             }
69             push @$matrix, \@row;
70             }
71             return pdl $matrix;
72             }
73              
74             #Create transpose adjacency matrix
75             sub _trans_adj_builder {
76             my $self = shift;
77             return transpose $self->adj_matrix;
78             }
79              
80             sub iterate {
81             my ($self, $itr) = @_;
82             for (1..$itr) {
83             my $m = $self->trans_x_adj x $self->auth_matrix;
84             $self->auth_matrix($m/$self->_get_sum($m));
85             }
86             my $m = $self->adj_matrix x $self->auth_matrix;
87             $self->hub_matrix($m/$self->_get_sum($m));
88             }
89              
90             sub _get_sum {
91             my ($self, $m) = @_;
92             my $result = unpdl $m;
93             my $sum=0;
94             $sum += shift @$_ for (@$result);
95             return $sum;
96             }
97              
98             sub get_authority {
99             my $self = shift;
100             my $ref = unpdl $self->auth_matrix;
101             my %result;
102             for my $v (sort $self->graph->vertices) {
103             $result{$v} = shift @{ shift @$ref };
104             }
105             return \%result;
106             }
107              
108             sub get_hub {
109             my $self = shift;
110             my $ref = unpdl $self->hub_matrix;
111             my %result;
112             for my $v (sort $self->graph->vertices) {
113             $result{$v} = shift @{ shift @$ref };
114             }
115             return \%result;
116             }
117              
118             1;
119             __END__