| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Algorithm::TravelingSalesman::BitonicTour; |
|
2
|
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
89427
|
use strict; |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
351
|
|
|
4
|
9
|
|
|
9
|
|
46
|
use warnings FATAL => 'all'; |
|
|
9
|
|
|
|
|
19
|
|
|
|
9
|
|
|
|
|
407
|
|
|
5
|
9
|
|
|
9
|
|
61
|
use base 'Class::Accessor::Fast'; |
|
|
9
|
|
|
|
|
15
|
|
|
|
9
|
|
|
|
|
11463
|
|
|
6
|
9
|
|
|
9
|
|
36231
|
use Carp 'croak'; |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
704
|
|
|
7
|
9
|
|
|
9
|
|
555
|
use List::Util 'reduce'; |
|
|
9
|
|
|
|
|
22
|
|
|
|
9
|
|
|
|
|
1218
|
|
|
8
|
9
|
|
|
9
|
|
10508
|
use Params::Validate qw/ validate_pos SCALAR /; |
|
|
9
|
|
|
|
|
107525
|
|
|
|
9
|
|
|
|
|
930
|
|
|
9
|
9
|
|
|
9
|
|
8420
|
use Regexp::Common; |
|
|
9
|
|
|
|
|
42879
|
|
|
|
9
|
|
|
|
|
50
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.05'; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw/ _points _sorted_points _tour /); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 NAME |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Algorithm::TravelingSalesman::BitonicTour - solve the euclidean traveling-salesman problem with bitonic tours |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
use Algorithm::TravelingSalesman::BitonicTour; |
|
22
|
|
|
|
|
|
|
my $bt = Algorithm::TravelingSalesman::BitonicTour->new; |
|
23
|
|
|
|
|
|
|
$bt->add_point($x1,$y1); |
|
24
|
|
|
|
|
|
|
$bt->add_point($x2,$y2); |
|
25
|
|
|
|
|
|
|
$bt->add_point($x3,$y3); |
|
26
|
|
|
|
|
|
|
# ...add other points as needed... |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# get and print the solution |
|
29
|
|
|
|
|
|
|
my ($len, @coords) = $bt->solve; |
|
30
|
|
|
|
|
|
|
print "optimal path length: $len\n"; |
|
31
|
|
|
|
|
|
|
print "coordinates of optimal path:\n"; |
|
32
|
|
|
|
|
|
|
print " ($_->[0], $_->[1])\n" for @coords; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 THE PROBLEM |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
From I, 2nd ed., T. H. Cormen, C. E. Leiserson, R. |
|
37
|
|
|
|
|
|
|
Rivest, and C. Stein, MIT Press, 2001, problem 15-1, p. 364: |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=over 4 |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
The B is the problem of determining the |
|
42
|
|
|
|
|
|
|
shortest closed tour that connects a given set of I points in the plane. |
|
43
|
|
|
|
|
|
|
Figure 15.9(a) shows the solution to a 7-point problem. The general problem is |
|
44
|
|
|
|
|
|
|
NP-complete, and its solution is therefore believed to require more than |
|
45
|
|
|
|
|
|
|
polynomial time (see Chapter 34). |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
J. L. Bentley has suggested that we simplify the problem by restricting our |
|
48
|
|
|
|
|
|
|
attention to B, that is, tours that start at the leftmost point, |
|
49
|
|
|
|
|
|
|
go strictly left to right to the rightmost point, and then go strictly right to |
|
50
|
|
|
|
|
|
|
left back to the starting point. Figure 15.9(b) shows the shortest bitonic |
|
51
|
|
|
|
|
|
|
tour of the same 7 points. In this case, a polynomial-time algorithm is |
|
52
|
|
|
|
|
|
|
possible. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Describe an I(n^2)-time algorithm for determining an optimal bitonic tour. |
|
55
|
|
|
|
|
|
|
You may assume that no two points have the same I-coordinate. (I |
|
56
|
|
|
|
|
|
|
Scan left to right, maintaining optimal possibilities for the two parts of the |
|
57
|
|
|
|
|
|
|
tour.) |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=back |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
From Wikipedia (L): |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=over 4 |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
In computational geometry, a B of a set of point sites in the |
|
66
|
|
|
|
|
|
|
Euclidean plane is a closed polygonal chain that has each site as one of its |
|
67
|
|
|
|
|
|
|
vertices, such that any vertical line crosses the chain at most twice. |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=back |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 THE SOLUTION |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head2 Conventions |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
Points are numbered from left to right, starting with "0", then "1", and so on. |
|
76
|
|
|
|
|
|
|
For convenience I call the rightmost point C. |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 Key Insights Into the Problem |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=over 4 |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=item 1. Focus on optimal B bitonic tours. |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
B have endpoints (i,j) where C<< i < j < R >>, and |
|
85
|
|
|
|
|
|
|
they are the building blocks of the optimal closed bitonic tour we're trying to |
|
86
|
|
|
|
|
|
|
find. |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
An open bitonic tour, optimal or not, has these properties: |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
* it's bitonic (a vertical line crosses the tour at most twice) |
|
91
|
|
|
|
|
|
|
* it's open (it has endpoints), which we call "i" and "j" (i < j) |
|
92
|
|
|
|
|
|
|
* all points to the left of "j" are visited by the tour |
|
93
|
|
|
|
|
|
|
* points i and j are endpoints (connected to exactly one edge) |
|
94
|
|
|
|
|
|
|
* all other points in the tour are connected to two edges |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
For a given set of points there may be many open bitonic tours with endpoints |
|
97
|
|
|
|
|
|
|
(i,j), but we are only interested in the I open tour--the tour with |
|
98
|
|
|
|
|
|
|
the shortest length. Let's call this tour B>. |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=item 2. Grok the (slightly) messy recurrence relation. |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
A concrete example helps clarify this. Assume we know the optimal tour lengths |
|
103
|
|
|
|
|
|
|
for all (i,j) to the right of point C<5>: |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
T(0,1) |
|
106
|
|
|
|
|
|
|
T(0,2) T(1,2) |
|
107
|
|
|
|
|
|
|
T(0,3) T(1,3) T(2,3) |
|
108
|
|
|
|
|
|
|
T(0,4) T(1,4) T(2,4) T(3,4) |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
From this information, we can find C, C, ... C. |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=over 4 |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item B> |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
From our definition, C must have endpoints C<0> and C<5>, and must also |
|
117
|
|
|
|
|
|
|
include all intermediate points C<1>-C<4>. This means C is composed of |
|
118
|
|
|
|
|
|
|
points C<0> through C<5> in order. This is also the union of C and the |
|
119
|
|
|
|
|
|
|
line segment C<4>-C<5>. |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=item B> |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
C has endpoints at C<1> and C<5>, and visits all points to the left of |
|
124
|
|
|
|
|
|
|
C<5>. To preserve the bitonicity of C, the only possibility for the |
|
125
|
|
|
|
|
|
|
tour is the union of C and line segment C<4>-C<5>. I have included a |
|
126
|
|
|
|
|
|
|
short proof by contradiction of this in the source code. |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=begin comment |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Proof by contradiction: |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
1. Assume the following: |
|
133
|
|
|
|
|
|
|
* T(1,5) is an optimal open bitonic tour having endpoints 1 and 5. |
|
134
|
|
|
|
|
|
|
* Points 4 and 5 are not adjacent in the tour, i.e. the final segment in |
|
135
|
|
|
|
|
|
|
the tour joins points "P" and 5, where "P" is to the left of point 4. |
|
136
|
|
|
|
|
|
|
2. Since T(1,5) is an optimal open bitonic tour, point 4 is included in the |
|
137
|
|
|
|
|
|
|
middle of the tour, not at an endpoint, and is connected to two edges. |
|
138
|
|
|
|
|
|
|
3. Since 4 is not connected to 5, both its edges connect to points to its |
|
139
|
|
|
|
|
|
|
left. |
|
140
|
|
|
|
|
|
|
4. Combined with the segment from 5 to P, a vertical line immediately to the |
|
141
|
|
|
|
|
|
|
left of point 4 must cross at least three line segments, thus our proposed |
|
142
|
|
|
|
|
|
|
T(1,5) is not bitonic. |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Thus points 4 and 5 must be adjacent in tour T(1,5), so the tour must be the |
|
145
|
|
|
|
|
|
|
optimal tour from 1 to 4 (more convenently called "T(1,4)"), plus the segment |
|
146
|
|
|
|
|
|
|
from 4 to 5. |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=end comment |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item B> |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Our logic for finding C applies to these cases as well. |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item B> |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Tour C breaks the pattern seen in C through C, because |
|
157
|
|
|
|
|
|
|
the leftmost point (point 4) must be an endpoint in the tour. Via proof by |
|
158
|
|
|
|
|
|
|
contradiction similar to the above, our choices for constructing C are: |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
T(0,4) + line segment from 0 to 5 |
|
161
|
|
|
|
|
|
|
T(1,4) + line segment from 1 to 5 |
|
162
|
|
|
|
|
|
|
T(2,4) + line segment from 2 to 5 |
|
163
|
|
|
|
|
|
|
T(3,4) + line segment from 3 to 5 |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
All of them meet our bitonicity requirements, so we choose the shortest of |
|
166
|
|
|
|
|
|
|
these for C. |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=back |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
To summarize the recurrence, and using function C to calculate the |
|
171
|
|
|
|
|
|
|
distance between points: |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=over 5 |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item if i < j-1: |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
C<< T(i,j) = T(i,j-1) + delta(j-1,j) >> |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item if i == j-1: |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
C<< T(i,j) = min{ T(k,i) + delta(k,j) } >>, for all k < i |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=back |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=item 3. The base case. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
The open tour C has to be the line segment from 0 to 1. |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=back |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head2 Dynamic Programming |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
This problem exhibits the classic features suggesting a dynamic programming |
|
194
|
|
|
|
|
|
|
solution: I and I. |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head3 Overlapping Subproblems |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
The construction of tour C depends on knowledge of tours to the left of |
|
199
|
|
|
|
|
|
|
C: |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
to construct: one must know: |
|
202
|
|
|
|
|
|
|
------------- -------------- |
|
203
|
|
|
|
|
|
|
T(0,5) T(0,4) |
|
204
|
|
|
|
|
|
|
T(1,5) T(1,4) |
|
205
|
|
|
|
|
|
|
T(2,5) T(2,4) |
|
206
|
|
|
|
|
|
|
T(3,5) T(3,4) |
|
207
|
|
|
|
|
|
|
T(4,5) T(0,4), T(1,4), T(2,4), T(3,4) |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
We also see that a given optimal tour is used I in constructing |
|
210
|
|
|
|
|
|
|
longer tours. For example, C is used in the construction of both |
|
211
|
|
|
|
|
|
|
C and C. |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head3 Optimal Substructure |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
As shown in the above analysis, constructing a given optimal tour depends on |
|
216
|
|
|
|
|
|
|
knowledge of shorter "included" optimal tours; suboptimal tours are irrelevant. |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head1 EXERCISES |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
These exercises may clarify the above analysis. |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=over 4 |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=item Exercise 1. |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Consider the parallelogram ((0,0), (1,1), (2,0), (3,1)). |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
a. Draw it on graph paper. |
|
229
|
|
|
|
|
|
|
b. Label points "0" through "3" |
|
230
|
|
|
|
|
|
|
c. Draw t[0,1]. Calculate its length. |
|
231
|
|
|
|
|
|
|
d. Draw t[0,2] and t[1,2]. Calculate their lengths. |
|
232
|
|
|
|
|
|
|
e. Draw t[0,3], t[1,3], and t[2,3]. Calculate their lengths. |
|
233
|
|
|
|
|
|
|
f. What is the optimal bitonic tour? |
|
234
|
|
|
|
|
|
|
g. Draw the suboptimal bitonic tour. |
|
235
|
|
|
|
|
|
|
h. Why does the above algorithm find the optimal tour, |
|
236
|
|
|
|
|
|
|
and not the suboptimal tour? |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item Exercise 2. |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Repeat Exercise 1 with pentagon ((0,2), (1,0), (2,3), (3,0), (4,2)). |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=back |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head1 METHODS |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=head2 $class->new() |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
Constructs a new solution object. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Example: |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
my $ts = Algorithm::TravelingSalesman::BitonicTour->new; |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=cut |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub new { |
|
257
|
25
|
|
|
25
|
1
|
23049
|
my $class = shift; |
|
258
|
25
|
|
|
|
|
131
|
my $self = bless { _tour => {}, _points => {} }, $class; |
|
259
|
25
|
|
|
|
|
68
|
return $self; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head2 $ts->add_point($x,$y) |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Adds a point at position (C<$x>, C<$y>) to be included in the solution. Method |
|
265
|
|
|
|
|
|
|
C checks to make sure that no two points have the same |
|
266
|
|
|
|
|
|
|
I-coordinate. This method will C with a descriptive error message |
|
267
|
|
|
|
|
|
|
if anything goes wrong. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Example: |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# add point at position (x=2, y=3) to the problem |
|
272
|
|
|
|
|
|
|
$ts->add_point(2,3); |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=cut |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub add_point { |
|
277
|
247
|
|
|
247
|
1
|
9106
|
my $self = shift; |
|
278
|
247
|
|
|
|
|
1060
|
my $valid = { type => SCALAR, regexp => $RE{num}{real} }; |
|
279
|
247
|
|
|
|
|
12533
|
my ($x, $y) = validate_pos(@_, ($valid) x 2); |
|
280
|
247
|
100
|
|
|
|
964
|
if (exists $self->_points->{$x}) { |
|
281
|
4
|
|
|
|
|
34
|
my $py = $self->_points->{$x}; |
|
282
|
4
|
|
|
|
|
73
|
croak "FAIL: point ($x,$y) duplicates previous point ($x,$py)"; |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
else { |
|
285
|
243
|
|
|
|
|
2162
|
$self->_sorted_points(undef); # clear any previous cache of sorted points |
|
286
|
243
|
|
|
|
|
1499
|
$self->_points->{$x} = $y; |
|
287
|
243
|
|
|
|
|
2700
|
return [$x, $y]; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head2 $ts->N() |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Returns the number of points that have been added to the object (mnemonic: |
|
294
|
|
|
|
|
|
|
Bumber). |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
Example: |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
print "I have %d points.\n", $ts->N; |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=cut |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub N { |
|
303
|
281854
|
|
|
281854
|
1
|
354079
|
my $self = shift; |
|
304
|
281854
|
|
|
|
|
271918
|
return scalar keys %{ $self->_points }; |
|
|
281854
|
|
|
|
|
674829
|
|
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head2 $ts->R() |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
Returns the index of the rightmost point that has been added to the object |
|
310
|
|
|
|
|
|
|
(mnemonic: Bightmost). This is always one less than C<< $ts->N >>. |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=cut |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
sub R { |
|
315
|
468
|
|
|
468
|
1
|
4278
|
my $self = shift; |
|
316
|
468
|
100
|
|
|
|
797
|
die 'Problem has no rightmost point (N < 1)' if $self->N < 1; |
|
317
|
467
|
|
|
|
|
2695
|
return $self->N - 1; |
|
318
|
|
|
|
|
|
|
} |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head2 $ts->sorted_points() |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
Returns an array of points sorted by increasing I-coordinate. The first |
|
324
|
|
|
|
|
|
|
("zeroI | ") array element returned is thus the leftmost point in the problem.
|
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Each point is represented as an arrayref containing (x,y) coordinates. The |
|
327
|
|
|
|
|
|
|
sorted array of points is cached, but the cache is cleared by each call to |
|
328
|
|
|
|
|
|
|
C. |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Example: |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
my $ts = Algorithm::TravelingSalesman::BitonicTour->new; |
|
333
|
|
|
|
|
|
|
$ts->add_point(1,1); |
|
334
|
|
|
|
|
|
|
$ts->add_point(0,0); |
|
335
|
|
|
|
|
|
|
$ts->add_point(2,0); |
|
336
|
|
|
|
|
|
|
my @sorted = $ts->sorted_points; |
|
337
|
|
|
|
|
|
|
# @sorted contains ([0,0], [1,1], [2,0]) |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=cut |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub sorted_points { |
|
342
|
80353
|
|
|
80353
|
1
|
93397
|
my $self = shift; |
|
343
|
80353
|
100
|
|
|
|
185571
|
unless ($self->_sorted_points) { |
|
344
|
27
|
|
|
|
|
145
|
my @x = sort { $a <=> $b } keys %{ $self->_points }; |
|
|
1322
|
|
|
|
|
1584
|
|
|
|
27
|
|
|
|
|
71
|
|
|
345
|
27
|
|
|
|
|
187
|
my @p = map [ $_, $self->_points->{$_} ], @x; |
|
346
|
27
|
|
|
|
|
913
|
$self->_sorted_points(\@p); |
|
347
|
|
|
|
|
|
|
} |
|
348
|
80353
|
|
|
|
|
422341
|
return @{ $self->_sorted_points }; |
|
|
80353
|
|
|
|
|
172126
|
|
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 coord($n) |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Returns an array containing the coordinates of point C<$n>. |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
Examples: |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
my ($x0, $y0) = $ts->coord(0); # coords of leftmost point |
|
358
|
|
|
|
|
|
|
my ($x1, $y1) = $ts->coord(1); # coords of next point |
|
359
|
|
|
|
|
|
|
# ... |
|
360
|
|
|
|
|
|
|
my ($xn, $yn) = $ts->coord(-1); # coords of rightmost point--CLEVER! |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=cut |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub coord { |
|
365
|
80348
|
|
|
80348
|
1
|
106349
|
my ($self, $n) = @_; |
|
366
|
80348
|
|
|
|
|
91929
|
return @{ ($self->sorted_points)[$n] }; |
|
|
80348
|
|
|
|
|
138112
|
|
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=head2 $ts->solve() |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Solves the problem as configured. Returns a list containing the length of the |
|
372
|
|
|
|
|
|
|
minimum tour, plus the coordinates of the points in the tour in traversal |
|
373
|
|
|
|
|
|
|
order. |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Example: |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
my ($length, @points) = $ts->solve(); |
|
378
|
|
|
|
|
|
|
print "length: $length\n"; |
|
379
|
|
|
|
|
|
|
for (@points) { |
|
380
|
|
|
|
|
|
|
my ($x,$y) = @$_; |
|
381
|
|
|
|
|
|
|
print "($x,$y)\n"; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=cut |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub solve { |
|
387
|
23
|
|
|
23
|
1
|
764
|
my $self = shift; |
|
388
|
23
|
|
|
|
|
29
|
my ($length, @points); |
|
389
|
23
|
100
|
|
|
|
59
|
if ($self->N < 1) { |
|
|
|
100
|
|
|
|
|
|
|
390
|
1
|
|
|
|
|
28
|
die "ERROR: you need to add some points!"; |
|
391
|
|
|
|
|
|
|
} |
|
392
|
|
|
|
|
|
|
elsif ($self->N == 1) { |
|
393
|
10
|
|
|
|
|
76
|
($length, @points) = (0,0); |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
else { |
|
396
|
12
|
|
|
|
|
76
|
($length, @points) = $self->optimal_closed_tour; |
|
397
|
|
|
|
|
|
|
} |
|
398
|
22
|
|
|
|
|
65
|
my @coords = map { [ $self->coord($_) ] } @points; |
|
|
247
|
|
|
|
|
5352
|
|
|
399
|
22
|
|
|
|
|
339
|
return ($length, @coords); |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head2 $ts->optimal_closed_tour |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
Find the length of the optimal complete (closed) bitonic tour. This is done by |
|
405
|
|
|
|
|
|
|
choosing the shortest tour from the set of all possible complete tours. |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
A possible closed tour is composed of a partial tour with rightmost point C |
|
408
|
|
|
|
|
|
|
as one of its endpoints plus the final return segment from R to the other |
|
409
|
|
|
|
|
|
|
endpoint of the tour. |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
T(0,R) + delta(0,R) |
|
412
|
|
|
|
|
|
|
T(1,R) + delta(1,R) |
|
413
|
|
|
|
|
|
|
... |
|
414
|
|
|
|
|
|
|
T(i,R) + delta(i,R) |
|
415
|
|
|
|
|
|
|
... |
|
416
|
|
|
|
|
|
|
T(R-1,R) + delta(R-1,R) |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=cut |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
sub optimal_closed_tour { |
|
421
|
12
|
|
|
12
|
1
|
16
|
my $self = shift; |
|
422
|
12
|
|
|
|
|
38
|
$self->populate_open_tours; |
|
423
|
12
|
|
|
|
|
89
|
my $R = $self->R; |
|
424
|
213
|
|
|
|
|
457
|
my @tours = map { |
|
425
|
12
|
|
|
|
|
67
|
my $cost = $self->tour_length($_,$self->R) + $self->delta($_,$self->R); |
|
426
|
213
|
|
|
|
|
538
|
my @points = ($self->tour_points($_,$R), $_); |
|
427
|
213
|
|
|
|
|
14637
|
[ $cost, @points ]; |
|
428
|
|
|
|
|
|
|
} 0 .. $self->R - 1; |
|
429
|
12
|
100
|
|
201
|
|
112
|
my $tour = reduce { $a->[0] < $b->[0] ? $a : $b } @tours; |
|
|
201
|
|
|
|
|
353
|
|
|
430
|
12
|
|
|
|
|
821
|
return @$tour; |
|
431
|
|
|
|
|
|
|
} |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=head2 $ts->populate_open_tours |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
Populates internal data structure C describing all possible |
|
436
|
|
|
|
|
|
|
optimal open tour costs and paths for this problem configuration. |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=cut |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub populate_open_tours { |
|
441
|
13
|
|
|
13
|
1
|
1083
|
my $self = shift; |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# Base case: tour(0,1) has to be the segment (0,1). It would be nice if |
|
444
|
|
|
|
|
|
|
# the loop indices handled this case correctly, but they don't. |
|
445
|
13
|
|
|
|
|
39
|
$self->tour_length(0, 1, $self->delta(0,1) ); |
|
446
|
13
|
|
|
|
|
93
|
$self->tour_points(0, 1, 0, 1); |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# find optimal tours for all points to the left of 2, 3, ... up to R |
|
449
|
13
|
|
|
|
|
90
|
foreach my $k (2 .. $self->R) { |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# for each point "i" to the left of "k", find (and save) the optimal |
|
452
|
|
|
|
|
|
|
# open bitonic tour from "i" to "k". |
|
453
|
203
|
|
|
|
|
2658
|
foreach my $i (0 .. $k - 1) { |
|
454
|
20109
|
|
|
|
|
200315
|
my ($len, @points) = $self->optimal_open_tour($i,$k); |
|
455
|
20109
|
|
|
|
|
116524
|
$self->tour_length($i, $k, $len); |
|
456
|
20109
|
|
|
|
|
206925
|
$self->tour_points($i, $k, @points); |
|
457
|
|
|
|
|
|
|
} |
|
458
|
|
|
|
|
|
|
} |
|
459
|
|
|
|
|
|
|
} |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=head2 $ts->optimal_open_tour($i,$j) |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
Determines the optimal open tour from point C<$i> to point C<$j>, based on the |
|
464
|
|
|
|
|
|
|
values of previously calculated optimal tours to the left of C<$j>. |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
As discussed above, there are two distinct cases for this calculation: when C<< |
|
467
|
|
|
|
|
|
|
$i == $j - 1 >> and when C<< $i < $j - 1 >>. |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# determine the length of and points in the tour |
|
470
|
|
|
|
|
|
|
# starting at point 20 and ending at point 25 |
|
471
|
|
|
|
|
|
|
my ($length,@points) = $ts->optimal_open_tour(20,25); |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=cut |
|
474
|
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub optimal_open_tour { |
|
476
|
20113
|
|
|
20113
|
1
|
40048
|
my ($self, $i, $j) = @_; |
|
477
|
20113
|
|
|
|
|
31637
|
local $" = q(,); |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# we want $i to be strictly less than $j (we can actually be more lax with |
|
480
|
|
|
|
|
|
|
# the inputs, but this stricture halves our storage needs) |
|
481
|
20113
|
100
|
|
|
|
39568
|
croak "ERROR: bad call, optimal_open_tour(@_)" unless $i < $j; |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# if $i and $j are adjacent, many valid bitonic tours (i => x => j) are |
|
484
|
|
|
|
|
|
|
# possible; choose the shortest one. |
|
485
|
20112
|
100
|
|
|
|
42254
|
return $self->optimal_open_tour_adjacent($i, $j) if $i + 1 == $j; |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# if $i and $j are NOT adjacent, then only one bitonic tour (i => j-1 => j) |
|
488
|
|
|
|
|
|
|
# is possible. |
|
489
|
19908
|
100
|
|
|
|
55776
|
return $self->optimal_open_tour_nonadjacent($i, $j) if $i + 1 < $j; |
|
490
|
|
|
|
|
|
|
|
|
491
|
1
|
|
|
|
|
28
|
croak "ERROR: bad call, optimal_open_tour(@_)"; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head2 $obj->optimal_open_tour_adjacent($i,$j) |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Uses information about optimal open tours to the left of <$j> to find the |
|
497
|
|
|
|
|
|
|
optimal tour with endpoints (C<$i>, C<$j>). |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
This method handles the case where C<$i> and C<$j> are adjacent, i.e. C<< $i = |
|
500
|
|
|
|
|
|
|
$j - 1 >>. In this case there are many possible bitonic tours, all going from |
|
501
|
|
|
|
|
|
|
C<$i> to "C<$x>" to C<$j>. All points C<$x> in the range C<(0 .. $i - 1)> are |
|
502
|
|
|
|
|
|
|
examined to find the optimal tour. |
|
503
|
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=cut |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sub optimal_open_tour_adjacent { |
|
507
|
204
|
|
|
204
|
1
|
367
|
my ($self, $i, $j) = @_; |
|
508
|
19907
|
|
|
|
|
27201
|
my @tours = map { |
|
509
|
204
|
|
|
|
|
2510
|
my $x = $_; |
|
510
|
19907
|
|
|
|
|
36644
|
my $len = $self->tour_length($x,$i) + $self->delta($x,$j); |
|
511
|
19907
|
|
|
|
|
46616
|
my @path = reverse($j, $self->tour_points($x, $i) ); |
|
512
|
19907
|
|
|
|
|
843537
|
[ $len, @path ]; |
|
513
|
|
|
|
|
|
|
} 0 .. $i - 1; |
|
514
|
204
|
100
|
|
19703
|
|
5467
|
my $min_tour = reduce { $a->[0] < $b->[0] ? $a : $b } @tours; |
|
|
19703
|
|
|
|
|
36890
|
|
|
515
|
204
|
|
|
|
|
65090
|
return @$min_tour; |
|
516
|
|
|
|
|
|
|
} |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=head2 $obj->optimal_open_tour_nonadjacent($i,$j) |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
Uses information about optimal open tours to the left of <$j> to find the |
|
521
|
|
|
|
|
|
|
optimal tour with endpoints (C<$i>, C<$j>). |
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
This method handles the case where C<$i> and C<$j> are not adjacent, i.e. C<< |
|
524
|
|
|
|
|
|
|
$i < $j - 1 >>. In this case there is only one bitonic tour possible, going |
|
525
|
|
|
|
|
|
|
from C<$i> to C<$j-1> to C<$j>. |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=cut |
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
sub optimal_open_tour_nonadjacent { |
|
530
|
19907
|
|
|
19907
|
1
|
27264
|
my ($self, $i, $j) = @_; |
|
531
|
19907
|
|
|
|
|
41607
|
my $len = $self->tour_length($i, $j - 1) + $self->delta($j - 1,$j); |
|
532
|
19907
|
|
|
|
|
64970
|
my @points = ($self->tour_points($i, $j - 1), $j); |
|
533
|
19907
|
|
|
|
|
897318
|
return($len, @points); |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=head2 $b->tour($i,$j) |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Returns the data structure associated with the optimal open bitonic tour with |
|
540
|
|
|
|
|
|
|
endpoints (C<$i>, C<$j>). |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=cut |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub tour { |
|
545
|
280868
|
|
|
280868
|
1
|
401386
|
my ($self, $i, $j) = @_; |
|
546
|
280868
|
100
|
|
|
|
592456
|
croak "ERROR: tour($i,$j) ($i >= $j)" |
|
547
|
|
|
|
|
|
|
unless $i < $j; |
|
548
|
280867
|
100
|
|
|
|
516236
|
croak "ERROR: tour($i,$j,...) ($j >= @{[ $self->N ]})" |
|
|
1
|
|
|
|
|
12
|
|
|
549
|
|
|
|
|
|
|
unless $j < $self->N; |
|
550
|
280866
|
100
|
|
|
|
1932973
|
$self->_tour->{$i}{$j} = [] unless $self->_tour->{$i}{$j}; |
|
551
|
280866
|
|
|
|
|
2013032
|
return $self->_tour->{$i}{$j}; |
|
552
|
|
|
|
|
|
|
} |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=head2 $b->tour_length($i, $j, [$len]) |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
Returns the length of the optimal open bitonic tour with endpoints (C<$i>, |
|
557
|
|
|
|
|
|
|
C<$j>). If C<$len> is specified, set the length to C<$len>. |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=cut |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub tour_length { |
|
562
|
60158
|
|
|
60158
|
1
|
94125
|
my $self = shift; |
|
563
|
60158
|
|
|
|
|
65800
|
my $i = shift; |
|
564
|
60158
|
|
|
|
|
57680
|
my $j = shift; |
|
565
|
60158
|
100
|
|
|
|
118567
|
if (@_) { |
|
566
|
20123
|
100
|
|
|
|
42591
|
croak "ERROR: tour_length($i,$j,$_[0]) has length <= 0 ($_[0])" |
|
567
|
|
|
|
|
|
|
unless $_[0] > 0; |
|
568
|
20122
|
|
|
|
|
36141
|
$self->tour($i,$j)->[0] = $_[0]; |
|
569
|
|
|
|
|
|
|
} |
|
570
|
60157
|
100
|
|
|
|
202774
|
if (exists $self->tour($i,$j)->[0]) { |
|
571
|
60155
|
|
|
|
|
393776
|
return $self->tour($i,$j)->[0]; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
|
|
|
|
|
|
else { |
|
574
|
1
|
|
|
|
|
37
|
croak "Don't know the length of tour($i,$j)"; |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
} |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
=head2 $b->tour_points($i, $j, [@points]) |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
Returns an array containing the indices of the points in the optimal open |
|
581
|
|
|
|
|
|
|
bitonic tour with endpoints (C<$i>, C<$j>). |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
If C<@points> is specified, set the endpoints to C<@points>. |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
=cut |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
sub tour_points { |
|
588
|
60159
|
|
|
60159
|
1
|
85510
|
my $self = shift; |
|
589
|
60159
|
|
|
|
|
63763
|
my $i = shift; |
|
590
|
60159
|
|
|
|
|
64235
|
my $j = shift; |
|
591
|
60159
|
100
|
|
|
|
135368
|
if (@_) { |
|
592
|
20125
|
100
|
|
|
|
37044
|
croak "ERROR: tour_points($i,$j,@_) ($i != first point)" |
|
593
|
|
|
|
|
|
|
unless $i == $_[0]; |
|
594
|
20124
|
100
|
|
|
|
38882
|
croak "ERROR: tour_points($i,$j,@_) ($j != last point)" |
|
595
|
|
|
|
|
|
|
unless $j == $_[-1]; |
|
596
|
20123
|
100
|
|
|
|
39182
|
croak "ERROR: tour_points($i,$j,@_) (wrong number of points in @_)" |
|
597
|
|
|
|
|
|
|
unless scalar(@_) == $j + 1; |
|
598
|
20122
|
|
|
|
|
56025
|
$self->tour($i,$j)->[1] = \@_; |
|
599
|
|
|
|
|
|
|
} |
|
600
|
60156
|
100
|
|
|
|
200177
|
if (exists $self->tour($i,$j)->[1]) { |
|
601
|
60155
|
|
|
|
|
325973
|
return @{ $self->tour($i,$j)->[1] }; |
|
|
60155
|
|
|
|
|
109133
|
|
|
602
|
|
|
|
|
|
|
} |
|
603
|
|
|
|
|
|
|
else { |
|
604
|
1
|
|
|
|
|
21
|
croak "Don't know the points for tour($i,$j)"; |
|
605
|
|
|
|
|
|
|
} |
|
606
|
|
|
|
|
|
|
} |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=head2 $b->delta($p1,$p2); |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
Returns the euclidean distance from point C<$p1> to point C<$p2>. |
|
611
|
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
Examples: |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# print the distance from the leftmost to the next point |
|
615
|
|
|
|
|
|
|
print $b->delta(0,1); |
|
616
|
|
|
|
|
|
|
# print the distance from the leftmost to the rightmost point |
|
617
|
|
|
|
|
|
|
print $b->delta(0,-1); |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=cut |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
sub delta { |
|
622
|
40048
|
|
|
40048
|
1
|
262834
|
my ($self, $p1, $p2) = @_; |
|
623
|
40048
|
|
|
|
|
72347
|
my ($x1, $y1) = $self->coord($p1); |
|
624
|
40048
|
|
|
|
|
993006
|
my ($x2, $y2) = $self->coord($p2); |
|
625
|
40048
|
|
|
|
|
971719
|
return sqrt((($x1-$x2)*($x1-$x2))+(($y1-$y2)*($y1-$y2))); |
|
626
|
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
=head1 RESOURCES |
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
=over 4 |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=item |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford |
|
636
|
|
|
|
|
|
|
(2001). Introduction to Algorithms, second edition, MIT Press and McGraw-Hill. |
|
637
|
|
|
|
|
|
|
ISBN 978-0-262-53196-2. |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=item |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Bentley, Jon L. (1990), "Experiments on traveling salesman heuristics", Proc. |
|
642
|
|
|
|
|
|
|
1st ACM-SIAM Symp. Discrete Algorithms (SODA), pp. 91-99, |
|
643
|
|
|
|
|
|
|
L. |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=item |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
L |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
=item |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
L |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=item |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
L |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=item |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
L |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
=back |
|
662
|
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
=head1 AUTHOR |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
John Trammell, C<< >> |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=head1 BUGS |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
Please report any bugs or feature requests to C
|
|
670
|
|
|
|
|
|
|
rt.cpan.org>, or through the web interface at |
|
671
|
|
|
|
|
|
|
L. |
|
672
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
|
673
|
|
|
|
|
|
|
your bug as |
|
674
|
|
|
|
|
|
|
I make changes. |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=head1 SUPPORT |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
perldoc Algorithm::TravelingSalesman::BitonicTour |
|
681
|
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
You can also look for information at: |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
=over 4 |
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
|
687
|
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
L |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
|
691
|
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
L |
|
693
|
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
=item * CPAN Ratings |
|
695
|
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
L |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
=item * Search CPAN |
|
699
|
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
L |
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
=back |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
Copyright 2008 John Trammell, all rights reserved. |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
709
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
=cut |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
1; |
|
714
|
|
|
|
|
|
|
|