File Coverage

blib/lib/Math/KullbackLeibler/Discrete.pm
Criterion Covered Total %
statement 31 31 100.0
branch 6 6 100.0
condition n/a
subroutine 7 7 100.0
pod 1 1 100.0
total 45 45 100.0


line stmt bran cond sub pod time code
1             package Math::KullbackLeibler::Discrete;
2             $Math::KullbackLeibler::Discrete::VERSION = '0.07';
3 1     1   23837 use 5.006;
  1         5  
  1         63  
4 1     1   7 use strict;
  1         2  
  1         47  
5 1     1   5 use warnings FATAL => 'all';
  1         7  
  1         57  
6 1     1   892 use parent 'Exporter';
  1         331  
  1         6  
7              
8             our @EXPORT = qw(kl);
9              
10              
11             sub kl {
12 5     5 1 276 my ($P, $Q, %opts) = @_;
13              
14 5         9 my $eps = 0.00001;
15              
16 5 100       18 $eps = $opts{epsilon} if exists $opts{epsilon};
17              
18             # Universe
19 5         9 my $SU = {};
20 5         69 $SU->{$_}++ for (keys %$P, keys %$Q);
21              
22             # | Universe - P |
23 5         19 my $susp = scalar(keys %$SU) - scalar(keys %$P);
24              
25             # | Universe - Q |
26 5         9 my $susq = scalar(keys %$SU) - scalar(keys %$Q);
27              
28 5         16 my $pc = $eps * ($susp/scalar(keys %$P));
29 5         10 my $qc = $eps * ($susq/scalar(keys %$Q));
30              
31             my $Pline = sub {
32 30     30   44 my $i = shift;
33 30 100       114 return exists($P->{$i}) ? $P->{$i} - $pc : $eps;
34 5         24 };
35             my $Qline = sub {
36 15     15   19 my $i = shift;
37 15 100       106 return exists($Q->{$i}) ? $Q->{$i} - $qc : $eps;
38 5         18 };
39              
40 5         6 my $kl = 0;
41 5         16 for (keys %$SU) {
42 15         30 $kl += $Pline->($_) * log($Pline->($_) / $Qline->($_));
43             }
44              
45 4         43 return $kl;
46             }
47              
48              
49             1; # End of Math::KullbackLeibler::Discrete
50              
51             __END__