line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright 2002 by Mats Kindahl. All rights reserved. |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
4
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Algorithm::Tree::NCA::Data; |
7
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
84678
|
use 5.006; |
|
3
|
|
|
|
|
12
|
|
|
3
|
|
|
|
|
403
|
|
9
|
3
|
|
|
3
|
|
18
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
112
|
|
10
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
132
|
|
11
|
|
|
|
|
|
|
|
12
|
3
|
|
|
3
|
|
2732
|
use fields qw(_run _magic _number _parent _leader _max _node); |
|
3
|
|
|
|
|
7843
|
|
|
3
|
|
|
|
|
30
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub new ($%) { |
15
|
572
|
|
|
572
|
|
646
|
my $class = shift; |
16
|
|
|
|
|
|
|
# Default values first, then the provided parameters |
17
|
572
|
|
|
|
|
2997
|
my %args = (_run => 0, # Corresponds to I(v) |
18
|
|
|
|
|
|
|
_magic => 0, # Corresponds to A_v |
19
|
|
|
|
|
|
|
_max => 0, # Maximum number assigned to subtree |
20
|
|
|
|
|
|
|
_number => 0, # The DFS number assigned to this node |
21
|
|
|
|
|
|
|
_parent => undef, # The parent node data for this node |
22
|
|
|
|
|
|
|
_leader => undef, # The leader node data for this node |
23
|
|
|
|
|
|
|
_node => undef, # The node that the data is for |
24
|
|
|
|
|
|
|
@_); |
25
|
|
|
|
|
|
|
|
26
|
572
|
|
|
|
|
1355
|
my $self = fields::new($class); |
27
|
572
|
|
|
|
|
39835
|
@$self{keys %args} = values %args; |
28
|
572
|
|
|
|
|
2165
|
return $self; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
package Algorithm::Tree::NCA; |
32
|
|
|
|
|
|
|
|
33
|
3
|
|
|
3
|
|
1000
|
use strict; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
94
|
|
34
|
3
|
|
|
3
|
|
84
|
use warnings; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
473
|
|
35
|
|
|
|
|
|
|
|
36
|
3
|
|
|
3
|
|
9200
|
use Data::Dumper; |
|
3
|
|
|
|
|
84077
|
|
|
3
|
|
|
|
|
704
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
require Exporter; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
43
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
44
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our @EXPORT_OK = (); |
47
|
|
|
|
|
|
|
our @EXPORT = (); |
48
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Preloaded methods go here. |
51
|
|
|
|
|
|
|
|
52
|
3
|
|
|
3
|
|
33
|
use fields qw(_get _set _data); |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
28
|
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub _set_method { |
55
|
572
|
|
|
572
|
|
624
|
my($node,$value) = @_; |
56
|
|
|
|
|
|
|
|
57
|
572
|
|
|
|
|
1684
|
$node->{'_nca_number'} = $value; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub _get_method { |
61
|
41237
|
|
|
41237
|
|
46732
|
my($node) = @_; |
62
|
|
|
|
|
|
|
|
63
|
41237
|
|
|
|
|
119099
|
return $node->{'_nca_number'}; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub new ($%) { |
68
|
9
|
|
|
9
|
0
|
16896
|
my($class,%o) = @_; |
69
|
|
|
|
|
|
|
|
70
|
9
|
50
|
|
|
|
89
|
$o{-get} = \&_get_method unless defined $o{-get}; |
71
|
9
|
50
|
|
|
|
84
|
$o{-set} = \&_set_method unless defined $o{-set}; |
72
|
|
|
|
|
|
|
|
73
|
9
|
|
|
|
|
49
|
my $self = fields::new($class); |
74
|
|
|
|
|
|
|
|
75
|
9
|
|
|
|
|
26099
|
$self->{_get} = $o{'-get'}; # Get method to use |
76
|
9
|
|
|
|
|
30
|
$self->{_set} = $o{'-set'}; # Set method to use |
77
|
9
|
|
|
|
|
25
|
$self->{_data} = []; # Array of node data |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Preprocess the tree if there is one supplied |
81
|
9
|
100
|
|
|
|
62
|
$self->preprocess($o{-tree}) if exists $o{-tree}; |
82
|
|
|
|
|
|
|
|
83
|
9
|
|
|
|
|
149
|
return $self; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _get ($$) { |
87
|
41237
|
|
|
41237
|
|
51698
|
my($self,$node) = @_; |
88
|
41237
|
|
|
|
|
77729
|
$self->{_get}->($node); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub _set ($$$) { |
92
|
572
|
|
|
572
|
|
716
|
my($self,$node,$val) = @_; |
93
|
572
|
|
|
|
|
1038
|
$self->{_set}->($node,$val); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub _lssb ($) { |
97
|
60900
|
|
|
60900
|
|
74035
|
my($v) = @_; |
98
|
60900
|
|
|
|
|
92426
|
return $v & -$v; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub _mssb ($) { |
102
|
58296
|
|
|
58296
|
|
73834
|
my($v) = @_; |
103
|
|
|
|
|
|
|
|
104
|
58296
|
|
|
|
|
70726
|
$v |= $v >> 1; |
105
|
58296
|
|
|
|
|
58248
|
$v |= $v >> 2; |
106
|
58296
|
|
|
|
|
60586
|
$v |= $v >> 4; |
107
|
58296
|
|
|
|
|
57649
|
$v |= $v >> 8; |
108
|
58296
|
|
|
|
|
64256
|
$v |= $v >> 16; |
109
|
|
|
|
|
|
|
|
110
|
58296
|
|
|
|
|
101554
|
return $v - ($v >> 1); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _data ($$) { |
114
|
41237
|
|
|
41237
|
|
56968
|
my($self,$node) = @_; |
115
|
41237
|
|
|
|
|
95329
|
return $self->{_data}->[$self->_get($node)]; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub preprocess ($$) { |
119
|
9
|
|
|
9
|
0
|
50
|
my($self,$root) = @_; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Enumeration phase |
122
|
9
|
|
|
|
|
41
|
$self->_enumerate($root, 1); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# Computing magic number and leaders |
125
|
9
|
|
|
|
|
39
|
$self->_compute_magic($root, $self->_data($root), 0); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# Enumerate each node of the tree with a number v and compute the run |
129
|
|
|
|
|
|
|
# I(v) for each node. Also set the parent for each node. |
130
|
|
|
|
|
|
|
sub _enumerate ($$$;$) { |
131
|
572
|
|
|
572
|
|
761
|
my($self,$node,$number,$parent) = @_; |
132
|
|
|
|
|
|
|
|
133
|
572
|
|
|
|
|
1328
|
my $data = Algorithm::Tree::NCA::Data |
134
|
|
|
|
|
|
|
->new(_node => $node, |
135
|
|
|
|
|
|
|
_run => $number, |
136
|
|
|
|
|
|
|
_parent => $parent, |
137
|
|
|
|
|
|
|
_number => $number); |
138
|
|
|
|
|
|
|
|
139
|
572
|
|
|
|
|
1178
|
$self->{_data}->[$number] = $data; |
140
|
|
|
|
|
|
|
|
141
|
572
|
|
|
|
|
1171
|
$self->_set($node,$number); |
142
|
|
|
|
|
|
|
|
143
|
572
|
|
|
|
|
1841
|
my $run = $number++; |
144
|
|
|
|
|
|
|
|
145
|
572
|
|
|
|
|
1484
|
for my $c ($node->children()) { |
146
|
563
|
|
|
|
|
2274
|
($number, $run) = $self->_enumerate($c, $number, $data); |
147
|
563
|
100
|
|
|
|
1054
|
if (_lssb($run) > _lssb($data->{_run})) { |
148
|
311
|
|
|
|
|
601
|
$data->{_run} = $run; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} |
151
|
572
|
|
|
|
|
2352
|
$data->{_max} = $number; |
152
|
572
|
|
|
|
|
1497
|
return ($number,$data->{_run}); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# Compute the magic number A_v and the leader L(v) for each node v. |
156
|
|
|
|
|
|
|
sub _compute_magic ($$$$) { |
157
|
572
|
|
|
572
|
|
730
|
my($self,$node,$ldata,$magic) = @_; |
158
|
|
|
|
|
|
|
|
159
|
572
|
|
|
|
|
948
|
my $ndata = $self->_data($node); |
160
|
|
|
|
|
|
|
|
161
|
572
|
|
|
|
|
1250
|
$ndata->{_magic} = $magic | _lssb($ndata->{_run}); |
162
|
|
|
|
|
|
|
|
163
|
572
|
100
|
|
|
|
1074
|
if ($ndata->{_run} != $ldata->{_run}) { |
164
|
322
|
|
|
|
|
411
|
$ndata->{_leader} = $ndata; |
165
|
|
|
|
|
|
|
} else { |
166
|
250
|
|
|
|
|
309
|
$ndata->{_leader} = $ldata; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
572
|
|
|
|
|
1213
|
foreach my $c ($node->children()) { |
170
|
563
|
|
|
|
|
3840
|
$self->_compute_magic($c, |
171
|
|
|
|
|
|
|
$ndata->{_leader}, |
172
|
|
|
|
|
|
|
$ndata->{_magic}); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _display_data ($) { |
177
|
0
|
|
|
0
|
|
0
|
my($self) = @_; |
178
|
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
0
|
my(@L,@I,@A); |
180
|
0
|
|
|
|
|
0
|
foreach my $d (@{$self->{_data}}) { |
|
0
|
|
|
|
|
0
|
|
181
|
0
|
0
|
|
|
|
0
|
push(@L, defined $d ? $d->{_leader}->{_number} : "*"); |
182
|
0
|
0
|
|
|
|
0
|
push(@I, defined $d ? $d->{_run} : "*"); |
183
|
0
|
0
|
|
|
|
0
|
push(@A, defined $d ? $d->{_magic} : "*"); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
0
|
print STDERR "L = (@L)\n"; |
187
|
0
|
|
|
|
|
0
|
print STDERR "I = (@I)\n"; |
188
|
0
|
|
|
|
|
0
|
print STDERR "A = (@A)\n"; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# Compute the nearest common ancestor of nodes I(x) and I(y) |
192
|
|
|
|
|
|
|
sub _bin_nca ($$$) { |
193
|
19734
|
|
|
19734
|
|
27547
|
my($self,$xd,$yd)= @_; |
194
|
|
|
|
|
|
|
|
195
|
19734
|
100
|
100
|
|
|
82650
|
if ($xd->{_number} <= $yd->{_number} && $yd->{_number} < $xd->{_max}) { |
196
|
36
|
|
|
|
|
89
|
return $xd->{_run}; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
19698
|
100
|
100
|
|
|
82696
|
if ($yd->{_number} <= $xd->{_number} && $xd->{_number} < $yd->{_max}) { |
200
|
36
|
|
|
|
|
1233
|
return $yd->{_run}; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
19662
|
|
|
|
|
48415
|
my $k = _mssb($xd->{_run} ^ $yd->{_run}); |
204
|
19662
|
|
|
|
|
30034
|
my $m = $k ^ ($k - 1); # Mask off the k-1 most significant bits |
205
|
19662
|
|
|
|
|
32673
|
my $r = ~$m & $xd->{_run}; # Take the k-1 most significant bits |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# Return k-1 least significant bits of I(x) with a 1 in position k |
208
|
19662
|
|
|
|
|
37354
|
return ($r | $k); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# Find the node closest to 'x' but on the same run as the NCA. |
213
|
|
|
|
|
|
|
sub _closest ($$$) { |
214
|
39468
|
|
|
39468
|
|
103563
|
my($self,$xd,$j) = @_; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# a. Find the position l of the right-most 1-bit in A_x |
217
|
39468
|
|
|
|
|
76841
|
my $l = _lssb($xd->{_magic}); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# b. If l == j then nx is x (since x and z are on the same run) |
220
|
39468
|
100
|
|
|
|
81760
|
if ($l == $j) { |
221
|
834
|
|
|
|
|
1507
|
return $xd; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# c. Find the position k of the left-most 1-bit in A_x that is to |
225
|
|
|
|
|
|
|
# the right of position j. |
226
|
38634
|
|
|
|
|
92991
|
my $k = _mssb(($j - 1) & $xd->{_magic}); |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Form the number u consisting of the bits of I(x) to the left |
229
|
|
|
|
|
|
|
# of position k, followed by a 1-bit in position k, followed by |
230
|
|
|
|
|
|
|
# all zeroes. (u will be I(w)) |
231
|
38634
|
|
|
|
|
71080
|
my $u = ~(($k - 1) | $k) & $xd->{_run} | $k; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Look up node L(I(w)), which must be node w. nx is then the parent |
234
|
|
|
|
|
|
|
# of node w. |
235
|
38634
|
|
|
|
|
74878
|
my $wd = $self->{_data}->[$u]->{_leader}; |
236
|
|
|
|
|
|
|
|
237
|
38634
|
|
|
|
|
87210
|
return $wd->{_parent}; |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub nca ($$$) { |
242
|
20028
|
|
|
20028
|
0
|
31673899
|
my($self,$x,$y) = @_; |
243
|
20028
|
|
|
|
|
43254
|
my $xd = $self->_data($x); |
244
|
20028
|
|
|
|
|
40527
|
my $yd = $self->_data($y); |
245
|
|
|
|
|
|
|
|
246
|
20028
|
100
|
|
|
|
69888
|
if ($xd->{_number} == $yd->{_number}) { |
247
|
294
|
|
|
|
|
742
|
return $x; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# 1. Find the [nearest] common ancestor b in B of nodes I(x) and I(y). |
251
|
19734
|
|
|
|
|
41592
|
my $b = $self->_bin_nca($xd,$yd); |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# 2. Find the smallest position j greater than or equal to h(b) such |
254
|
|
|
|
|
|
|
# that both numbers A_x and A_y have 1-bits in position j. j is |
255
|
|
|
|
|
|
|
# then h(I(z)). |
256
|
19734
|
|
|
|
|
28060
|
my $m = ~$b & ($b - 1); # Mask for the h(b)-1 least significant bits |
257
|
19734
|
|
|
|
|
37629
|
my $c = $xd->{_magic} & $yd->{_magic}; |
258
|
|
|
|
|
|
|
# The common set bits in A_x and A_y |
259
|
19734
|
|
|
|
|
22814
|
my $u = $c & ~$m; # The upper bits of the common set bits |
260
|
19734
|
|
|
|
|
34670
|
my $j = _lssb($u); # Isolate the rightmost 1-bit of u |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# 3a. Find node nx, the closest node to x on the same run as z. |
263
|
19734
|
|
|
|
|
40786
|
my $nxd = $self->_closest($xd,$j); |
264
|
|
|
|
|
|
|
# 3b. Find node ny, the closest node to y on the same run as z. |
265
|
19734
|
|
|
|
|
37089
|
my $nyd = $self->_closest($yd,$j); |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# 4. If nx < ny then z is nx, else z is ny |
268
|
19734
|
100
|
|
|
|
49718
|
if ($nxd->{_number} < $nyd->{_number}) { |
269
|
9764
|
|
|
|
|
29333
|
return $nxd->{_node}; |
270
|
|
|
|
|
|
|
} else { |
271
|
9970
|
|
|
|
|
32109
|
return $nyd->{_node}; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Autoload methods go after =cut, and are processed by the autosplit program. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
1; |
278
|
|
|
|
|
|
|
__END__ |