Wednesday, April 5, 2017

3-opt with Neighbor Lists and DLB – simple

Compare the code below with the code for 2-opt with neighbor lists and DLB and notice that this algorithm is simplified, not truly bi-directional version.

proc One_City_3_Opt_ND(tour: var Tour_Array;
                       basePos: Tour_Index;
                       neighbor: Neighbor_Matrix;
                       position: var City_Position_In_Tour;
                       numberOfNeigbors: int;
                       DontLook: var DLB_Array): bool =
  type
    Move3 = object
      i, j, k: Tour_Index
      optCase: Reconnection_3_optCase
      gain: Length_Gain
  var
    improved: bool
    i, j, k: Tour_Index
    X1, X2, Y1, Y2, Z1, Z2: City_Number
    k_6, k_7:  Tour_Index
    Z1_6, Z2_6, Z1_7, Z2_7: City_Number
    gainExpected: Length_Gain
    goodMove: Move3
  
  improved = false
  goodMove.gain = 0
  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]
 
      for neighbor_1 in 0 .. numberOfNeigbors-1:
        # new edges in optCase=6: *X1-Y2*, Y1-Z1, X2-Z2
        # new edges in optCase=7: *X1-Y2*, X2-Z1, Y1-Z2
        Y2 = neighbor[X1][neighbor_1]
        j  = (position[Y2] + N - 1) mod N
        Y1 = tour[j]

        if (Y1 != X1) and (Y1 != X2):
          gainExpected = Gain_From_2_Opt(X1, X2, Y1, Y2)
          if gainExpected > goodMove.gain:
            improved = true
            goodMove = Move3(i: i,  j: j,  k: j,
                             optCase: opt3_case_1, gain: gainExpected)

        for neighbor_2 in 0 .. numberOfNeigbors-1:
          # new edges in optCase=6: X1-Y2, *Y1-Z1*, X2-Z2
          Z1_6 = neighbor[Y1][neighbor_2]
          k_6  = position[Z1_6]
          Z2_6 = tour[(k_6 + 1) mod N]
          # new edges in optCase=7: X1-Y2, X2-Z1, *Y1-Z2*
          Z2_7 = neighbor[Y1][neighbor_2]
          k_7  = (position[Z2_7] + N - 1) mod N
          Z1_7 = tour[k_7]
          
          if Between(i, j, k_6):
            gainExpected = Gain_From_3_Opt(X1, X2, Y1, Y2, Z1_6, Z2_6,
                                           opt3_case_6)
            if gainExpected > goodMove.gain:
              improved = true
              goodMove = Move3(i: i,  j: j,  k: k_6,
                               optCase: opt3_case_6, gain: gainExpected)

          if Between(i, j, k_7):
            gainExpected = Gain_From_3_Opt(X1, X2, Y1, Y2, Z1_7, Z2_7,
                                           opt3_case_7)
            if gainExpected > goodMove.gain:
              improved = true
              goodMove = Move3(i: i,  j: j,  k: k_7,
                               optCase: opt3_case_7, gain: gainExpected)

  if improved:
    Set_DLB_off(DontLook,
                  [ tour[goodMove.i], tour[(goodMove.i + 1) mod N],
                    tour[goodMove.j], tour[(goodMove.j + 1) mod N],
                    tour[goodMove.k], tour[(goodMove.k + 1) mod N] ])
    Make_3_Opt_Move(tour,
                    goodMove.i,  goodMove.j,  goodMove.k,
                    goodMove.optCase,  position)
  result = improved

Some simple statistics

Relative time, best length, average length and worst length for all tours created by NN heuristic and improved by some 2-opt and 3-opt algorithms. Random planar problems, N=100.
Problem # Method Time Best Avg Worst
1NN100100.00111.12122.44
NN + 2opt136088.9492.5898.91
NN + 2opt Take Best114089.4791.7595.40
NN + 3opt7916687.9989.6192.82
NN + 3opt-ND(24)458687.9989.8694.22
2NN100100.00107.46119.61
NN + 2opt114690.8594.70100.03
NN + 2opt Take Best104688.5992.0997.39
NN + 3opt6947387.2289.8994.23
NN + 3opt-ND(24)458687.2289.8793.04
3NN100100.00106.81117.56
NN + 2opt68188.9293.3497.90
NN + 2opt Take Best88189.3892.2896.22
NN + 3opt6611287.8589.5393.19
NN + 3opt-ND(24)410687.6889.0792.68
4NN100100.00108.58116.96
NN + 2opt146085.6088.5292.28
NN + 2opt Take Best125385.4086.8789.81
NN + 3opt7322683.1484.8087.22
NN + 3opt-ND(24)458683.1585.0187.43
5NN100100.00110.59124.43
NN + 2opt114692.7395.4298.30
NN + 2opt Take Best94091.4393.5897.02
NN + 3opt7239390.9192.3294.66
NN + 3opt-ND(24)416690.9192.2793.67
6NN100100.00107.15118.12
NN + 2opt125389.3592.7198.25
NN + 2opt Take Best93988.7490.8192.73
NN + 3opt6937387.9489.6391.73
NN + 3opt-ND(24)437388.2090.0092.09
7NN100100.00110.20121.48
NN + 2opt125392.3095.3198.94
NN + 2opt Take Best93991.5393.9497.52
NN + 3opt6530690.4191.7494.38
NN + 3opt-ND(24)427390.4191.6393.30
8NN100100.00105.35112.99
NN + 2opt125388.2092.0297.83
NN + 2opt Take Best83388.6990.7295.39
NN + 3opt6698087.6688.7794.75
NN + 3opt-ND(24)427387.6689.3492.54
9NN100100.00107.15115.57
NN + 2opt78192.0895.79100.95
NN + 2opt Take Best87590.9494.0698.73
NN + 3opt7168189.7691.3594.37
NN + 3opt-ND(24)439389.7691.3293.54
10NN100100.00106.56113.89
NN + 2opt125387.0790.8794.98
NN + 2opt Take Best104086.6688.6391.83
NN + 3opt7135386.0187.6490.86
NN + 3opt-ND(24)427386.0187.4191.10

No comments:

Post a Comment