File Coverage

blib/lib/AI/Pathfinding/SMAstar/TreeOfQueues.pm
Criterion Covered Total %
statement 54 142 38.0
branch 10 36 27.7
condition 1 3 33.3
subroutine 9 20 45.0
pod 0 17 0.0
total 74 218 33.9


line stmt bran cond sub pod time code
1             #
2             # TreeOfQueues.pm
3             #
4             # An implementation of a binary tree of queues.
5             # This is a way to solve the problem of duplicate elements within
6             # a tree. We want to remove elements from the tree in time oldest-first
7             # order. In order to do this, a queue is located at each node in
8             # the tree. The queue contains objects with duplicate
9             # tree-keys.
10             #
11             # Author: matthias beebe
12             # Date : June 2008
13             #
14             #
15             package AI::Pathfinding::SMAstar::TreeOfQueues;
16 1     1   5 use strict;
  1         2  
  1         37  
17 1     1   6 use Tree::AVL;
  1         2  
  1         20  
18 1     1   578 use AI::Pathfinding::SMAstar::AVLQueue;
  1         3  
  1         2124  
19              
20              
21             ##################################################
22             # TreeOfQueues constructor
23             ##################################################
24             sub new {
25 6     6 0 8 my $invocant = shift;
26 6   33     24 my $class = ref($invocant) || $invocant;
27 6         34 my $self = {
28             f_avl_compare => undef,
29             f_obj_get_key => undef,
30             f_obj_get_data => undef,
31             _avl_tree => Tree::AVL->new(fcompare => \&AI::Pathfinding::SMAstar::AVLQueue::compare,
32             fget_key => \&AI::Pathfinding::SMAstar::AVLQueue::key,
33             fget_data => \&AI::Pathfinding::SMAstar::AVLQueue::key),
34             @_, # attribute override
35             };
36              
37 6         164 return bless $self, $class;
38             }
39              
40              
41             sub insert{
42 16     16 0 19 my ($self, $obj) = @_;
43              
44             # check to see if there is a Queue in the tree with the key of obj.
45             # if not, create one and insert
46 16         24 my $fget_key = $self->{f_obj_get_key};
47 16         21 my $avl_compare = $self->{f_avl_compare};
48 16         36 my $key = $obj->$fget_key();
49 16         57 my $queue = AI::Pathfinding::SMAstar::AVLQueue->new(_key => $key);
50              
51 16         47 my $found_queue = $self->{_avl_tree}->lookup_obj($queue);
52              
53 16 100       98 if(!$found_queue){
54 15         39 $self->{_avl_tree}->insert($queue); # insert queue, with no duplicates
55 15         281 $queue->insert($obj); # insert object onto new queue
56             }
57             else { # found a queue here. insert obj
58 1         5 $found_queue->insert($obj);
59             }
60             }
61              
62              
63             sub remove{
64 4     4 0 5 my ($self, $obj, $cmp_func) = @_;
65              
66             # check to see if there is a Queue in the tree with the key of obj.
67             # if not, create one and insert
68 4         5 my $fget_key = $self->{f_obj_get_key};
69 4         5 my $avl_compare = $self->{f_avl_compare};
70 4         10 my $key = $obj->$fget_key();
71 4         14 my $queue = AI::Pathfinding::SMAstar::AVLQueue->new(_key => $key);
72 4         9 my $avltree = \$self->{_avl_tree};
73 4         13 my $found_queue = $self->{_avl_tree}->lookup_obj($queue);
74              
75              
76              
77 4 50       21 if(!$found_queue){
78             # print "TreeOfQueues::remove: did not find queue with key $key\n";
79             # $self->{_avl_tree}->print();
80             }
81             else { # found a queue here. remove obj
82             #print "TreeOfQueues::remove: found queue, removing obj using $cmp_func\n";
83 4         12 $found_queue->remove($obj, $cmp_func);
84 4 50       9 if($found_queue->is_empty()){
85             #print "TreeOfQueues::remove: found queue is now empty, removing queue from tree\n";
86 4         11 $$avltree->remove($found_queue);
87             }
88             }
89             }
90              
91             sub largest_oldest{
92 6     6 0 7 my ($self) = @_;
93 6         13 my $avltree = \$self->{_avl_tree};
94              
95             # $$avltree->print("-");
96              
97             # get the avl tree with the largest key
98 6         16 my $queue = $$avltree->largest();
99 6 50       124 if($queue){
100 6         14 my $key = $queue->key();
101 6         19 my $obj = $queue->top();
102 6         14 return $obj;
103             }
104             else{
105 0         0 return;
106             }
107             }
108              
109              
110             sub pop_largest_oldest{
111 5     5 0 7 my ($self) = @_;
112 5         6 my $avltree = \$self->{_avl_tree};
113            
114             # $$avltree->print("*");
115            
116             # get the avl tree with the largest key
117 5         14 my $queue = $$avltree->largest();
118 5 50       81 if($queue){
119 5         15 my $key = $queue->key();
120 5         16 my $obj = $queue->pop_top();
121            
122 5 100       25 if($queue->is_empty()){
123 4         9 $$avltree->remove($queue);
124             }
125 5         92 return $obj;
126             }
127             else{
128 0         0 return;
129             }
130             }
131              
132             sub smallest_oldest{
133 0     0 0 0 my ($self) = @_;
134 0         0 my $avltree = \$self->{_avl_tree};
135              
136             # $$avltree->print("-");
137              
138             # get the avl tree with the largest key
139 0         0 my $queue = $$avltree->smallest();
140 0 0       0 if($queue){
141 0         0 my $key = $queue->key();
142 0         0 my $obj = $queue->top();
143 0         0 return $obj;
144             }
145             else{
146 0         0 return;
147             }
148             }
149              
150              
151             sub pop_smallest_oldest{
152 0     0 0 0 my ($self) = @_;
153 0         0 my $avltree = \$self->{_avl_tree};
154            
155             # $$avltree->print("*");
156            
157             # get the avl tree with the largest key
158 0         0 my $queue = $$avltree->smallest();
159 0 0       0 if($queue){
160 0         0 my $key = $queue->key();
161 0         0 my $obj = $queue->pop_top();
162            
163 0 0       0 if($queue->is_empty()){
164 0         0 $$avltree->remove($queue);
165             }
166 0         0 return $obj;
167             }
168             else{
169 0         0 return;
170             }
171             }
172              
173              
174             sub pop_oldest_at{
175 0     0 0 0 my ($self, $key) = @_;
176 0         0 my $avltree = \$self->{_avl_tree};
177            
178 0         0 my $queue_to_find = AI::Pathfinding::SMAstar::AVLQueue->new(_key => $key);
179              
180 0         0 my $queue = $$avltree->lookup_obj($queue_to_find);
181              
182 0 0       0 if($queue){
183             # print "TreeOfQueues::pop_oldest_at: found queue with key: $key\n";
184 0         0 my $obj = $queue->pop_top();
185 0 0       0 if($queue->is_empty()){
186 0         0 $$avltree->remove($queue);
187             }
188 0         0 return $obj;
189             }
190             else{
191             # print "TreeOfQueues::pop_oldest_at: did not find queue with key: $key\n";
192 0         0 return;
193             }
194             }
195              
196              
197              
198              
199             sub oldest_at{
200 0     0 0 0 my ($self, $key) = @_;
201 0         0 my $avltree = \$self->{_avl_tree};
202            
203 0         0 my $queue_to_find = AI::Pathfinding::SMAstar::AVLQueue->new(_key => $key);
204              
205 0         0 my $queue = $$avltree->lookup_obj($queue_to_find);
206              
207 0 0       0 if($queue){
208             # print "TreeOfQueues::oldest_at: found queue with key: $key\n";
209 0         0 my $obj = $queue->top();
210 0         0 return $obj;
211             }
212             else{
213             # print "TreeOfQueues::oldest_at: did not find queue with key: $key\n";
214 0         0 return;
215             }
216             }
217              
218              
219             sub largest{
220 0     0 0 0 my ($self) = @_;
221 0         0 my $avltree = \$self->{_avl_tree};
222            
223 0         0 return $$avltree->largest();
224             }
225              
226              
227              
228              
229              
230             sub get_queue{
231 0     0 0 0 my ($self, $key) = @_;
232 0         0 my $avltree = \$self->{_avl_tree};
233            
234 0         0 my $queue_to_find = AI::Pathfinding::SMAstar::AVLQueue->new(_key => $key);
235              
236 0         0 my $queue = $$avltree->lookup_obj($queue_to_find);
237              
238 0 0       0 if($queue){
239             # print "TreeOfQueues::get_queue: found queue with key: $key\n";
240 0         0 return $queue;
241             }
242             else{
243             # print "TreeOfQueues::get_queue: did not find queue with key: $key\n";
244 0         0 return;
245             }
246             }
247              
248              
249              
250              
251              
252             sub get_keys_iterator
253             {
254 0     0 0 0 my ($self) = @_;
255 0         0 my $avltree = \$self->{_avl_tree};
256 0         0 return $$avltree->get_keys_iterator();
257             }
258              
259              
260             sub get_keys
261             {
262 0     0 0 0 my ($self) = @_;
263 0         0 my $avltree = \$self->{_avl_tree};
264            
265 0         0 return $$avltree->get_keys();
266             }
267              
268              
269             sub print{
270 0     0 0 0 my ($self) = @_;
271              
272 0 0       0 if($self->{_avl_tree}->is_empty()){
273 0         0 print "tree is empty\n";
274             }
275              
276 0         0 my $get_key_func = $self->{f_obj_get_key};
277 0         0 my $get_data_func = $self->{f_obj_get_data};
278              
279 0         0 my @queue_list = $self->{_avl_tree}->get_list();
280              
281 0         0 foreach my $queue (@queue_list){
282             #print "queue is $queue\n";
283              
284 0         0 my $queue_key = $queue->key();
285             #print "queue key: $queue_key\n";
286            
287 0         0 my @objlist = $queue->get_list();
288              
289 0 0       0 if(!@objlist){
290 0         0 print "queue at key $queue_key is empty\n";
291             }
292              
293 0         0 print "queue at key $queue_key:\n";
294 0         0 foreach my $obj (@objlist){
295 0         0 my $key = $obj->$get_key_func;
296 0         0 my $word = $obj->$get_data_func;
297            
298 0         0 print " key: $key, data: $word\n";
299             }
300             }
301             }
302              
303              
304              
305             sub is_empty{
306 9     9 0 12 my ($self) = @_;
307 9 100       19 if($self->{_avl_tree}->is_empty()){
308 4         36 return 1;
309             }
310 5         45 return 0;
311             }
312              
313              
314              
315             sub get_size{
316 0     0 0   my ($self) = @_;
317            
318 0           my $size = 0;
319            
320 0 0         if($self->{_avl_tree}->is_empty()){
321 0           return $size;
322             }
323            
324 0           my @queue_list = $self->{_avl_tree}->get_list();
325            
326 0           foreach my $queue (@queue_list){
327 0           $size = $size + $queue->get_size();
328             }
329 0           return $size;
330             }
331              
332             sub get_list{
333 0     0 0   my ($self) = @_;
334              
335 0           my @objs;
336              
337 0 0         if($self->{_avl_tree}->is_empty()){
338 0           return;
339             }
340              
341             #$self->{_avl_tree}->print(">>>");
342              
343 0           my @queue_list = $self->{_avl_tree}->get_list();
344              
345 0           foreach my $queue (@queue_list){
346 0           my $queue_key = $queue->key();
347              
348              
349 0           my @objlist = $queue->get_list();
350              
351             #print "get_list: size of queue at key: $queue_key is: " . @objlist . "\n";
352              
353 0           push(@objs, @objlist);
354             }
355 0           return @objs;
356             }
357              
358              
359              
360              
361             1;