| Filename | /home/s1/perl5/perlbrew/perls/perl-5.22.1/lib/site_perl/5.22.1/Data/Graph/Util.pm |
| Statements | Executed 185 statements in 595µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 78µs | 78µs | Data::Graph::Util::_toposort |
| 1 | 1 | 1 | 30µs | 30µs | Data::Graph::Util::BEGIN@6 |
| 1 | 1 | 1 | 10µs | 14µs | Data::Graph::Util::BEGIN@7 |
| 1 | 1 | 1 | 10µs | 18µs | Data::Graph::Util::BEGIN@8 |
| 1 | 1 | 1 | 10µs | 20µs | Data::Graph::Util::BEGIN@10 |
| 1 | 1 | 1 | 10µs | 26µs | Data::Graph::Util::BEGIN@42 |
| 1 | 1 | 1 | 9µs | 87µs | Data::Graph::Util::toposort |
| 0 | 0 | 0 | 0s | 0s | Data::Graph::Util::is_acyclic |
| 0 | 0 | 0 | 0s | 0s | Data::Graph::Util::is_cyclic |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Data::Graph::Util; | ||||
| 2 | |||||
| 3 | 1 | 500ns | our $DATE = '2016-06-24'; # DATE | ||
| 4 | 1 | 100ns | our $VERSION = '0.002'; # VERSION | ||
| 5 | |||||
| 6 | 2 | 54µs | 1 | 30µs | # spent 30µs within Data::Graph::Util::BEGIN@6 which was called:
# once (30µs+0s) by DateTime::Format::Alami::new at line 6 # spent 30µs making 1 call to Data::Graph::Util::BEGIN@6 |
| 7 | 2 | 27µs | 2 | 18µs | # spent 14µs (10+4) within Data::Graph::Util::BEGIN@7 which was called:
# once (10µs+4µs) by DateTime::Format::Alami::new at line 7 # spent 14µs making 1 call to Data::Graph::Util::BEGIN@7
# spent 4µs making 1 call to strict::import |
| 8 | 2 | 30µs | 2 | 27µs | # spent 18µs (10+9) within Data::Graph::Util::BEGIN@8 which was called:
# once (10µs+9µs) by DateTime::Format::Alami::new at line 8 # spent 18µs making 1 call to Data::Graph::Util::BEGIN@8
# spent 9µs making 1 call to warnings::import |
| 9 | |||||
| 10 | 2 | 166µs | 2 | 29µs | # spent 20µs (10+10) within Data::Graph::Util::BEGIN@10 which was called:
# once (10µs+10µs) by DateTime::Format::Alami::new at line 10 # spent 20µs making 1 call to Data::Graph::Util::BEGIN@10
# spent 10µs making 1 call to Exporter::import |
| 11 | 1 | 1µs | our @EXPORT_OK = qw(toposort is_cyclic is_acyclic); | ||
| 12 | |||||
| 13 | # spent 78µs within Data::Graph::Util::_toposort which was called:
# once (78µs+0s) by Data::Graph::Util::toposort at line 60 | ||||
| 14 | 1 | 300ns | my $graph = shift; | ||
| 15 | |||||
| 16 | # this is the Kahn algorithm, ref: | ||||
| 17 | # https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm | ||||
| 18 | |||||
| 19 | 1 | 200ns | my %in_degree; | ||
| 20 | 1 | 2µs | for my $k (keys %$graph) { | ||
| 21 | 8 | 3µs | $in_degree{$k} //= 0; | ||
| 22 | 33 | 15µs | for (@{ $graph->{$k} }) { $in_degree{$_}++ } | ||
| 23 | } | ||||
| 24 | |||||
| 25 | # collect nodes with no incoming edges (in_degree = 0) | ||||
| 26 | 1 | 200ns | my @S; | ||
| 27 | 24 | 11µs | for (keys %in_degree) { unshift @S, $_ if $in_degree{$_} == 0 } | ||
| 28 | |||||
| 29 | 1 | 100ns | my @L; | ||
| 30 | 1 | 400ns | while (@S) { | ||
| 31 | 23 | 4µs | my $n = pop @S; | ||
| 32 | 23 | 6µs | push @L, $n; | ||
| 33 | 23 | 18µs | for my $m (@{ $graph->{$n} }) { | ||
| 34 | 25 | 14µs | if (--$in_degree{$m} == 0) { | ||
| 35 | unshift @S, $m; | ||||
| 36 | } | ||||
| 37 | } | ||||
| 38 | } | ||||
| 39 | |||||
| 40 | 1 | 600ns | if (@L == keys(%$graph)) { | ||
| 41 | 1 | 300ns | if (@_) { | ||
| 42 | 2 | 223µs | 2 | 42µs | # spent 26µs (10+16) within Data::Graph::Util::BEGIN@42 which was called:
# once (10µs+16µs) by DateTime::Format::Alami::new at line 42 # spent 26µs making 1 call to Data::Graph::Util::BEGIN@42
# spent 16µs making 1 call to warnings::unimport |
| 43 | # user specifies a list to be sorted according to @L. this is like | ||||
| 44 | # Sort::ByExample but we implement it ourselves to avoid dependency. | ||||
| 45 | my %pos; | ||||
| 46 | for (0..$#L) { $pos{$L[$_]} = $_+1 } | ||||
| 47 | return (0, [ | ||||
| 48 | sort { ($pos{$a} || @L+1) <=> ($pos{$b} || @L+1) } @{$_[0]} | ||||
| 49 | ]); | ||||
| 50 | } else { | ||||
| 51 | 1 | 6µs | return (0, \@L); | ||
| 52 | } | ||||
| 53 | } else { | ||||
| 54 | # there is a cycle | ||||
| 55 | return (1, \@L); | ||||
| 56 | } | ||||
| 57 | } | ||||
| 58 | |||||
| 59 | # spent 87µs (9+78) within Data::Graph::Util::toposort which was called:
# once (9µs+78µs) by DateTime::Format::Alami::new at line 84 of lib/DateTime/Format/Alami.pm | ||||
| 60 | 1 | 1µs | 1 | 78µs | my ($err, $res) = _toposort(@_); # spent 78µs making 1 call to Data::Graph::Util::_toposort |
| 61 | 1 | 200ns | die "Can't toposort(), graph is cyclic" if $err; | ||
| 62 | 1 | 6µs | @$res; | ||
| 63 | } | ||||
| 64 | |||||
| 65 | sub is_cyclic { | ||||
| 66 | my ($err, $res) = _toposort(@_); | ||||
| 67 | $err; | ||||
| 68 | } | ||||
| 69 | |||||
| 70 | sub is_acyclic { | ||||
| 71 | my ($err, $res) = _toposort(@_); | ||||
| 72 | !$err; | ||||
| 73 | } | ||||
| 74 | |||||
| 75 | 1 | 4µs | 1; | ||
| 76 | # ABSTRACT: Utilities related to graph data structure | ||||
| 77 | |||||
| 78 | __END__ |