Saturday, March 11, 2017

Node Swap

Node Swap move

Node Swap is a simple tour optimization heuristics: it consists in swapping two cities in tour.

The idea:

A B
B A

Diagrams:

X0 Y0 X0_pred X0_succ Y0_pred Y0_succ
X0 Y0 X0_pred X0_succ Y0_pred Y0_succ

Node Swap move is a special case of two subsequent 2-opt moves: the first including both cities and the second without them. It involves removing four links and adding four new links, therefore is a specific type of 4-opt move.

Gain from Node Swap move

proc Gain_From_Node_Swap(X0_pred, X0, X0_succ,
                         Y0_pred, Y0, Y0_succ: City_Number): Length_Gain =
  ## Gain of tour length which can be obtained by performing Node Swap
  ## City X0 would be moved from its current position, between X0_pred
  ## and X0_succ, to the position of city Y0 and vice versa
  # Assumes: X0!=Y0
  #          X0=successor(X0_pred); X0_succ==successor(X0);
  #          Y0=successor(Y0_pred); Y0_succ==successor(Y0);
  var
    del_Length, add_Length: Length_Gain
  if (Y0==X0_succ) or (X0_succ==Y0_pred):
    del_Length = distance(X0_pred, X0) + distance(Y0, Y0_succ)
    add_Length = distance(X0_pred, Y0) + distance(X0, Y0_succ)
  elif (X0==Y0_succ) or (Y0_succ==X0_pred):
    del_Length = distance(Y0_pred, Y0) + distance(X0, X0_succ)
    add_Length = distance(Y0_pred, X0) + distance(Y0, X0_succ)
  else:
    del_Length = distance(X0_pred, X0) + distance(X0, X0_succ) +
                 distance(Y0_pred, Y0) + distance(Y0, Y0_succ)
    add_Length = distance(X0_pred, Y0) + distance(Y0, X0_succ) +
                 distance(Y0_pred, X0) + distance(X0, Y0_succ)
  #end_if
  result = del_Length - add_Length

Node Swap move implementation

proc Make_Node_Swap_Move(tour: var Tour_Array;
                         i, j: Tour_Index) =
  ## Performs given Node Swap move: swaps city t[i] with city city t[j]
  # This is a special, simple case of two subsequent 2-opt moves:
  # the first including both cities and the second without them
  #   -a-t[i]-b-t[j]-a-
  #   -a-(t[i]-b-t[j])'-a-  == -a-t[j]-b'-t[i]-a-
  #   -a-t[j]-(b')'-t[i]-a- == -a-t[j]-b-t[i]-a-
  swap(tour[i], tour[j])

Iterative Node Swap optimization

proc LS_Node_Swap(tour: var Tour_Array) =
  ## Optimizes the given tour using Node_Swap.
  # Shortens tour by repeating Node Swap moves until no improvement
  # can by done: in every iteration immediatelly makes permanent
  # the first move found that gives any length gain.
  var
    locallyOptimal: bool = false
    i, j: Tour_Index
    X0_pred, X0, X0_succ, Y0_pred, Y0, Y0_succ: City_Number

  while not locallyOptimal:
    locallyOptimal = true

    for counter_1 in 0 .. N-1:
      i = counter_1  # position of the first city
      X0_pred = tour[(N + i - 1) mod N]
      X0      = tour[i]
      X0_succ = tour[(i + 1) mod N]

      for counter_2 in counter_1+1 .. N-1:
        j  = counter_2  # position of the second city
        Y0_pred = tour[(N + j - 1) mod N]
        Y0 = tour[j]
        Y0_succ = tour[(j + 1) mod N]

        if Gain_From_Node_Swap(X0_pred, X0, X0_succ,
                               Y0_pred, Y0, Y0_succ) > 0:
          Make_Node_Swap_Move(tour, i, j)
          locallyOptimal = false
          break

Some simple statistics

Relative time, best length, average length and worst length for all tours created by NN heuristic and improved by 2-opt and Node Swap algorithms. Random planar problems, N=100.
Problem # Method Time Best Avg Worst
1NN100100.00107.17119.19
NN + 2opt97589.5392.7799.31
NN + NodeSwap29394.61103.80116.17
2NN100100.00107.49118.89
NN + 2opt114690.7894.5198.18
NN + NodeSwap41995.23101.53110.37
3NN100100.00107.68114.62
NN + 2opt117589.9793.0897.98
NN + NodeSwap29394.55102.50111.75
4NN100100.00109.62122.88
NN + 2opt107590.7493.5598.18
NN + NodeSwap29397.54106.47118.40
5NN100100.00106.67113.50
NN + 2opt117590.9093.9197.43
NN + NodeSwap29394.35101.54107.83
6NN100100.00109.94120.93
NN + 2opt125387.1490.8497.60
NN + NodeSwap41993.50101.63110.62
7NN100100.00109.60121.26
NN + 2opt146086.2290.3294.58
NN + NodeSwap42095.34103.06114.27
8NN100100.00110.14121.53
NN + 2opt97586.0590.9298.23
NN + NodeSwap48791.82105.68115.13
9NN100100.00110.14121.53
NN + 2opt107586.0590.9298.23
NN + NodeSwap39391.82105.68115.13
10NN100100.00111.65120.86
NN + 2opt83395.0997.70102.49
NN + NodeSwap41997.68106.43117.24

No comments:

Post a Comment