Procedures to calculate the gain from 3-opt move and to make 3-opt move assume that their parameters (cities and their indices in tour) are given in the order of ascending indices of tour array (modulo N). Therefore we need a function to recognize whether three indices are in this order, or: whether in this orientation the middle index is between the two boundary indices.
proc Between(a, x, b: Tour_Index): bool =
## Returns true if `x` is between `a` and `b` in cyclic sequence
## with established orientation of nondescending indices
# That is: when one begins a forward traversal of the tour
# at position `a', then position `x` is reached before position `b'.
# Returns true if and only if:
# a < x < b or b < a < x or x < b < a
if (b > a):
result = (x > a) and (x < b)
elif (b < a):
result = (x > a) or (x < b)
else:
result = false
Note the additional speed-up: the link between base city X1
and its tour neighbor X2
is not considered when at least one of these cities has its don’t-look bit set to on.
proc One_City_3_Opt_DLB(tour: var Tour_Array,
basePos: Tour_Index,
DontLook: var DLB_Array): bool =
type
Move3 = object
i, j, k: Tour_Index
optCase: Reconnection_3_optCase
var
improved: bool
i, j, k: Tour_Index
X1, X2, Y1, Y2, Z1, Z2: City_Number
gainExpected: Length_Gain
optCase: Reconnection_3_optCase
goodMove: Move3
improved = false
block three_loops:
for direction in [forward, backward]:
if direction == forward:
i = basePos
else:
i = (N + basePos - 1) mod N
X1 = tour[i]
X2 = tour[(i+1) mod N]
if isDLB_on(DontLook,X1) or isDLB_on(DontLook,X2): # NOTE
continue
for counter_2 in 0 .. N-1:
j = counter_2 # second cut after j
Y1 = tour[j]
Y2 = tour[(j+1) mod N]
if (X1 == Y1) or (X2 == Y1) or (Y2 == X1):
continue
# examine 2-opt move (see: opt3_case_1 .. opt3_case_3)
gainExpected = Gain_From_2_Opt(X1, X2, Y1, Y2)
if gainExpected > 0:
goodMove = Move3(i: i, j: j, k: j,
optCase: opt3_case_1)
improved = true
break three_loops
for counter_3 in 0 .. N-1:
k = counter_3 # third cut after k
Z1 = tour[k]
Z2 = tour[(k+1) mod N]
if (X1 == Z1) or (Y1 == Z1):
continue
if not Between(i, j, k):
continue
# examine pure 3-opt cases
for optCase in [opt3_case_6, opt3_case_7]:
gainExpected = Gain_From_3_Opt(X1, X2, Y1, Y2, Z1, Z2,
optCase)
if gainExpected > 0:
goodMove = Move3(i: i, j: j, k: k,
optCase: optCase)
improved = true
break three_loops
# end_block three_loops
if improved:
Set_DLB_off(DontLook, [X1, X2, Y1, Y2])
if goodMove.optCase > opt3_case_3:
Set_DLB_off(DontLook, [Z1, Z2])
Make_3_Opt_Move(tour,
goodMove.i, goodMove.j, goodMove.k,
goodMove.optCase)
result = improved
proc LS_3_Opt_DLB(tour: var Tour_Array) =
## Optimizes the given tour using 3-opt with Don't Look Bits (DLB)
var
locallyOptimal: bool = false
improved: bool
DontLook: DLB_Array
baseCity: City_Number
Set_DLB_off(DontLook, tour)
while not locallyOptimal:
locallyOptimal = true
for basePos in 0 .. N-1:
baseCity = tour[basePos]
if isDLB_on(DontLook, baseCity):
continue
improved = One_City_3_Opt_DLB(tour, basePos, DontLook)
if not improved:
Set_DLB_on(DontLook, baseCity)
else:
locallyOptimal = false
Some simple statistics
Problem # | Method | Time | Best | Avg | Worst |
---|---|---|---|---|---|
1 | NN | 100 | 100.00 | 107.94 | 117.16 |
NN + 2opt | 1268 | 90.06 | 92.88 | 101.40 | |
NN + 3opt | 75093 | 88.61 | 89.92 | 91.77 | |
NN + 3opt-DLB | 28125 | 88.61 | 90.07 | 92.72 | |
2 | NN | 100 | 100.00 | 109.67 | 122.62 |
NN + 2opt | 1146 | 88.91 | 94.14 | 101.71 | |
NN + 3opt | 73646 | 88.89 | 90.41 | 93.56 | |
NN + 3opt-DLB | 27919 | 88.99 | 90.85 | 94.98 | |
3 | NN | 100 | 100.00 | 107.04 | 118.01 |
NN + 2opt | 940 | 91.11 | 94.74 | 98.25 | |
NN + 3opt | 72920 | 88.77 | 91.19 | 93.11 | |
NN + 3opt-DLB | 25933 | 88.86 | 91.53 | 93.85 | |
4 | NN | 100 | 100.00 | 107.40 | 118.32 |
NN + 2opt | 975 | 89.03 | 92.56 | 97.91 | |
NN + 3opt | 72856 | 87.99 | 89.56 | 92.33 | |
NN + 3opt-DLB | 25681 | 87.99 | 89.80 | 93.41 | |
5 | NN | 100 | 100.00 | 104.79 | 113.38 |
NN + 2opt | 1460 | 81.19 | 84.60 | 89.37 | |
NN + 3opt | 72706 | 79.82 | 81.76 | 84.73 | |
NN + 3opt-DLB | 29166 | 79.82 | 81.98 | 85.00 | |
6 | NN | 100 | 100.00 | 104.66 | 115.85 |
NN + 2opt | 1360 | 82.98 | 86.03 | 90.66 | |
NN + 3opt | 68539 | 82.39 | 83.59 | 85.12 | |
NN + 3opt-DLB | 26979 | 82.39 | 83.59 | 85.56 | |
7 | NN | 100 | 100.00 | 109.45 | 118.42 |
NN + 2opt | 1360 | 88.10 | 92.88 | 97.84 | |
NN + 3opt | 78639 | 86.66 | 88.83 | 91.93 | |
NN + 3opt-DLB | 28026 | 86.66 | 89.14 | 92.78 | |
8 | NN | 100 | 100.00 | 104.37 | 112.02 |
NN + 2opt | 1046 | 88.50 | 91.59 | 97.77 | |
NN + 3opt | 75313 | 86.40 | 88.34 | 91.11 | |
NN + 3opt-DLB | 26040 | 86.75 | 88.92 | 95.75 | |
9 | NN | 100 | 100.00 | 108.32 | 118.64 |
NN + 2opt | 1566 | 91.31 | 94.95 | 100.77 | |
NN + 3opt | 66460 | 90.46 | 92.05 | 95.71 | |
NN + 3opt-DLB | 25726 | 90.59 | 92.12 | 95.83 | |
10 | NN | 100 | 100.00 | 107.87 | 122.61 |
NN + 2opt | 1146 | 89.12 | 93.21 | 99.11 | |
NN + 3opt | 69066 | 87.98 | 89.43 | 93.58 | |
NN + 3opt-DLB | 26666 | 87.98 | 89.67 | 92.78 |
No comments:
Post a Comment