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   555 use strict;
  6         12  
  6         180  
4 6     6   29 use warnings;
  6         9  
  6         191  
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   30 use base 'Graph';
  6         10  
  6         672  
11 6     6   2748 use Graph::TransitiveClosure::Matrix;
  6         16  
  6         2170  
12              
13             sub _G () { Graph::_G() }
14              
15             sub new {
16 75     75 1 397 my ($class, $g, %opt) = @_;
17 75 50 33     725 Graph::__carp_confess(__PACKAGE__."->new given non-Graph '$g'")
18             if !(ref $g and $g->isa('Graph'));
19 75 100       247 %opt = (path_vertices => 1) unless %opt;
20             # No delete $opt{ attribute_name } since we need to pass it on.
21 75 100       400 my $attr = exists $opt{ attribute_name } ? $opt{ attribute_name } : Graph::_defattr();
22 75 100       290 $opt{ reflexive } = 1 unless exists $opt{ reflexive };
23             my $tcg = $g->new(
24             multiedged => 0,
25 75 100       389 ($opt{ reflexive } ? (vertices => [$g->vertices]) : ()),
26             );
27 75         595 my $tcm = $g->_check_cache('transitive_closure_matrix', [],
28             \&_transitive_closure_matrix_compute, %opt);
29 75         299 my $tcm00 = $tcm->[0][0]; # 0=am, 0=bitmatrix
30 75         139 my $tcm01 = $tcm->[0][1]; # , 1=hash mapping v-name to the offset into dm data structures (in retval of $g->vertices)
31 75         120 my @edges;
32 75         285 for my $u ($tcm->vertices) {
33 521         1021 my $tcm00i = $tcm00->[ $tcm01->{ $u } ];
34 521         1065 for my $v ($tcm->vertices) {
35 17191 100 100     25275 next if $u eq $v && ! $opt{ reflexive };
36 17179         19122 my $j = $tcm01->{ $v };
37 17179 100       34455 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         594 $tcg->add_edges(@edges);
43 75         417 $tcg->set_graph_attribute('_tcm', [ $g->[ _G ], $tcm ]);
44 75         1569 bless $tcg, $class;
45             }
46              
47             sub _transitive_closure_matrix_compute {
48 60     60   368 Graph::TransitiveClosure::Matrix->new(@_);
49             }
50              
51             sub is_transitive {
52 10     10 1 773 my $g = shift;
53 10         66 $g->expect_no_args(@_);
54 10         38 Graph::TransitiveClosure::Matrix::is_transitive($g);
55             }
56              
57             sub transitive_closure_matrix {
58 12830     12830 1 23581 $_[0]->get_graph_attribute('_tcm')->[1];
59             }
60              
61             1;
62             __END__