annotate variant_effect_predictor/Bio/Coordinate/Graph.pm @ 1:d6778b5d8382 draft default tip

Deleted selected files
author willmclaren
date Fri, 03 Aug 2012 10:05:43 -0400
parents 21066c0abaf5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
1 # $Id: Graph.pm,v 1.2.2.2 2003/09/08 12:16:18 heikki Exp $
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
2 #
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
3 # bioperl module for Bio::Coordinate::Graph
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
4 #
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
5 # Cared for by Heikki Lehvaslaiho <heikki@ebi.ac.uk>
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
6 #
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
7 # Copyright Heikki Lehvaslaiho
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
8 #
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
9 # You may distribute this module under the same terms as perl itself
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
10
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
11 # POD documentation - main docs before the code
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
12
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
13 =head1 NAME
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
14
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
15 Bio::Coordinate::Graph - Finds shortest path between nodes in a graph
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
16
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
17 =head1 SYNOPSIS
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
18
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
19 # get a hash of hashes representing the graph. E.g.:
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
20 my $hash= {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
21 '1' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
22 '2' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
23 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
24 '2' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
25 '4' => 1,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
26 '3' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
27 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
28 '3' => undef,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
29 '4' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
30 '5' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
31 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
32 '5' => undef
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
33 };
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
34
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
35 # create the object;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
36 my $graph = Bio::Coordinate::Graph->new(-graph => $hash);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
37
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
38 # find the shortest path between two nodes
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
39 my $a = 1;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
40 my $b = 6;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
41 my @path = $graph->shortest_paths($a);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
42 print join (", ", @path), "\n";
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
43
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
44
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
45 =head1 DESCRIPTION
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
46
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
47 This class calculates the shortest path between input and output
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
48 coordinate systems in a graph that defines the relationships between
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
49 them. This class is primarely designed to analyze gene-related
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
50 coordinate systems. See L<Bio::Coordinate::GeneMapper>.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
51
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
52 Note that this module can not be used to manage graphs.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
53
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
54 Technically the graph implemented here is known as Directed Acyclic
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
55 Graph (DAG). DAG is composed of vertices (nodes) and edges (with
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
56 optional weights) linking them. Nodes of the graph are the coordinate
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
57 systems in gene mapper.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
58
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
59 The shortest path is found using the Dijkstra's algorithm. This
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
60 algorithm is fast and greedy and requires all weights to be
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
61 positive. All weights in the gene coordinate system graph are
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
62 currently equal (1) making the graph unweighted. That makes the use of
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
63 Dijkstra's algorithm an overkill. A impler and faster breadth-first
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
64 would be enough. Luckily the difference for small graphs is not
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
65 signigicant and the implementation is capable to take weights into
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
66 account if needed at some later time.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
67
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
68 =head2 Input format
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
69
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
70 The graph needs to be primed using a hash of hashes where there is a
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
71 key for each node. The second keys are the names of the downstream
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
72 neighboring nodes and values are the weights for reaching them. Here
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
73 is part of the gene coordiante system graph::
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
74
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
75
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
76 $hash = {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
77 '6' => undef,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
78 '3' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
79 '6' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
80 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
81 '2' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
82 '6' => 1,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
83 '4' => 1,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
84 '3' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
85 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
86 '1' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
87 '2' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
88 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
89 '4' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
90 '5' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
91 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
92 '5' => undef
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
93 };
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
94
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
95
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
96 Note that the names need to be positive integrers. Root should be '1'
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
97 and directness of the graph is taken advantage of to speed
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
98 calculations by assuming that downsream nodes always have larger
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
99 number as name.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
100
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
101 An alternative (shorter) way of describing input is to use hash of
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
102 arrays. See L<Bio::Coordinate::Graph::hash_of_arrays>.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
103
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
104
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
105 =head1 FEEDBACK
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
106
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
107 =head2 Mailing Lists
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
108
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
109 User feedback is an integral part of the evolution of this and other
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
110 Bioperl modules. Send your comments and suggestions preferably to the
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
111 Bioperl mailing lists Your participation is much appreciated.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
112
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
113 bioperl-l@bioperl.org - General discussion
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
114 http://bio.perl.org/MailList.html - About the mailing lists
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
115
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
116 =head2 Reporting Bugs
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
117
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
118 report bugs to the Bioperl bug tracking system to help us keep track
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
119 the bugs and their resolution. Bug reports can be submitted via
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
120 email or the web:
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
121
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
122 bioperl-bugs@bio.perl.org
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
123 http://bugzilla.bioperl.org/
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
124
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
125 =head1 AUTHOR - Heikki Lehvaslaiho
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
126
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
127 Email: heikki@ebi.ac.uk
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
128 Address:
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
129
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
130 EMBL Outstation, European Bioinformatics Institute
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
131 Wellcome Trust Genome Campus, Hinxton
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
132 Cambs. CB10 1SD, United Kingdom
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
133
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
134 =head1 APPENDIX
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
135
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
136 The rest of the documentation details each of the object
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
137 methods. Internal methods are usually preceded with a _
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
138
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
139 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
140
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
141
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
142 # Let the code begin...
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
143
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
144 package Bio::Coordinate::Graph;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
145 use vars qw(@ISA );
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
146 use strict;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
147
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
148 # Object preamble - inherits from Bio::Root::Root
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
149 use Bio::Root::Root;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
150
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
151 @ISA = qw(Bio::Root::Root);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
152
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
153
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
154 sub new {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
155 my($class,@args) = @_;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
156 my $self = $class->SUPER::new(@args);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
157
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
158 my($graph, $hasharray) =
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
159 $self->_rearrange([qw(
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
160 GRAPH
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
161 HASHARRAY
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
162 )],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
163 @args);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
164
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
165 $graph && $self->graph($graph);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
166 $hasharray && $self->hasharray($hasharray);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
167
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
168 $self->{'_root'} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
169
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
170 return $self; # success - we hope!
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
171
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
172 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
173
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
174 =head2 Graph structure input methods
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
175
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
176 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
177
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
178 =head2 graph
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
179
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
180 Title : graph
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
181 Usage : $obj->graph($my_graph)
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
182 Function: Read/write method for the graph structure
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
183 Example :
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
184 Returns : hash of hashes grah structure
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
185 Args : reference to a hash of hashes
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
186
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
187 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
188
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
189 sub graph {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
190
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
191 my ($self,$value) = @_;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
192
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
193 if ($value) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
194 $self->throw("Need a hash of hashes")
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
195 unless ref($value) eq 'HASH' ;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
196 $self->{'_dag'} = $value;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
197
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
198 # empty the cache
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
199 $self->{'_root'} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
200
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
201 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
202
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
203 return $self->{'_dag'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
204
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
205 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
206
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
207
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
208 =head2 hash_of_arrays
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
209
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
210 Title : hash_of_arrays
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
211 Usage : $obj->hash_of_array(%hasharray)
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
212 Function: An alternative method to read in the graph structure.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
213 Hash arrays are easier to type. This method converts
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
214 arrays into hashes and assigns equal values "1" to
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
215 weights.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
216
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
217 Example : Here is an example of simple structure containing a graph.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
218
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
219 my $DAG = {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
220 6 => [],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
221 5 => [],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
222 4 => [5],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
223 3 => [6],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
224 2 => [3, 4, 6],
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
225 1 => [2]
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
226 };
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
227
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
228 Returns : hash of hashes graph structure
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
229 Args : reference to a hash of arrays
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
230
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
231 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
232
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
233 sub hash_of_arrays {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
234
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
235 my ($self,$value) = @_;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
236
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
237 # empty the cache
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
238 $self->{'_root'} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
239
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
240 if ($value) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
241
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
242 $self->throw("Need a hash of hashes")
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
243 unless ref($value) eq 'HASH' ;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
244
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
245 #copy the hash of arrays into a hash of hashes;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
246 my %hash;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
247 foreach my $start ( keys %{$value}){
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
248 $hash{$start} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
249 map { $hash{$start}{$_} = 1 } @{$value->{$start}};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
250 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
251
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
252 $self->{'_dag'} = \%hash;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
253 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
254
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
255 return $self->{'_dag'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
256
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
257 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
258
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
259 =head2 Methods for determining the shortest path in the graph
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
260
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
261 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
262
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
263 =head2 shortest_path
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
264
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
265 Title : shortest_path
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
266 Usage : $obj->shortest_path($a, $b);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
267 Function: Method for retrieving the shortest path between nodes.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
268 If the start node remains the same, the method is sometimes
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
269 able to use cached results, otherwise it will recalculate
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
270 the paths.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
271 Example :
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
272 Returns : array of node names, only the start node name if no path
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
273 Args : name of the start node
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
274 : name of the end node
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
275
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
276 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
277
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
278
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
279 sub shortest_path {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
280 my ($self, $root, $end) = @_;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
281
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
282 $self->throw("Two arguments needed") unless @_ == 3;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
283 $self->throw("No node name [$root]")
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
284 unless exists $self->{'_dag'}->{$root};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
285 $self->throw("No node name [$end]")
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
286 unless exists $self->{'_dag'}->{$end};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
287
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
288 my @res; # results
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
289 my $reverse;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
290
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
291 if ($root > $end) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
292 ($root, $end) = ($end, $root );
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
293 $reverse++;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
294 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
295
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
296 # try to use cached paths
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
297 $self->dijkstra($root) unless
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
298 defined $self->{'_root'} and $self->{'_root'} eq $root;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
299
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
300 return @res unless $self->{'_paths'} ;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
301
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
302 # create the list
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
303 my $node = $end;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
304 my $prev = $self->{'_paths'}->{$end}{'prev'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
305 while ($prev) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
306 unshift @res, $node;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
307 $node = $self->{'_paths'}->{$node}{'prev'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
308 $prev = $self->{'_paths'}->{$node}{'prev'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
309 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
310 unshift @res, $node;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
311
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
312 $reverse ? return reverse @res : return @res;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
313 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
314
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
315
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
316 =head2 dijkstra
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
317
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
318 Title : dijkstra
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
319 Usage : $graph->dijkstra(1);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
320 Function: Implements Dijkstra's algorithm.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
321 Returns or sets a list of mappers. The returned path
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
322 description is always directed down from the root.
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
323 Called from shortest_path().
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
324 Example :
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
325 Returns : Reference to a hash of hashes representing a linked list
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
326 which contains shortest path down to all nodes from the start
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
327 node. E.g.:
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
328
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
329 $res = {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
330 '2' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
331 'prev' => '1',
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
332 'dist' => 1
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
333 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
334 '1' => {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
335 'prev' => undef,
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
336 'dist' => 0
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
337 },
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
338 };
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
339
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
340 Args : name of the start node
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
341
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
342 =cut
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
343
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
344 sub dijkstra {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
345 my ($self,$root) = @_;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
346
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
347 $self->throw("I need the name of the root node input") unless $root;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
348 $self->throw("No node name [$root]")
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
349 unless exists $self->{'_dag'}->{$root};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
350
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
351 my %est = (); # estimate hash
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
352 my %res = (); # result hash
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
353 my $nodes = keys %{$self->{'_dag'}};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
354 my $maxdist = 1000000;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
355
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
356 # cache the root value
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
357 $self->{'_root'} = $root;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
358
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
359 foreach my $node ( keys %{$self->{'_dag'}} ){
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
360 if ($node eq $root) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
361 $est{$node}{'prev'} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
362 $est{$node}{'dist'} = 0;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
363 } else {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
364 $est{$node}{'prev'} = undef;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
365 $est{$node}{'dist'} = $maxdist;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
366 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
367 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
368
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
369 # remove nodes from %est until it is empty
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
370 while (keys %est) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
371
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
372 #select the node closest to current one, or root node
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
373 my $min_node;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
374 my $min = $maxdist;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
375 foreach my $node (reverse sort keys %est) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
376 if ( $est{$node}{'dist'} < $min ) {
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
377 $min = $est{$node}{'dist'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
378 $min_node = $node;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
379 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
380 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
381
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
382 # no more links between nodes
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
383 last unless ($min_node);
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
384
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
385 # move the node from %est into %res;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
386 $res{$min_node} = delete $est{$min_node};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
387
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
388 # recompute distances to the neighbours
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
389 my $dist = $res{$min_node}{'dist'};
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
390 foreach my $neighbour ( keys %{$self->{'_dag'}->{$min_node}} ){
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
391 next unless $est{$neighbour}; # might not be there any more
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
392 $est{$neighbour}{'prev'} = $min_node;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
393 $est{$neighbour}{'dist'} =
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
394 $dist + $self->{'_dag'}{$min_node}{$neighbour}
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
395 if $est{$neighbour}{'dist'} > $dist + 1 ;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
396 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
397 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
398 return $self->{'_paths'} = \%res;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
399 }
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
400
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
401
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
402 1;
21066c0abaf5 Uploaded
willmclaren
parents:
diff changeset
403