File Coverage

blib/lib/Graph/TransitiveClosure.pm
Criterion Covered Total %
statement 36 36 100.0
branch 13 14 92.8
condition 4 6 66.6
subroutine 8 8 100.0
pod 3 3 100.0
total 64 67 95.5


line stmt bran cond sub pod time code
1             package Graph::TransitiveClosure;
2              
3 6     6   583 use strict;
  6         14  
  6         237  
4 6     6   25 use warnings;
  6         9  
  6         334  
5              
6             # COMMENT THESE OUT FOR TESTING AND PRODUCTION.
7             # $SIG{__DIE__ } = \&Graph::__carp_confess;
8             # $SIG{__WARN__} = \&Graph::__carp_confess;
9              
10 6     6   28 use base 'Graph';
  6         8  
  6         805  
11 6     6   3461 use Graph::TransitiveClosure::Matrix;
  6         17  
  6         2605  
12              
13             sub _G () { Graph::_G() }
14              
15             sub new {
16 75     75 1 476 my ($class, $g, %opt) = @_;
17 75 50 33     844 Graph::__carp_confess(__PACKAGE__."->new given non-Graph '$g'")
18             if !(ref $g and $g->isa('Graph'));
19 75 100       304 %opt = (path_vertices => 1) unless %opt;
20             # No delete $opt{ attribute_name } since we need to pass it on.
21 75 100       379 my $attr = exists $opt{ attribute_name } ? $opt{ attribute_name } : Graph::_defattr();
22 75 100       318 $opt{ reflexive } = 1 unless exists $opt{ reflexive };
23             my $tcg = $g->new(
24             multiedged => 0,
25 75 100       424 ($opt{ reflexive } ? (vertices => [$g->vertices]) : ()),
26             );
27 75         687 my $tcm = $g->_check_cache('transitive_closure_matrix', [],
28             \&_transitive_closure_matrix_compute, %opt);
29 75         268 my $tcm00 = $tcm->[0][0]; # 0=am, 0=bitmatrix
30 75         147 my $tcm01 = $tcm->[0][1]; # , 1=hash mapping v-name to the offset into dm data structures (in retval of $g->vertices)
31 75         193 my @edges;
32 75         302 for my $u ($tcm->vertices) {
33 529         1295 my $tcm00i = $tcm00->[ $tcm01->{ $u } ];
34 529         1680 for my $v ($tcm->vertices) {
35 18731 100 100     44686 next if $u eq $v && ! $opt{ reflexive };
36 18719         34670 my $j = $tcm01->{ $v };
37 18719 100       57295 push @edges, [$u, $v] if vec($tcm00i, $j, 1);
38             # $tcm->is_transitive($u, $v)
39             # $tcm->[0]->get($u, $v)
40             }
41             }
42 75         871 $tcg->add_edges(@edges);
43 75         476 $tcg->set_graph_attribute('_tcm', [ $g->[ _G ], $tcm ]);
44 75         1953 bless $tcg, $class;
45             }
46              
47             sub _transitive_closure_matrix_compute {
48 60     60   380 Graph::TransitiveClosure::Matrix->new(@_);
49             }
50              
51             sub is_transitive {
52 10     10 1 472 my $g = shift;
53 10         74 $g->expect_no_args(@_);
54 10         35 Graph::TransitiveClosure::Matrix::is_transitive($g);
55             }
56              
57             sub transitive_closure_matrix {
58 13884     13884 1 28396 $_[0]->get_graph_attribute('_tcm')->[1];
59             }
60              
61             1;
62             __END__