Using neighbor lists forces us to use some convenient and quick method to determine for given city (a neighbor) what is its position in current tour. We use an array indexed by city numbers and storing corresponding positions.
type
City_Position_In_Tour = array[City_Number, Tour_Index]
proc Create_Position_In_Tour(tour: Tour_Array): City_Position_In_Tour =
## Creates array with position of each city in tour
var
position: City_Position_In_Tour
for pos in 0 .. N-1:
position[tour[pos]] = pos
result = position
Note that array of positions should be updated during any action that changes the tour, be it reversing a segment:
proc Reverse_Segment(tour: var Tour_Array;
startIndex, endIndex: Tour_Index;
position: var City_Position_In_Tour) =
## Reverses order of elements in segment [startIndex, endIndex]
## of tour, and updates positon[] array used with neighbour lists
var
left, right: Tour_Index
let inversionSize = ((endIndex - startIndex + 1 + N) mod N) div 2
left = startIndex
right = endIndex
for counter in 1 .. inversionSize:
swap(tour[left], tour[right])
position[tour[left]] = left
position[tour[right]] = right
left = (left + 1) mod N
right = (N + right - 1) mod N
...or shifting a segment:
proc Shift_Segment(tour: var Tour_Array; i, j, k: Tour_Index;
position: var City_Position_In_Tour) =
## Shifts the segment of tour:
## cities from t[i+1] to t[j] from their current position to position
## after current city t[k], that is between cities t[k] and t[k+1].
## Accordingly updates positon[] array.
# Assumes: k, k+1 are not within the segment [i+1..j]
let
segmentSize = (j - i + N) mod N
shiftSize = ((k - i + N) - segmentSize + N) mod N
offset = i + 1 + shiftSize
var
pos, posNew: Tour_Index
segment: seq[City_Number] = newSeq[City_Number](segmentSize)
# make a copy of the segment before shift
for pos in 0 .. segmentSize-1:
segment[pos] = tour[(pos + i+1) mod N]
# shift to the left by segmentSize all cities between old position
# of right end of the segment and new position of its left end
pos = (i + 1) mod N
for counter in 1 .. shiftSize:
tour[pos] = tour[(pos + segmentSize) mod N]
position[tour[pos]] = pos
pos = (pos + 1) mod N
#end_for counter loop
# put the copy of the segment into its new place in the tour
for pos in 0 .. segmentSize-1:
posNew = (pos + offset) mod N
tour[posNew] = segment[pos]
position[tour[posNew]] = posNew
No comments:
Post a Comment