line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Graph::AdjacencyMap; |
2
|
|
|
|
|
|
|
|
3
|
80
|
|
|
52791
|
|
558
|
use strict; |
|
80
|
|
|
|
|
167
|
|
|
80
|
|
|
|
|
2419
|
|
4
|
80
|
|
|
80
|
|
390
|
use warnings; |
|
80
|
|
|
|
|
174
|
|
|
80
|
|
|
|
|
12188
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# $SIG{__DIE__ } = \&Graph::__carp_confess; |
7
|
|
|
|
|
|
|
# $SIG{__WARN__} = \&Graph::__carp_confess; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
my $empty = {}; |
10
|
82
|
|
|
82
|
|
599
|
sub _empty () { $empty } |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my (@FLAGS, %FLAG_COMBOS, %FLAG2I, @FIELDS); |
13
|
|
|
|
|
|
|
BEGIN { |
14
|
80
|
|
|
80
|
|
985
|
@FLAGS = qw(_COUNT _MULTI _UNORD _REF _UNIONFIND _LIGHT _STR); |
15
|
80
|
|
|
|
|
481
|
%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
|
|
|
|
|
283
|
@FIELDS = qw(_n _f _arity _i _pi _s _p _attr _count); |
23
|
80
|
|
|
|
|
438
|
for my $i (0..$#FLAGS) { |
24
|
560
|
|
|
|
|
1138
|
my $n = $FLAGS[$i]; |
25
|
560
|
|
|
|
|
898
|
my $f = 1 << $i; |
26
|
560
|
|
|
|
|
1248
|
$FLAG2I{$n} = $f; |
27
|
80
|
|
|
80
|
|
652
|
no strict 'refs'; |
|
80
|
|
|
|
|
178
|
|
|
80
|
|
|
|
|
13463
|
|
28
|
560
|
|
|
|
|
4451
|
*$n = sub () { $f }; |
|
0
|
|
|
|
|
0
|
|
29
|
560
|
|
|
71030
|
|
2659
|
*{"_is$n"} = sub { $_[0]->[ 1 ] & $f }; # 1 = _f |
|
560
|
|
|
67958
|
|
3170
|
|
|
71030
|
|
|
|
|
228294
|
|
30
|
|
|
|
|
|
|
} |
31
|
80
|
|
|
|
|
375
|
for my $k (keys %FLAG_COMBOS) { |
32
|
160
|
|
|
|
|
307
|
my $f = 0; |
33
|
160
|
|
|
|
|
283
|
$f |= $_ for map $FLAG2I{$_}, @{ $FLAG_COMBOS{$k} }; |
|
160
|
|
|
|
|
877
|
|
34
|
80
|
|
|
80
|
|
647
|
no strict 'refs'; |
|
80
|
|
|
|
|
1977
|
|
|
80
|
|
|
|
|
9472
|
|
35
|
160
|
|
|
1328
|
|
1074
|
*$k = sub () { return $f }; # return to dodge pointless 5.22 stricture |
|
1328
|
|
|
|
|
4265
|
|
36
|
160
|
|
|
1
|
|
622
|
*{"_is$k"} = sub { $_[0]->[ 1 ] & $f }; # 1 = _f |
|
160
|
|
|
0
|
|
939
|
|
|
1
|
|
|
|
|
5
|
|
37
|
|
|
|
|
|
|
} |
38
|
80
|
|
|
|
|
366
|
for my $i (0..$#FIELDS) { |
39
|
80
|
|
|
80
|
|
679
|
no strict 'refs'; |
|
80
|
|
|
|
|
275
|
|
|
80
|
|
|
|
|
6131
|
|
40
|
720
|
|
|
|
|
3478
|
*{ $FIELDS[$i] }= sub () { $i }; |
|
720
|
|
|
|
|
14179
|
|
|
0
|
|
|
|
|
0
|
|
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub _new { |
45
|
1798
|
|
|
1798
|
|
5453
|
my ($class, $flags, $arity) = @_; |
46
|
1798
|
|
|
|
|
2802
|
my $hyper = !$arity; |
47
|
1798
|
|
|
|
|
2840
|
my $need_s = $arity != 1; |
48
|
1798
|
|
100
|
|
|
5226
|
my $need_p = $need_s && !($flags & _UNORD); |
49
|
1798
|
100
|
|
|
|
10104
|
bless [ |
|
|
100
|
|
|
|
|
|
50
|
|
|
|
|
|
|
0, $flags, $arity, [], {}, |
51
|
|
|
|
|
|
|
($need_s ? {} : undef), ($need_p ? {} : undef), |
52
|
|
|
|
|
|
|
[], [], |
53
|
|
|
|
|
|
|
], $class; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
require Exporter; |
57
|
80
|
|
|
80
|
|
661
|
use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS); |
|
80
|
|
|
|
|
239
|
|
|
80
|
|
|
|
|
373319
|
|
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
|
|
677
|
sub _GEN_ID () { \$_GEN_ID } |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub stringify { |
69
|
24
|
|
|
24
|
1
|
5595
|
my ($f, $arity, $m) = (@{ $_[0] }[ _f, _arity ], $_[0]); |
|
24
|
|
|
|
|
84
|
|
70
|
24
|
|
|
|
|
61
|
my ($multi, @rows) = $f & _MULTI; |
71
|
24
|
|
|
|
|
56
|
my @p = $m->paths; |
72
|
|
|
|
|
|
|
@p = $arity == 1 ? sort @p : |
73
|
24
|
100
|
100
|
|
|
305
|
map $_->[0], sort { $a->[1] cmp $b->[1] } |
|
138
|
100
|
|
|
|
198
|
|
74
|
|
|
|
|
|
|
($arity == 0 && !($f & _UNORD)) |
75
|
|
|
|
|
|
|
? map [$_, join '|', map "@$_", @$_], @p |
76
|
|
|
|
|
|
|
: map [$_,"@$_"], @p; # use the Schwartz |
77
|
24
|
100
|
|
|
|
88
|
if ($arity == 2) { |
78
|
10
|
|
|
|
|
727
|
require Set::Object; |
79
|
10
|
|
|
|
|
8788
|
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
|
|
|
|
|
107
|
my $p = $_; |
|
24
|
|
|
|
|
36
|
|
82
|
|
|
|
|
|
|
[ $p, map { |
83
|
24
|
100
|
|
|
|
47
|
my $text = defined(my $id = $m->has_path([$p, $_])) ? 1 : ''; |
|
93
|
|
|
|
|
278
|
|
84
|
93
|
100
|
|
|
|
274
|
my $attrs = !$text ? undef : |
|
|
100
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$multi ? $m->[ _attr ][$id] : $m->_get_path_attrs([$p, $_]); |
86
|
93
|
100
|
|
|
|
281
|
defined $attrs ? $m->_dumper($attrs) : $text; |
87
|
|
|
|
|
|
|
} @s ]; |
88
|
|
|
|
|
|
|
} sort $pre->members); |
89
|
|
|
|
|
|
|
} else { |
90
|
|
|
|
|
|
|
@rows = map { |
91
|
14
|
100
|
|
|
|
32
|
my $attrs = $multi |
|
33
|
|
|
|
|
214
|
|
92
|
|
|
|
|
|
|
? $m->[ _attr ][ $m->has_path($_) ] : $m->_get_path_attrs($_); |
93
|
33
|
100
|
|
|
|
89
|
[ $m->_dumper($_), |
94
|
|
|
|
|
|
|
($m->get_ids_by_paths([ $_ ], 0))[0]. |
95
|
|
|
|
|
|
|
(!defined $attrs ? '' : ",".$m->_dumper($attrs)) ]; |
96
|
|
|
|
|
|
|
} @p; |
97
|
|
|
|
|
|
|
} |
98
|
24
|
|
|
|
|
239
|
join '', |
99
|
|
|
|
|
|
|
map "$_\n", |
100
|
24
|
|
|
|
|
124
|
"@{[ref $m]} arity=$arity flags: @{[_stringify_fields($m->[ _f ])]}", |
|
24
|
|
|
|
|
65
|
|
101
|
|
|
|
|
|
|
map join(' ', map sprintf('%4s', $_), @$_), |
102
|
|
|
|
|
|
|
@rows; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub _stringify_fields { |
106
|
38
|
100
|
|
38
|
|
383
|
return '0' if !$_[0]; |
107
|
30
|
|
|
|
|
586
|
join '|', grep $_[0] & $FLAG2I{$_}, @FLAGS; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub _dumper { |
111
|
58
|
|
|
58
|
|
141
|
my (undef, $got) = @_; |
112
|
58
|
100
|
66
|
|
|
311
|
return $got if defined $got and !ref $got; |
113
|
31
|
|
|
|
|
1675
|
require Data::Dumper; |
114
|
31
|
|
|
|
|
14724
|
my $dumper = Data::Dumper->new([$got]); |
115
|
31
|
|
|
|
|
945
|
$dumper->Indent(0)->Terse(1); |
116
|
31
|
50
|
|
|
|
660
|
$dumper->Sortkeys(1) if $dumper->can("Sortkeys"); |
117
|
31
|
|
|
|
|
183
|
$dumper->Dump; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub has_any_paths { |
121
|
90
|
|
|
90
|
1
|
15467
|
scalar keys %{ $_[0]->[ _pi ] }; |
|
90
|
|
|
|
|
436
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub _set_path_attr_common { |
125
|
125
|
|
|
125
|
|
277
|
push @_, 0; |
126
|
125
|
|
|
|
|
228
|
my ($i) = &__set_path; |
127
|
125
|
|
|
|
|
245
|
my $attr = (my $m = $_[0])->[ _attr ]; |
128
|
125
|
100
|
|
|
|
847
|
($m->[ _f ] & _MULTI) ? \$attr->[ $i ]{ $_[2] } : \$attr->[ $i ]; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub _set_path_attrs { |
132
|
1128
|
|
|
1128
|
|
9937
|
${ &{ $_[0]->can('_set_path_attr_common') } } = $_[-1]; |
|
1128
|
|
|
|
|
1442
|
|
|
1128
|
|
|
|
|
3364
|
|
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub _set_path_attr { |
136
|
4751
|
|
|
4751
|
|
15576
|
${ &{ $_[0]->can('_set_path_attr_common') } }->{ $_[-2] } = $_[-1]; |
|
4751
|
|
|
|
|
6343
|
|
|
4751
|
|
|
|
|
16122
|
|
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub set_paths { |
140
|
333
|
|
|
333
|
1
|
1188
|
map +($_[0]->__set_path($_, 1))[0], @_[1..$#_]; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub set_path_by_multi_id { |
144
|
112
|
|
|
112
|
1
|
244
|
push @_, 1; |
145
|
112
|
|
|
|
|
309
|
goto &__set_path; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub __set_path { |
149
|
556
|
|
|
556
|
|
832
|
my $inc_if_exists = pop; |
150
|
556
|
|
|
|
|
1275
|
&__arg; |
151
|
556
|
|
|
|
|
929
|
my ($f, $a, $map_i, $pi, $map_s, $map_p, $m, $k, $id) = (@{ $_[0] }[ _f, _arity, _i, _pi, _s, _p ], @_); |
|
556
|
|
|
|
|
1458
|
|
152
|
556
|
|
|
|
|
926
|
my $is_multi = $f & _MULTI; |
153
|
556
|
|
|
|
|
791
|
my $k_orig = $k; |
154
|
556
|
100
|
100
|
|
|
2149
|
$k = __strval($k, $f) if $a == 1 && ($f & _REF) && ref($k); |
|
|
|
100
|
|
|
|
|
155
|
556
|
100
|
100
|
|
|
2236
|
my $l = ($a == 0 && !($f & _UNORD)) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
156
|
556
|
100
|
|
|
|
1315
|
if (exists $pi->{ $l }) { |
157
|
189
|
100
|
100
|
|
|
769
|
return ($pi->{ $l }) if !($inc_if_exists and ($f & _COUNTMULTI)); |
158
|
53
|
|
|
|
|
193
|
my $nc = \$m->[ _count ][ my $i = $pi->{ $l } ]; |
159
|
53
|
100
|
|
|
|
218
|
$$nc++, return ($i) if !$is_multi; |
160
|
32
|
|
|
|
|
70
|
my $na = $m->[ _attr ][ $i ]; |
161
|
32
|
100
|
|
|
|
71
|
if ($id eq _GEN_ID) { |
162
|
17
|
|
|
|
|
112
|
$$nc++ while exists $na->{ $$nc }; |
163
|
17
|
|
|
|
|
42
|
$id = $$nc; |
164
|
|
|
|
|
|
|
} |
165
|
32
|
|
|
|
|
84
|
$na->{ $id } = { }; |
166
|
32
|
|
|
|
|
140
|
return ($i, $id); |
167
|
|
|
|
|
|
|
} |
168
|
367
|
|
|
|
|
1176
|
$map_i->[ $pi->{ $l } = my $i = $m->[ _n ]++ ] = $k_orig; |
169
|
367
|
100
|
|
|
|
797
|
$m->[ _attr ][ $i ] = { ($id = ($id eq _GEN_ID) ? 0 : $id) => {} } if $is_multi; |
|
|
100
|
|
|
|
|
|
170
|
367
|
100
|
|
|
|
668
|
$m->[ _count ][ $i ] = $is_multi ? 0 : 1 if ($f & _COUNTMULTI); |
|
|
100
|
|
|
|
|
|
171
|
367
|
100
|
|
|
|
984
|
_successors_add($f, $a, $map_s, $map_p, $i, $k) if $map_s; # dereffed |
172
|
367
|
|
|
|
|
1418
|
($i, $id); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub _successors_add { |
176
|
117
|
|
|
117
|
|
275
|
my ($f, $a, $map_s, $map_p, $id, $path) = @_; |
177
|
117
|
|
|
|
|
356
|
my $pairs = _successors_cartesian(($f & _UNORD), $a == 0, $path); |
178
|
117
|
|
|
|
|
348
|
push @{ $map_s->{ $_->[0] }{ $_->[1] } }, $id for @$pairs; |
|
240
|
|
|
|
|
770
|
|
179
|
117
|
100
|
|
|
|
337
|
return if !$map_p; |
180
|
78
|
|
|
|
|
151
|
push @{ $map_p->{ $_->[1] }{ $_->[0] } }, $id for @$pairs; |
|
124
|
|
|
|
|
473
|
|
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub _successors_del { |
184
|
24
|
|
|
24
|
|
64
|
my ($f, $a, $map_s, $map_p, $id, $path) = @_; |
185
|
24
|
|
|
|
|
73
|
my $pairs = _successors_cartesian(($f & _UNORD), $a == 0, $path); |
186
|
24
|
|
|
|
|
106
|
for (@$pairs) { |
187
|
61
|
|
|
|
|
129
|
my ($p, $s) = @$_; |
188
|
61
|
|
|
|
|
90
|
my @new = grep $_ != $id, @{ $map_s->{ $p }{ $s } }; |
|
61
|
|
|
|
|
177
|
|
189
|
61
|
100
|
|
|
|
140
|
if (@new) { |
190
|
2
|
|
|
|
|
5
|
$map_s->{ $p }{ $s } = \@new; |
191
|
2
|
50
|
|
|
|
5
|
$map_p->{ $s }{ $p } = \@new if $map_p; |
192
|
2
|
|
|
|
|
5
|
next; |
193
|
|
|
|
|
|
|
} |
194
|
59
|
|
|
|
|
128
|
delete $map_s->{ $p }{ $s }; |
195
|
59
|
100
|
|
|
|
82
|
delete $map_s->{ $p } if !keys %{ $map_s->{ $p } }; |
|
59
|
|
|
|
|
165
|
|
196
|
59
|
100
|
|
|
|
160
|
next if !$map_p; |
197
|
27
|
|
|
|
|
64
|
delete $map_p->{ $s }{ $p }; |
198
|
27
|
100
|
|
|
|
40
|
delete $map_p->{ $s } if !keys %{ $map_p->{ $s } }; |
|
27
|
|
|
|
|
116
|
|
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub _successors_cartesian { |
203
|
27040
|
|
|
27040
|
|
42181
|
my ($unord, $hyper, $seq) = @_; |
204
|
27040
|
100
|
100
|
|
|
81642
|
return [ $seq ] if !$unord and !$hyper; |
205
|
11905
|
100
|
100
|
|
|
36660
|
return [] if $unord and $hyper and !@$seq; |
|
|
|
100
|
|
|
|
|
206
|
11900
|
|
|
|
|
17057
|
my ($allow_self, $p_s, $s_s, @pairs); |
207
|
11900
|
100
|
|
|
|
20113
|
if ($unord) { |
208
|
11884
|
|
|
|
|
70399
|
require Set::Object; |
209
|
11884
|
|
|
|
|
335365
|
my @a = Set::Object->new(@$seq)->members; |
210
|
11884
|
|
|
|
|
58903
|
($allow_self, $p_s, $s_s) = (@a < 2, \@a, \@a); |
211
|
|
|
|
|
|
|
} else { |
212
|
16
|
|
|
|
|
47
|
($allow_self, $p_s, $s_s) = (1, @$seq); |
213
|
|
|
|
|
|
|
} |
214
|
11900
|
|
|
|
|
24219
|
for my $p (@$p_s) { |
215
|
23547
|
100
|
|
|
|
105525
|
push @pairs, map [$p, $_], $allow_self ? @$s_s : grep $p != $_, @$s_s; |
216
|
|
|
|
|
|
|
} |
217
|
11900
|
|
|
|
|
34313
|
\@pairs; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub _get_path_count { |
221
|
217
|
100
|
|
217
|
|
6482
|
return 0 unless my ($i) = &__has_path; |
222
|
194
|
|
|
|
|
411
|
my $f = (my $m = $_[0])->[ _f ]; |
223
|
|
|
|
|
|
|
return |
224
|
|
|
|
|
|
|
($f & _COUNT) ? $m->[ _count ][ $i ] : |
225
|
194
|
100
|
|
|
|
771
|
($f & _MULTI) ? scalar keys %{ $m->[ _attr ][ $i ] } : 1; |
|
90
|
100
|
|
|
|
498
|
|
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub has_path { |
229
|
778
|
|
|
778
|
1
|
14379
|
( &__has_path )[0]; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub has_path_by_multi_id { |
233
|
268
|
100
|
|
268
|
1
|
3866
|
return undef unless my ($i) = &__has_path; |
234
|
235
|
|
|
|
|
1006
|
return exists $_[0]->[ _attr ][ $i ]{ $_[2] }; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub del_path { |
238
|
208
|
100
|
|
208
|
1
|
6014
|
return unless my ($i, $l) = &__has_path; |
239
|
207
|
100
|
100
|
|
|
501
|
return 1 if &_is_COUNT and --$_[0][ _count ][ $i ] > 0; |
240
|
195
|
|
|
|
|
544
|
$_[0]->_sequence_del($i, $l); |
241
|
195
|
|
|
|
|
357
|
1; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub del_path_by_multi_id { |
245
|
17
|
50
|
|
17
|
1
|
1176
|
return unless my ($i, $l) = &__has_path; |
246
|
17
|
|
|
|
|
75
|
delete((my $attrs = (my $m = $_[0])->[ _attr ][ $i ])->{ $_[2] }); |
247
|
17
|
100
|
|
|
|
57
|
return 1 if keys %$attrs; |
248
|
9
|
|
|
|
|
31
|
$m->_sequence_del($i, $l); |
249
|
9
|
|
|
|
|
22
|
1; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub get_multi_ids { |
253
|
51
|
100
|
66
|
51
|
1
|
209
|
return unless ((my $m = $_[0])->[ _f ] & _MULTI) and my ($i) = &__has_path; |
254
|
49
|
|
|
|
|
90
|
keys %{ $m->[ _attr ][ $i ] }; |
|
49
|
|
|
|
|
291
|
|
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub rename_path { |
258
|
32
|
|
|
32
|
1
|
2480
|
my ($m, $from, $to) = @_; |
259
|
32
|
50
|
|
|
|
78
|
return 1 if $m->[ _arity ] != 1; # all integers, no names |
260
|
32
|
50
|
|
|
|
71
|
return unless my ($i, $l) = $m->__has_path($from); |
261
|
32
|
|
|
|
|
81
|
$m->[ _i ][ $i ] = $to; |
262
|
32
|
100
|
66
|
|
|
88
|
$to = __strval($to, $m->[ _f ]) if ref($to) and ($m->[ _f ] & _REF); |
263
|
32
|
|
|
|
|
173
|
$m->[ _pi ]{ $to } = delete $m->[ _pi ]{ $l }; |
264
|
32
|
|
|
|
|
108
|
return 1; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub _del_path_attrs { |
268
|
38
|
50
|
|
38
|
|
78
|
return unless my ($i) = &__has_path; |
269
|
38
|
|
|
|
|
81
|
my $attr = (my $m = $_[0])->[ _attr ]; |
270
|
38
|
100
|
|
|
|
140
|
return $attr->[ $i ]{ $_[2] } = undef, 1 if ($m->[ _f ] & _MULTI); |
271
|
27
|
|
|
|
|
87
|
delete $attr->[ $i ]; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub __has_path { |
275
|
1964
|
|
|
1964
|
|
4435
|
&__arg; |
276
|
1964
|
|
|
|
|
3080
|
my ($f, $a, $pi, $k) = (@{ $_[0] }[ _f, _arity, _pi ], $_[1]); |
|
1964
|
|
|
|
|
3912
|
|
277
|
1964
|
100
|
100
|
|
|
8379
|
$k = __strval($k, $f) if $a == 1 && ($f & _REF) && ref($k); |
|
|
|
100
|
|
|
|
|
278
|
1964
|
100
|
100
|
|
|
7600
|
my $l = ($a == 0 && !($f & _UNORD)) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
279
|
1964
|
|
|
|
|
3511
|
my $id = $pi->{ $l }; |
280
|
1964
|
100
|
|
|
|
8199
|
(defined $id ? $id : return, $l); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub _get_path_attrs { |
284
|
355
|
100
|
|
355
|
|
2871
|
return unless my ($i) = &__has_path; |
285
|
346
|
|
|
|
|
707
|
my $attrs = (my $m = $_[0])->[ _attr ][ $i ]; |
286
|
346
|
100
|
|
|
|
2458
|
($m->[ _f ] & _MULTI) ? $attrs->{ $_[2] } : $attrs; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _has_path_attrs { |
290
|
82
|
100
|
|
82
|
|
7615
|
keys %{ &{ $_[0]->can('_get_path_attrs') } || return undef } ? 1 : 0; |
|
82
|
100
|
|
|
|
119
|
|
|
82
|
|
|
|
|
325
|
|
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _has_path_attr { |
294
|
62
|
|
100
|
62
|
|
124
|
exists(( &{ $_[0]->can('_get_path_attrs') } || return )->{ $_[-1] }); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub _get_path_attr { |
298
|
11514
|
|
100
|
11514
|
|
15809
|
( &{ $_[0]->can('_get_path_attrs') } || return )->{ $_[-1] }; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub _get_path_attr_names { |
302
|
78
|
100
|
|
78
|
|
202
|
keys %{ &{ $_[0]->can('_get_path_attrs') } || return }; |
|
78
|
|
|
|
|
152
|
|
|
78
|
|
|
|
|
292
|
|
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub _get_path_attr_values { |
306
|
26
|
100
|
|
26
|
|
50
|
values %{ &{ $_[0]->can('_get_path_attrs') } || return }; |
|
26
|
|
|
|
|
48
|
|
|
26
|
|
|
|
|
119
|
|
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub _del_path_attr { |
310
|
40
|
100
|
|
40
|
|
9744
|
return unless my $attrs = &{ $_[0]->can('_get_path_attrs') }; |
|
40
|
|
|
|
|
181
|
|
311
|
36
|
50
|
|
|
|
125
|
return 0 unless exists $attrs->{ my $attr = $_[-1] }; |
312
|
36
|
|
|
|
|
98
|
delete $attrs->{$attr}; |
313
|
36
|
100
|
|
|
|
121
|
return 1 if keys %$attrs; |
314
|
15
|
|
|
|
|
31
|
&{ $_[0]->can('_del_path_attrs') }; |
|
15
|
|
|
|
|
71
|
|
315
|
15
|
|
|
|
|
42
|
1; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _sequence_del { |
319
|
204
|
|
|
204
|
|
440
|
my ($m, $id, $l) = @_; |
320
|
204
|
|
|
|
|
485
|
my ($f, $a, $map_i, $pi, $map_s, $map_p) = @$m[ _f, _arity, _i, _pi, _s, _p ]; |
321
|
204
|
|
|
|
|
411
|
delete $pi->{ $l }; |
322
|
204
|
|
|
|
|
615
|
delete $m->[ $_ ][ $id ] for _count, _attr; |
323
|
204
|
|
|
|
|
346
|
my $path = delete $map_i->[ $id ]; |
324
|
204
|
100
|
|
|
|
443
|
_successors_del($f, $a, $map_s, $map_p, $id, $path) if $map_s; |
325
|
204
|
|
|
|
|
321
|
return 1; |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub get_paths_by_ids { |
329
|
6179
|
|
|
6179
|
1
|
15711
|
my ($i, undef, $list, $deep) = ( @{ $_[0] }[ _i ], @_ ); |
|
6179
|
|
|
|
|
15887
|
|
330
|
6179
|
100
|
|
|
|
102199
|
$deep ? map [ map [ @$i[ @$_ ] ], @$_ ], @$list : map [ @$i[ @$_ ] ], @$list; |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub paths { |
334
|
3526
|
50
|
|
3526
|
1
|
5077
|
grep defined, @{ $_[0]->[ _i ] || Graph::_empty_array() }; |
|
3526
|
|
|
|
|
23983
|
|
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
sub ids { |
338
|
302
|
50
|
|
302
|
1
|
498
|
values %{ $_[0]->[ _pi ] || Graph::_empty_array() }; |
|
302
|
|
|
|
|
2666
|
|
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub get_ids_by_paths { |
342
|
1230
|
|
|
1230
|
1
|
17133
|
my ($f, $a, $pi, $m, $list, $ensure, $deep) = ( @{ $_[0] }[ _f, _arity, _pi ], @_ ); |
|
1230
|
|
|
|
|
3200
|
|
343
|
1230
|
|
100
|
|
|
4535
|
$deep ||= 0; |
344
|
1230
|
|
|
|
|
3993
|
my ($is_multi, $is_ref, $is_unord) = (map $f & $_, _MULTI, _REF, _UNORD); |
345
|
|
|
|
|
|
|
return map { # Fast path |
346
|
1230
|
100
|
100
|
|
|
4697
|
my @ret = map { |
|
|
|
100
|
|
|
|
|
347
|
121
|
100
|
|
|
|
262
|
my $id = $pi->{ $a != 1 ? "@$_" : $_ }; |
|
154
|
100
|
|
|
|
365
|
|
348
|
154
|
100
|
|
|
|
448
|
defined $id ? $id : |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
349
|
|
|
|
|
|
|
!$ensure ? return : |
350
|
|
|
|
|
|
|
($is_multi ? $m->set_path_by_multi_id($_, _GEN_ID) : $m->set_paths($_))[0]; |
351
|
|
|
|
|
|
|
} $deep ? @$_ : $_; |
352
|
108
|
100
|
|
|
|
443
|
$deep ? \@ret : @ret; |
353
|
|
|
|
|
|
|
} @$list if $a and !$is_ref and $deep < 2; |
354
|
|
|
|
|
|
|
map { |
355
|
1106
|
|
|
|
|
1883
|
my @ret = map { |
356
|
1166
|
100
|
|
|
|
2311
|
my @ret2 = map { |
357
|
1277
|
100
|
|
|
|
2334
|
my $k = $_; |
|
1290
|
|
|
|
|
2129
|
|
358
|
1290
|
100
|
100
|
|
|
6070
|
$k = __strval($k, $f) if $a == 1 && $is_ref && ref($k); |
|
|
|
100
|
|
|
|
|
359
|
1290
|
100
|
100
|
|
|
4424
|
my $l = ($a == 0 && !$is_unord) ? join '|', map join(' ', sort @$_), @$k : $a == 1 ? "$k" : "@$k"; |
|
|
100
|
|
|
|
|
|
360
|
1290
|
|
|
|
|
2204
|
my $id = $pi->{ $l }; |
361
|
1290
|
50
|
|
|
|
4326
|
defined $id ? $id : |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
362
|
|
|
|
|
|
|
!$ensure ? return : |
363
|
|
|
|
|
|
|
($is_multi ? $m->set_path_by_multi_id($_, _GEN_ID) : $m->set_paths($_))[0]; |
364
|
|
|
|
|
|
|
} $deep > 1 ? @$_ : $_; |
365
|
1116
|
100
|
|
|
|
2766
|
$deep > 1 ? \@ret2 : @ret2; |
366
|
|
|
|
|
|
|
} $deep ? @$_ : $_; |
367
|
1005
|
100
|
|
|
|
3887
|
$deep ? \@ret : @ret; |
368
|
|
|
|
|
|
|
} @$list; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
sub _paths_fromto { |
372
|
46
|
|
|
46
|
|
85
|
my $offset = pop; |
373
|
46
|
|
|
|
|
75
|
my ($i, $map_x, @v) = ( @{ $_[0] }[ _i, $offset ], @_[1..$#_] ); |
|
46
|
|
|
|
|
163
|
|
374
|
46
|
50
|
|
|
|
230
|
Graph::__carp_confess("undefined vertex") if grep !defined, @v; |
375
|
46
|
|
|
|
|
260
|
require Set::Object; |
376
|
46
|
100
|
|
|
|
103
|
map $i->[ $_ ], Set::Object->new(map @$_, map values %{ $map_x->{ $_ } || _empty }, @v)->members; |
|
52
|
|
|
|
|
656
|
|
377
|
|
|
|
|
|
|
} |
378
|
31
|
|
|
31
|
1
|
7866
|
sub paths_from { push @_, _s; goto &_paths_fromto } |
|
31
|
|
|
|
|
111
|
|
379
|
15
|
|
|
15
|
1
|
3773
|
sub paths_to { push @_, _p; goto &_paths_fromto } |
|
15
|
|
|
|
|
52
|
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
sub _cessors { |
382
|
181
|
|
|
181
|
|
272
|
my $offset = pop; |
383
|
181
|
|
|
|
|
298
|
my ($map_x, @v) = ( @{ $_[0] }[ $offset ], @_[1..$#_] ); |
|
181
|
|
|
|
|
497
|
|
384
|
181
|
50
|
|
|
|
518
|
Graph::__carp_confess("undefined vertex") if grep !defined, @v; |
385
|
181
|
|
|
|
|
1379
|
require Set::Object; |
386
|
181
|
100
|
|
|
|
8443
|
Set::Object->new(map keys %{ $map_x->{ $_ } || _empty }, @v)->members; |
|
187
|
|
|
|
|
1539
|
|
387
|
|
|
|
|
|
|
} |
388
|
140
|
|
|
140
|
1
|
6226
|
sub successors { push @_, _s; goto &_cessors } |
|
140
|
|
|
|
|
349
|
|
389
|
41
|
|
|
41
|
1
|
4755
|
sub predecessors { push @_, _p; goto &_cessors } |
|
41
|
|
|
|
|
126
|
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
sub has_successor { |
392
|
72
|
|
|
72
|
1
|
8646
|
my ($map_s, $u, $v) = ( @{ $_[0] }[ _s ], @_[1, 2] ); |
|
72
|
|
|
|
|
229
|
|
393
|
72
|
50
|
|
|
|
281
|
Graph::__carp_confess("undefined vertex") if grep !defined, $u, $v; |
394
|
72
|
100
|
|
|
|
101
|
exists ${ $map_s->{ $u } || _empty }{ $v }; |
|
72
|
|
|
|
|
381
|
|
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
sub __strval { |
398
|
2151
|
|
|
2151
|
|
3688
|
my ($k, $f) = @_; |
399
|
2151
|
50
|
33
|
|
|
6380
|
return $k unless ref $k && ($f & _REF); |
400
|
2151
|
100
|
|
|
|
4067
|
return "$k" if ($f & _STR); |
401
|
2147
|
|
|
|
|
9726
|
require Scalar::Util; |
402
|
2147
|
|
|
|
|
5960
|
Scalar::Util::refaddr($k); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub __arg { |
406
|
2520
|
|
|
2520
|
|
3544
|
my ($f, $a, $m, $k) = (@{ $_[0] }[ _f, _arity ], @_[0, 1]); |
|
2520
|
|
|
|
|
6607
|
|
407
|
2520
|
50
|
66
|
|
|
7653
|
Graph::__carp_confess(sprintf "arguments %d (%s) expected %d for\n".$m->stringify, |
408
|
|
|
|
|
|
|
scalar @$k, "@$k", $a) |
409
|
|
|
|
|
|
|
if $a > 1 and @$k != $a; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
sub reindex { |
413
|
3
|
|
|
3
|
1
|
540
|
my ($f, $a, $i2p, $m) = (@{ $_[0] }[ _f, _arity, _i ], $_[0]); |
|
3
|
|
|
|
|
14
|
|
414
|
3
|
|
33
|
|
|
22
|
my $is_ref = $a == 1 && ($f & _REF); |
415
|
3
|
|
|
|
|
11
|
my $pi = $m->[ _pi ] = {}; |
416
|
3
|
|
|
|
|
7
|
for my $i ( 0..$#{ $i2p } ) { |
|
3
|
|
|
|
|
13
|
|
417
|
4
|
50
|
|
|
|
28
|
next if !defined(my $k = $i2p->[ $i ]); # deleted |
418
|
4
|
50
|
33
|
|
|
35
|
$k = __strval($k, $f) if $is_ref && ref($k); |
419
|
4
|
|
|
|
|
33
|
$pi->{ $k } = $i; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
1; |
424
|
|
|
|
|
|
|
__END__ |