Monday, March 20, 2017

2.5-opt with DLB

proc One_City_25_Opt_DLB(tour: var Tour_Array,
                         basePos: Tour_Index,
                         DontLook: var DLB_Array): bool =
  var
    improved: bool
    i, j: Tour_Index
    X1, X2, Y1, Y2, V0: City_Number

  improved = false
  block two_loops:
    for direction in [forward, backward]:  # NOTE: both tour neighbors
      # consider link between t[i] and t[i+1],
      # then between t[i-1] and t[i]
      if direction == forward:
        i  = basePos
      else:
        i  = (N + basePos - 1) mod N
      X1 = tour[i]
      X2 = tour[(i+1) mod N]

      for counter_2 in 0 .. N-1:
        j = counter_2
        Y1 = tour[j]
        Y2 = tour[(j+1) mod N]
        if (X1 == Y1) or (X2 == Y1) or (Y2 == X1):
          continue

        if Gain_From_2_Opt(X1, X2, Y1, Y2) > 0:
          Make_2_Opt_Move(tour, i, j)
          improved = true
        else:
          V0 = tour[(i+2) mod N]
          if V0 != Y1:
            if Gain_From_Node_Shift(X1, X2, V0, Y1, Y2) > 0:
              Set_DLB_off(DontLook, V0)
              Make_Node_Shift_Move(tour, (i+1) mod N, j)
              improved = true
          else:
            V0 = tour[(N+j-1) mod N]
            if V0 != X2:
              if Gain_From_Node_Shift(V0, Y1, Y2, X1, X2) > 0:
                Set_DLB_off(DontLook, V0)
                Make_Node_Shift_Move(tour, j, i)
                improved = true
        #end_if Gain_From_2_Opt...
        if improved:
          Set_DLB_off(DontLook, [X1, X2, Y1, Y2])
          break two_loops
  result = improved
proc LS_25_Opt_DLB(tour: var Tour_Array) =
  ## Optimizes the given tour using 2.5-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_25_Opt_DLB(tour, basePos, DontLook)
      if not improved:
        Set_DLB_on(DontLook, baseCity)
      else:
        locallyOptimal = false

No comments:

Post a Comment