line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Graph::AdjacencyMap; |
2
|
|
|
|
|
|
|
|
3
|
80
|
|
|
49119
|
|
462
|
use strict; |
|
80
|
|
|
|
|
124
|
|
|
80
|
|
|
|
|
2046
|
|
4
|
80
|
|
|
80
|
|
330
|
use warnings; |
|
80
|
|
|
|
|
120
|
|
|
80
|
|
|
|
|
9753
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# $SIG{__DIE__ } = \&Graph::__carp_confess; |
7
|
|
|
|
|
|
|
# $SIG{__WARN__} = \&Graph::__carp_confess; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
my $empty = {}; |
10
|
82
|
|
|
82
|
|
522
|
sub _empty () { $empty } |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my (@FLAGS, %FLAG_COMBOS, %FLAG2I, @FIELDS); |
13
|
|
|
|
|
|
|
BEGIN { |
14
|
80
|
|
|
80
|
|
371
|
@FLAGS = qw(_COUNT _MULTI _UNORD _REF _UNIONFIND _LIGHT _STR); |
15
|
80
|
|
|
|
|
473
|
%FLAG_COMBOS = ( |
16
|
|
|
|
|
|
|
_COUNTMULTI => [qw(_COUNT _MULTI)], |
17
|
|
|
|
|
|
|
_REFSTR => [qw(_REF _STR)], |
18
|
|
|
|
|
|
|
); |
19
|
|
|
|
|
|
|
# Next id, Flags, Arity, Index to path, path to index, |
20
|
|
|
|
|
|
|
# successors, predecessors: 2-level hashes to array-ref of path IDs |
21
|
|
|
|
|
|
|
# attributes - two-level for MULTI, node/multi count |
22
|
80
|
|
|
|
|
231
|
@FIELDS = qw(_n _f _arity _i _pi _s _p _attr _count); |
23
|
80
|
|
|
|
|
282
|
for my $i (0..$#FLAGS) { |
24
|
560
|
|
|
|
|
925
|
my $n = $FLAGS[$i]; |
25
|
560
|
|
|
|
|
717
|
my $f = 1 << $i; |
26
|
560
|
|
|
|
|
972
|
$FLAG2I{$n} = $f; |
27
|
80
|
|
|
80
|
|
508
|
no strict 'refs'; |
|
80
|
|
|
|
|
134
|
|
|
80
|
|
|
|
|
11174
|
|
28
|
560
|
|
|
|
|
3619
|
*$n = sub () { $f }; |
|
0
|
|
|
|
|
0
|
|
29
|
560
|
|
|
70689
|
|
2143
|
*{"_is$n"} = sub { $_[0]->[ 1 ] & $f }; # 1 = _f |
|
560
|
|
|
66593
|
|
2235
|
|
|
70689
|
|
|
|
|
192123
|
|
30
|
|
|
|
|
|
|
} |
31
|
80
|
|
|
|
|
309
|
for my $k (keys %FLAG_COMBOS) { |
32
|
160
|
|
|
|
|
251
|
my $f = 0; |
33
|
160
|
|
|
|
|
238
|
$f |= $_ for map $FLAG2I{$_}, @{ $FLAG_COMBOS{$k} }; |
|
160
|
|
|
|
|
641
|
|
34
|
80
|
|
|
80
|
|
521
|
no strict 'refs'; |
|
80
|
|
|
|
|
1490
|
|
|
80
|
|
|
|
|
7825
|
|
35
|
160
|
|
|
1325
|
|
965
|
*$k = sub () { return $f }; # return to dodge pointless 5.22 stricture |
|
1325
|
|
|
|
|
4152
|
|
36
|
160
|
|
|
1
|
|
493
|
*{"_is$k"} = sub { $_[0]->[ 1 ] & $f }; # 1 = _f |
|
160
|
|
|
0
|
|
709
|
|
|
1
|
|
|
|
|
6
|
|
37
|
|
|
|
|
|
|
} |
38
|
80
|
|
|
|
|
334
|
for my $i (0..$#FIELDS) { |
39
|
80
|
|
|
80
|
|
520
|
no strict 'refs'; |
|
80
|
|
|
|
|
163
|
|
|
80
|
|
|
|
|
5008
|
|
40
|
720
|
|
|
|
|
2991
|
*{ $FIELDS[$i] }= sub () { $i }; |
|
720
|
|
|
|
|
11569
|
|
|
0
|
|
|
|
|
0
|
|
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub _new { |
45
|
1792
|
|
|
1792
|
|
4628
|
my ($class, $flags, $arity) = @_; |
46
|
1792
|
|
|
|
|
2493
|
my $hyper = !$arity; |
47
|
1792
|
|
|
|
|
2425
|
my $need_s = $arity != 1; |
48
|
1792
|
|
100
|
|
|
5981
|
my $need_p = $need_s && !($flags & _UNORD); |
49
|
1792
|
100
|
|
|
|
9216
|
bless [ |
|
|
100
|
|
|
|
|
|
50
|
|
|
|
|
|
|
0, $flags, $arity, [], {}, |
51
|
|
|
|
|
|
|
($need_s ? {} : undef), ($need_p ? {} : undef), |
52
|
|
|
|
|
|
|
[], [], |
53
|
|
|
|
|
|
|
], $class; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
require Exporter; |
57
|
80
|
|
|
80
|
|
561
|
use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS); |
|
80
|
|
|
|
|
142
|
|
|
80
|
|
|
|
|
314813
|
|
58
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
59
|
|
|
|
|
|
|
%EXPORT_TAGS = |
60
|
|
|
|
|
|
|
(flags => [@FLAGS, keys %FLAG_COMBOS, qw(_GEN_ID)], |
61
|
|
|
|
|
|
|
fields => \@FIELDS); |
62
|
|
|
|
|
|
|
@EXPORT_OK = map @$_, values %EXPORT_TAGS; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
my $_GEN_ID = 0; |
65
|
|
|
|
|
|
|
|
66
|
168
|
|
|
168
|
|
691
|
sub _GEN_ID () { \$_GEN_ID } |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub stringify { |
69
|
24
|
|
|
24
|
1
|
3000
|
my ($f, $arity, $m) = (@{ $_[0] }[ _f, _arity ], $_[0]); |
|
24
|
|
|
|
|
67
|
|
70
|
24
|
|
|
|
|
56
|
my ($multi, @rows) = $f & _MULTI; |
71
|
24
|
|
|
|
|
55
|
my @p = $m->paths; |
72
|
|
|
|
|
|
|
@p = $arity == 1 ? sort @p : |
73
|
24
|
100
|
100
|
|
|
238
|
map $_->[0], sort { $a->[1] cmp $b->[1] } |
|
138
|
100
|
|
|
|
164
|
|
74
|
|
|
|
|
|
|
($arity == 0 && !($f & _UNORD)) |
75
|
|
|
|
|
|
|
? map [$_, join '|', map "@$_", @$_], @p |
76
|
|
|
|
|
|
|
: map [$_,"@$_"], @p; # use the Schwartz |
77
|
24
|
100
|
|
|
|
84
|
if ($arity == 2) { |
78
|
10
|
|
|
|
|
642
|
require Set::Object; |
79
|
10
|
|
|
|
|
6863
|
my ($pre, $suc, @s) = (Set::Object->new(map $_->[0], @p), Set::Object->new(map $_->[1], @p)); |
80
|
|
|
|
|
|
|
@rows = ([ 'to:', @s = sort $suc->members ], map { |
81
|
10
|
|
|
|
|
83
|
my $p = $_; |
|
24
|
|
|
|
|
35
|
|
82
|
|
|
|
|
|
|
[ $p, map { |
83
|
24
|
100
|
|
|
|
35
|
my $text = defined(my $id = $m->has_path([$p, $_])) ? 1 : ''; |
|
93
|
|
|
|
|
230
|
|
84
|
93
|
100
|
|
|
|
229
|
my $attrs = !$text ? undef : |
|
|
100
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$multi ? $m->[ _attr ][$id] : $m->_get_path_attrs([$p, $_]); |
86
|
93
|
100
|
|
|
|
229
|
defined $attrs ? $m->_dumper($attrs) : $text; |
87
|
|
|
|
|
|
|
} @s ]; |
88
|
|
|
|
|
|
|
} sort $pre->members); |
89
|
|
|
|
|
|
|
} else { |
90
|
|
|
|
|
|
|
@rows = map { |
91
|
14
|
100
|
|
|
|
27
|
my $attrs = $multi |
|
33
|
|
|
|
|
190
|
|
92
|
|
|
|
|
|
|
? $m->[ _attr ][ $m->has_path($_) ] : $m->_get_path_attrs($_); |
93
|
33
|
100
|
|
|
|
73
|
[ $m->_dumper($_), |
94
|
|
|
|
|
|
|
($m->get_ids_by_paths([ $_ ], 0))[0]. |
95
|
|
|
|
|
|
|
(!defined $attrs ? '' : ",".$m->_dumper($attrs)) ]; |
96
|
|
|
|
|
|
|
} @p; |
97
|
|
|
|
|
|
|
} |
98
|
24
|
|
|
|
|
194
|
join '', |
99
|
|
|
|
|
|
|
map "$_\n", |
100
|
24
|
|
|
|
|
103
|
"@{[ref $m]} arity=$arity flags: @{[_stringify_fields($m->[ _f ])]}", |
|
24
|
|
|
|
|
63
|
|
101
|
|
|
|
|
|
|
map join(' ', map sprintf('%4s', $_), @$_), |
102
|
|
|
|
|
|
|
@rows; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub _stringify_fields { |
106
|
38
|
100
|
|
38
|
|
380
|
return '0' if !$_[0]; |
107
|
30
|
|
|
|
|
536
|
join '|', grep $_[0] & $FLAG2I{$_}, @FLAGS; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub _dumper { |
111
|
58
|
|
|
58
|
|
138
|
my (undef, $got) = @_; |
112
|
58
|
100
|
66
|
|
|
260
|
return $got if defined $got and !ref $got; |
113
|
31
|
|
|
|
|
1391
|
require Data::Dumper; |
114
|
31
|
|
|
|
|
11978
|
my $dumper = Data::Dumper->new([$got]); |
115
|
31
|
|
|
|
|
993
|
$dumper->Indent(0)->Terse(1); |
116
|
31
|
50
|
|
|
|
610
|
$dumper->Sortkeys(1) if $dumper->can("Sortkeys"); |
117
|
31
|
|
|
|
|
196
|
$dumper->Dump; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub has_any_paths { |
121
|
90
|
|
|
90
|
1
|
10910
|
scalar keys %{ $_[0]->[ _pi ] }; |
|
90
|
|
|
|
|
398
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub _set_path_attr_common { |
125
|
125
|
|
|
125
|
|
262
|
push @_, 0; |
126
|
125
|
|
|
|
|
225
|
my ($i) = &__set_path; |
127
|
125
|
|
|
|
|
229
|
my $attr = (my $m = $_[0])->[ _attr ]; |
128
|
125
|
100
|
|
|
|
745
|
($m->[ _f ] & _MULTI) ? \$attr->[ $i ]{ $_[2] } : \$attr->[ $i ]; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub _set_path_attrs { |
132
|
1129
|
|
|
1129
|
|
7453
|
${ &{ $_[0]->can('_set_path_attr_common') } } = $_[-1]; |
|
1129
|
|
|
|
|
1214
|
|
|
1129
|
|
|
|
|
3091
|
|
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub _set_path_attr { |
136
|
4714
|
|
|
4714
|
|
12510
|
${ &{ $_[0]->can('_set_path_attr_common') } }->{ $_[-2] } = $_[-1]; |
|
4714
|
|
|
|
|
5015
|
|
|
4714
|
|
|
|
|
13563
|
|
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub set_paths { |
140
|
333
|
|
|
333
|
1
|
993
|
map +($_[0]->__set_path($_, 1))[0], @_[1..$#_]; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub set_path_by_multi_id { |
144
|
112
|
|
|
112
|
1
|
207
|
push @_, 1; |
145
|
112
|
|
|
|
|
325
|
goto &__set_path; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub __set_path { |
149
|
556
|
|
|
556
|
|
823
|
my $inc_if_exists = pop; |
150
|
556
|
|
|
|
|
1025
|
&__arg; |
151
|
556
|
|
|
|
|
725
|
my ($f, $a, $map_i, $pi, $map_s, $map_p, $m, $k, $id) = (@{ $_[0] }[ _f, _arity, _i, _pi, _s, _p ], @_); |
|
556
|
|
|
|
|
1262
|
|
152
|
556
|
|
|
|
|
793
|
my $is_multi = $f & _MULTI; |
153
|
556
|
|
|
|
|
664
|
my $k_orig = $k; |
154
|
556
|
100
|
100
|
|
|
1773
|
$k = __strval($k, $f) if $a == 1 && ($f & _REF) && ref($k); |
|
|
|
100
|
|
|
|
|
155
|
556
|
100
|
100
|
|
|
1970
|
my $l = ($a == 0 && !($f & _UNORD)) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
156
|
556
|
100
|
|
|
|
1122
|
if (exists $pi->{ $l }) { |
157
|
189
|
100
|
100
|
|
|
702
|
return ($pi->{ $l }) if !($inc_if_exists and ($f & _COUNTMULTI)); |
158
|
53
|
|
|
|
|
173
|
my $nc = \$m->[ _count ][ my $i = $pi->{ $l } ]; |
159
|
53
|
100
|
|
|
|
180
|
$$nc++, return ($i) if !$is_multi; |
160
|
32
|
|
|
|
|
53
|
my $na = $m->[ _attr ][ $i ]; |
161
|
32
|
100
|
|
|
|
66
|
if ($id eq _GEN_ID) { |
162
|
17
|
|
|
|
|
63
|
$$nc++ while exists $na->{ $$nc }; |
163
|
17
|
|
|
|
|
34
|
$id = $$nc; |
164
|
|
|
|
|
|
|
} |
165
|
32
|
|
|
|
|
80
|
$na->{ $id } = { }; |
166
|
32
|
|
|
|
|
115
|
return ($i, $id); |
167
|
|
|
|
|
|
|
} |
168
|
367
|
|
|
|
|
958
|
$map_i->[ $pi->{ $l } = my $i = $m->[ _n ]++ ] = $k_orig; |
169
|
367
|
100
|
|
|
|
736
|
$m->[ _attr ][ $i ] = { ($id = ($id eq _GEN_ID) ? 0 : $id) => {} } if $is_multi; |
|
|
100
|
|
|
|
|
|
170
|
367
|
100
|
|
|
|
669
|
$m->[ _count ][ $i ] = $is_multi ? 0 : 1 if ($f & _COUNTMULTI); |
|
|
100
|
|
|
|
|
|
171
|
367
|
100
|
|
|
|
828
|
_successors_add($f, $a, $map_s, $map_p, $i, $k) if $map_s; # dereffed |
172
|
367
|
|
|
|
|
1217
|
($i, $id); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub _successors_add { |
176
|
117
|
|
|
117
|
|
245
|
my ($f, $a, $map_s, $map_p, $id, $path) = @_; |
177
|
117
|
|
|
|
|
333
|
my $pairs = _successors_cartesian(($f & _UNORD), $a == 0, $path); |
178
|
117
|
|
|
|
|
257
|
push @{ $map_s->{ $_->[0] }{ $_->[1] } }, $id for @$pairs; |
|
240
|
|
|
|
|
680
|
|
179
|
117
|
100
|
|
|
|
304
|
return if !$map_p; |
180
|
78
|
|
|
|
|
132
|
push @{ $map_p->{ $_->[1] }{ $_->[0] } }, $id for @$pairs; |
|
124
|
|
|
|
|
376
|
|
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub _successors_del { |
184
|
24
|
|
|
24
|
|
65
|
my ($f, $a, $map_s, $map_p, $id, $path) = @_; |
185
|
24
|
|
|
|
|
85
|
my $pairs = _successors_cartesian(($f & _UNORD), $a == 0, $path); |
186
|
24
|
|
|
|
|
59
|
for (@$pairs) { |
187
|
61
|
|
|
|
|
108
|
my ($p, $s) = @$_; |
188
|
61
|
|
|
|
|
71
|
my @new = grep $_ != $id, @{ $map_s->{ $p }{ $s } }; |
|
61
|
|
|
|
|
159
|
|
189
|
61
|
100
|
|
|
|
120
|
if (@new) { |
190
|
2
|
|
|
|
|
4
|
$map_s->{ $p }{ $s } = \@new; |
191
|
2
|
50
|
|
|
|
5
|
$map_p->{ $s }{ $p } = \@new if $map_p; |
192
|
2
|
|
|
|
|
4
|
next; |
193
|
|
|
|
|
|
|
} |
194
|
59
|
|
|
|
|
102
|
delete $map_s->{ $p }{ $s }; |
195
|
59
|
100
|
|
|
|
66
|
delete $map_s->{ $p } if !keys %{ $map_s->{ $p } }; |
|
59
|
|
|
|
|
138
|
|
196
|
59
|
100
|
|
|
|
122
|
next if !$map_p; |
197
|
27
|
|
|
|
|
51
|
delete $map_p->{ $s }{ $p }; |
198
|
27
|
100
|
|
|
|
29
|
delete $map_p->{ $s } if !keys %{ $map_p->{ $s } }; |
|
27
|
|
|
|
|
95
|
|
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub _successors_cartesian { |
203
|
26776
|
|
|
26776
|
|
34638
|
my ($unord, $hyper, $seq) = @_; |
204
|
26776
|
100
|
100
|
|
|
65878
|
return [ $seq ] if !$unord and !$hyper; |
205
|
11869
|
100
|
100
|
|
|
30231
|
return [] if $unord and $hyper and !@$seq; |
|
|
|
100
|
|
|
|
|
206
|
11864
|
|
|
|
|
15801
|
my ($allow_self, $p_s, $s_s, @pairs); |
207
|
11864
|
100
|
|
|
|
16073
|
if ($unord) { |
208
|
11848
|
|
|
|
|
60912
|
require Set::Object; |
209
|
11848
|
|
|
|
|
291478
|
my @a = Set::Object->new(@$seq)->members; |
210
|
11848
|
|
|
|
|
50364
|
($allow_self, $p_s, $s_s) = (@a < 2, \@a, \@a); |
211
|
|
|
|
|
|
|
} else { |
212
|
16
|
|
|
|
|
33
|
($allow_self, $p_s, $s_s) = (1, @$seq); |
213
|
|
|
|
|
|
|
} |
214
|
11864
|
|
|
|
|
20797
|
for my $p (@$p_s) { |
215
|
23479
|
100
|
|
|
|
87308
|
push @pairs, map [$p, $_], $allow_self ? @$s_s : grep $p != $_, @$s_s; |
216
|
|
|
|
|
|
|
} |
217
|
11864
|
|
|
|
|
28574
|
\@pairs; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub _get_path_count { |
221
|
217
|
100
|
|
217
|
|
5300
|
return 0 unless my ($i) = &__has_path; |
222
|
194
|
|
|
|
|
385
|
my $f = (my $m = $_[0])->[ _f ]; |
223
|
|
|
|
|
|
|
return |
224
|
|
|
|
|
|
|
($f & _COUNT) ? $m->[ _count ][ $i ] : |
225
|
194
|
100
|
|
|
|
662
|
($f & _MULTI) ? scalar keys %{ $m->[ _attr ][ $i ] } : 1; |
|
90
|
100
|
|
|
|
402
|
|
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub has_path { |
229
|
706
|
|
|
706
|
1
|
11448
|
( &__has_path )[0]; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub has_path_by_multi_id { |
233
|
268
|
100
|
|
268
|
1
|
3055
|
return undef unless my ($i) = &__has_path; |
234
|
235
|
|
|
|
|
853
|
return exists $_[0]->[ _attr ][ $i ]{ $_[2] }; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub del_path { |
238
|
208
|
100
|
|
208
|
1
|
890
|
return unless my ($i, $l) = &__has_path; |
239
|
207
|
100
|
100
|
|
|
376
|
return 1 if &_is_COUNT and --$_[0][ _count ][ $i ] > 0; |
240
|
195
|
|
|
|
|
527
|
$_[0]->_sequence_del($i, $l); |
241
|
195
|
|
|
|
|
313
|
1; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub del_path_by_multi_id { |
245
|
17
|
50
|
|
17
|
1
|
61
|
return unless my ($i, $l) = &__has_path; |
246
|
17
|
|
|
|
|
46
|
delete((my $attrs = (my $m = $_[0])->[ _attr ][ $i ])->{ $_[2] }); |
247
|
17
|
100
|
|
|
|
43
|
return 1 if keys %$attrs; |
248
|
9
|
|
|
|
|
27
|
$m->_sequence_del($i, $l); |
249
|
9
|
|
|
|
|
17
|
1; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub get_multi_ids { |
253
|
51
|
100
|
66
|
51
|
1
|
177
|
return unless ((my $m = $_[0])->[ _f ] & _MULTI) and my ($i) = &__has_path; |
254
|
49
|
|
|
|
|
72
|
keys %{ $m->[ _attr ][ $i ] }; |
|
49
|
|
|
|
|
233
|
|
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub rename_path { |
258
|
32
|
|
|
32
|
1
|
1977
|
my ($m, $from, $to) = @_; |
259
|
32
|
50
|
|
|
|
91
|
return 1 if $m->[ _arity ] != 1; # all integers, no names |
260
|
32
|
50
|
|
|
|
68
|
return unless my ($i, $l) = $m->__has_path($from); |
261
|
32
|
|
|
|
|
57
|
$m->[ _i ][ $i ] = $to; |
262
|
32
|
100
|
66
|
|
|
82
|
$to = __strval($to, $m->[ _f ]) if ref($to) and ($m->[ _f ] & _REF); |
263
|
32
|
|
|
|
|
71
|
$m->[ _pi ]{ $to } = delete $m->[ _pi ]{ $l }; |
264
|
32
|
|
|
|
|
79
|
return 1; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub _del_path_attrs { |
268
|
38
|
50
|
|
38
|
|
90
|
return unless my ($i) = &__has_path; |
269
|
38
|
|
|
|
|
79
|
my $attr = (my $m = $_[0])->[ _attr ]; |
270
|
38
|
100
|
|
|
|
139
|
return $attr->[ $i ]{ $_[2] } = undef, 1 if ($m->[ _f ] & _MULTI); |
271
|
27
|
|
|
|
|
85
|
delete $attr->[ $i ]; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub __has_path { |
275
|
1892
|
|
|
1892
|
|
3787
|
&__arg; |
276
|
1892
|
|
|
|
|
2265
|
my ($f, $a, $pi, $k) = (@{ $_[0] }[ _f, _arity, _pi ], $_[1]); |
|
1892
|
|
|
|
|
3199
|
|
277
|
1892
|
100
|
100
|
|
|
6652
|
$k = __strval($k, $f) if $a == 1 && ($f & _REF) && ref($k); |
|
|
|
100
|
|
|
|
|
278
|
1892
|
100
|
100
|
|
|
5742
|
my $l = ($a == 0 && !($f & _UNORD)) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
279
|
1892
|
|
|
|
|
2676
|
my $id = $pi->{ $l }; |
280
|
1892
|
100
|
|
|
|
6491
|
(defined $id ? $id : return, $l); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub _get_path_attrs { |
284
|
355
|
100
|
|
355
|
|
2292
|
return unless my ($i) = &__has_path; |
285
|
346
|
|
|
|
|
647
|
my $attrs = (my $m = $_[0])->[ _attr ][ $i ]; |
286
|
346
|
100
|
|
|
|
1918
|
($m->[ _f ] & _MULTI) ? $attrs->{ $_[2] } : $attrs; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _has_path_attrs { |
290
|
82
|
100
|
|
82
|
|
5937
|
keys %{ &{ $_[0]->can('_get_path_attrs') } || return undef } ? 1 : 0; |
|
82
|
100
|
|
|
|
117
|
|
|
82
|
|
|
|
|
325
|
|
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _has_path_attr { |
294
|
62
|
|
100
|
62
|
|
120
|
exists(( &{ $_[0]->can('_get_path_attrs') } || return )->{ $_[-1] }); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub _get_path_attr { |
298
|
11429
|
|
100
|
11429
|
|
13483
|
( &{ $_[0]->can('_get_path_attrs') } || return )->{ $_[-1] }; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub _get_path_attr_names { |
302
|
78
|
100
|
|
78
|
|
175
|
keys %{ &{ $_[0]->can('_get_path_attrs') } || return }; |
|
78
|
|
|
|
|
102
|
|
|
78
|
|
|
|
|
265
|
|
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub _get_path_attr_values { |
306
|
26
|
100
|
|
26
|
|
49
|
values %{ &{ $_[0]->can('_get_path_attrs') } || return }; |
|
26
|
|
|
|
|
46
|
|
|
26
|
|
|
|
|
145
|
|
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub _del_path_attr { |
310
|
40
|
100
|
|
40
|
|
9072
|
return unless my $attrs = &{ $_[0]->can('_get_path_attrs') }; |
|
40
|
|
|
|
|
152
|
|
311
|
36
|
50
|
|
|
|
111
|
return 0 unless exists $attrs->{ my $attr = $_[-1] }; |
312
|
36
|
|
|
|
|
71
|
delete $attrs->{$attr}; |
313
|
36
|
100
|
|
|
|
121
|
return 1 if keys %$attrs; |
314
|
15
|
|
|
|
|
27
|
&{ $_[0]->can('_del_path_attrs') }; |
|
15
|
|
|
|
|
79
|
|
315
|
15
|
|
|
|
|
36
|
1; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _sequence_del { |
319
|
204
|
|
|
204
|
|
360
|
my ($m, $id, $l) = @_; |
320
|
204
|
|
|
|
|
412
|
my ($f, $a, $map_i, $pi, $map_s, $map_p) = @$m[ _f, _arity, _i, _pi, _s, _p ]; |
321
|
204
|
|
|
|
|
363
|
delete $pi->{ $l }; |
322
|
204
|
|
|
|
|
525
|
delete $m->[ $_ ][ $id ] for _count, _attr; |
323
|
204
|
|
|
|
|
306
|
my $path = delete $map_i->[ $id ]; |
324
|
204
|
100
|
|
|
|
455
|
_successors_del($f, $a, $map_s, $map_p, $id, $path) if $map_s; |
325
|
204
|
|
|
|
|
298
|
return 1; |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub get_paths_by_ids { |
329
|
23452
|
|
|
23452
|
1
|
30833
|
my ($i, undef, $list, $deep) = ( @{ $_[0] }[ _i ], @_ ); |
|
23452
|
|
|
|
|
43785
|
|
330
|
23452
|
100
|
|
|
|
150720
|
$deep ? map [ map [ @$i[ @$_ ] ], @$_ ], @$list : map [ @$i[ @$_ ] ], @$list; |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub paths { |
334
|
3917
|
50
|
|
3917
|
1
|
4940
|
grep defined, @{ $_[0]->[ _i ] || Graph::_empty_array() }; |
|
3917
|
|
|
|
|
27568
|
|
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
sub get_ids_by_paths { |
338
|
1230
|
|
|
1230
|
1
|
13592
|
my ($f, $a, $pi, $m, $list, $ensure, $deep) = ( @{ $_[0] }[ _f, _arity, _pi ], @_ ); |
|
1230
|
|
|
|
|
2676
|
|
339
|
1230
|
|
100
|
|
|
3801
|
$deep ||= 0; |
340
|
1230
|
|
|
|
|
3328
|
my ($is_multi, $is_ref, $is_unord) = (map $f & $_, _MULTI, _REF, _UNORD); |
341
|
|
|
|
|
|
|
return map { # Fast path |
342
|
1230
|
100
|
100
|
|
|
3908
|
my @ret = map { |
|
|
|
100
|
|
|
|
|
343
|
121
|
100
|
|
|
|
234
|
my $id = $pi->{ $a != 1 ? "@$_" : $_ }; |
|
154
|
100
|
|
|
|
296
|
|
344
|
154
|
100
|
|
|
|
391
|
defined $id ? $id : |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
345
|
|
|
|
|
|
|
!$ensure ? return : |
346
|
|
|
|
|
|
|
($is_multi ? $m->set_path_by_multi_id($_, _GEN_ID) : $m->set_paths($_))[0]; |
347
|
|
|
|
|
|
|
} $deep ? @$_ : $_; |
348
|
108
|
100
|
|
|
|
371
|
$deep ? \@ret : @ret; |
349
|
|
|
|
|
|
|
} @$list if $a and !$is_ref and $deep < 2; |
350
|
|
|
|
|
|
|
map { |
351
|
1106
|
|
|
|
|
1475
|
my @ret = map { |
352
|
1165
|
100
|
|
|
|
1837
|
my @ret2 = map { |
353
|
1276
|
100
|
|
|
|
1828
|
my $k = $_; |
|
1289
|
|
|
|
|
1626
|
|
354
|
1289
|
100
|
100
|
|
|
4696
|
$k = __strval($k, $f) if $a == 1 && $is_ref && ref($k); |
|
|
|
100
|
|
|
|
|
355
|
1289
|
100
|
100
|
|
|
3379
|
my $l = ($a == 0 && !$is_unord) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
356
|
1289
|
|
|
|
|
1733
|
my $id = $pi->{ $l }; |
357
|
1289
|
50
|
|
|
|
3547
|
defined $id ? $id : |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
358
|
|
|
|
|
|
|
!$ensure ? return : |
359
|
|
|
|
|
|
|
($is_multi ? $m->set_path_by_multi_id($_, _GEN_ID) : $m->set_paths($_))[0]; |
360
|
|
|
|
|
|
|
} $deep > 1 ? @$_ : $_; |
361
|
1115
|
100
|
|
|
|
2251
|
$deep > 1 ? \@ret2 : @ret2; |
362
|
|
|
|
|
|
|
} $deep ? @$_ : $_; |
363
|
1004
|
100
|
|
|
|
3020
|
$deep ? \@ret : @ret; |
364
|
|
|
|
|
|
|
} @$list; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub _paths_fromto { |
368
|
46
|
|
|
46
|
|
69
|
my $offset = pop; |
369
|
46
|
|
|
|
|
65
|
my ($i, $map_x, @v) = ( @{ $_[0] }[ _i, $offset ], @_[1..$#_] ); |
|
46
|
|
|
|
|
145
|
|
370
|
46
|
50
|
|
|
|
159
|
Graph::__carp_confess("undefined vertex") if grep !defined, @v; |
371
|
46
|
|
|
|
|
222
|
require Set::Object; |
372
|
46
|
100
|
|
|
|
85
|
map $i->[ $_ ], Set::Object->new(map @$_, map values %{ $map_x->{ $_ } || _empty }, @v)->members; |
|
52
|
|
|
|
|
680
|
|
373
|
|
|
|
|
|
|
} |
374
|
31
|
|
|
31
|
1
|
6037
|
sub paths_from { push @_, _s; goto &_paths_fromto } |
|
31
|
|
|
|
|
95
|
|
375
|
15
|
|
|
15
|
1
|
2926
|
sub paths_to { push @_, _p; goto &_paths_fromto } |
|
15
|
|
|
|
|
46
|
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub _cessors { |
378
|
181
|
|
|
181
|
|
237
|
my $offset = pop; |
379
|
181
|
|
|
|
|
228
|
my ($map_x, @v) = ( @{ $_[0] }[ $offset ], @_[1..$#_] ); |
|
181
|
|
|
|
|
481
|
|
380
|
181
|
50
|
|
|
|
449
|
Graph::__carp_confess("undefined vertex") if grep !defined, @v; |
381
|
181
|
|
|
|
|
1198
|
require Set::Object; |
382
|
181
|
100
|
|
|
|
6803
|
Set::Object->new(map keys %{ $map_x->{ $_ } || _empty }, @v)->members; |
|
187
|
|
|
|
|
1261
|
|
383
|
|
|
|
|
|
|
} |
384
|
140
|
|
|
140
|
1
|
4965
|
sub successors { push @_, _s; goto &_cessors } |
|
140
|
|
|
|
|
306
|
|
385
|
41
|
|
|
41
|
1
|
3735
|
sub predecessors { push @_, _p; goto &_cessors } |
|
41
|
|
|
|
|
104
|
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub has_successor { |
388
|
72
|
|
|
72
|
1
|
6720
|
my ($map_s, $u, $v) = ( @{ $_[0] }[ _s ], @_[1, 2] ); |
|
72
|
|
|
|
|
184
|
|
389
|
72
|
50
|
|
|
|
245
|
Graph::__carp_confess("undefined vertex") if grep !defined, $u, $v; |
390
|
72
|
100
|
|
|
|
98
|
exists ${ $map_s->{ $u } || _empty }{ $v }; |
|
72
|
|
|
|
|
298
|
|
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
sub __strval { |
394
|
2079
|
|
|
2079
|
|
2827
|
my ($k, $f) = @_; |
395
|
2079
|
50
|
33
|
|
|
5009
|
return $k unless ref $k && ($f & _REF); |
396
|
2079
|
100
|
|
|
|
3168
|
return "$k" if ($f & _STR); |
397
|
2075
|
|
|
|
|
7713
|
require Scalar::Util; |
398
|
2075
|
|
|
|
|
4180
|
Scalar::Util::refaddr($k); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub __arg { |
402
|
2448
|
|
|
2448
|
|
2874
|
my ($f, $a, $m, $k) = (@{ $_[0] }[ _f, _arity ], @_[0, 1]); |
|
2448
|
|
|
|
|
5149
|
|
403
|
2448
|
50
|
66
|
|
|
6616
|
Graph::__carp_confess(sprintf "arguments %d (%s) expected %d for\n".$m->stringify, |
404
|
|
|
|
|
|
|
scalar @$k, "@$k", $a) |
405
|
|
|
|
|
|
|
if $a > 1 and @$k != $a; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub reindex { |
409
|
3
|
|
|
3
|
1
|
487
|
my ($f, $a, $i2p, $m) = (@{ $_[0] }[ _f, _arity, _i ], $_[0]); |
|
3
|
|
|
|
|
13
|
|
410
|
3
|
|
33
|
|
|
19
|
my $is_ref = $a == 1 && ($f & _REF); |
411
|
3
|
|
|
|
|
9
|
my $pi = $m->[ _pi ] = {}; |
412
|
3
|
|
|
|
|
6
|
for my $i ( 0..$#{ $i2p } ) { |
|
3
|
|
|
|
|
11
|
|
413
|
4
|
50
|
|
|
|
13
|
next if !defined(my $k = $i2p->[ $i ]); # deleted |
414
|
4
|
50
|
33
|
|
|
23
|
$k = __strval($k, $f) if $is_ref && ref($k); |
415
|
4
|
|
|
|
|
15
|
$pi->{ $k } = $i; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
1; |
420
|
|
|
|
|
|
|
__END__ |