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   573 use strict;
  6         13  
  6         192  
4 6     6   30 use warnings;
  6         17  
  6         175  
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   35 use base 'Graph';
  6         12  
  6         613  
11 6     6   3362 use Graph::TransitiveClosure::Matrix;
  6         15  
  6         2604  
12              
13             sub _G () { Graph::_G() }
14              
15             sub new {
16 75     75 1 337 my ($class, $g, %opt) = @_;
17 75 50 33     554 Graph::__carp_confess(__PACKAGE__."->new given non-Graph '$g'")
18             if !(ref $g and $g->isa('Graph'));
19 75 100       220 %opt = (path_vertices => 1) unless %opt;
20             # No delete $opt{ attribute_name } since we need to pass it on.
21 75 100       293 my $attr = exists $opt{ attribute_name } ? $opt{ attribute_name } : Graph::_defattr();
22 75 100       245 $opt{ reflexive } = 1 unless exists $opt{ reflexive };
23             my $tcg = $g->new(
24             multiedged => 0,
25 75 100       345 ($opt{ reflexive } ? (vertices => [$g->vertices]) : ()),
26             );
27 75         536 my $tcm = $g->_check_cache('transitive_closure_matrix', [],
28             \&_transitive_closure_matrix_compute, %opt);
29 75         198 my $tcm00 = $tcm->[0][0]; # 0=am, 0=bitmatrix
30 75         123 my $tcm01 = $tcm->[0][1]; # , 1=hash mapping v-name to the offset into dm data structures (in retval of $g->vertices)
31 75         117 my @edges;
32 75         246 for my $u ($tcm->vertices) {
33 528         1088 my $tcm00i = $tcm00->[ $tcm01->{ $u } ];
34 528         1364 for my $v ($tcm->vertices) {
35 18712 100 100     33594 next if $u eq $v && ! $opt{ reflexive };
36 18700         26390 my $j = $tcm01->{ $v };
37 18700 100       44959 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         610 $tcg->add_edges(@edges);
43 75         402 $tcg->set_graph_attribute('_tcm', [ $g->[ _G ], $tcm ]);
44 75         1617 bless $tcg, $class;
45             }
46              
47             sub _transitive_closure_matrix_compute {
48 60     60   336 Graph::TransitiveClosure::Matrix->new(@_);
49             }
50              
51             sub is_transitive {
52 10     10 1 794 my $g = shift;
53 10         52 $g->expect_no_args(@_);
54 10         29 Graph::TransitiveClosure::Matrix::is_transitive($g);
55             }
56              
57             sub transitive_closure_matrix {
58 13451     13451 1 28212 $_[0]->get_graph_attribute('_tcm')->[1];
59             }
60              
61             1;
62             __END__