def merge_double_bridge(xy, best_order, start_point): original_length = len(best_order) trial_order = double_bridge.perturbed_climb(xy, best_order, 1) trial_length = basic.tour_length(xy, trial_order) print("trial tour length: " + str(trial_length)) old_edges, new_edges = tour_diff(best_order, trial_order) basic.write_edges(old_edges, "output/old_edges_test.txt") basic.write_edges(new_edges, "output/new_edges_test.txt") best_order = merge(xy, best_order, trial_order) new_length = basic.tour_length(xy, best_order) print("new length: " + str(new_length)) assert (trial_length >= new_length) assert (len(best_order) == original_length) return best_order
def perturbed_climb(xy, order, iterations): best_order = order[:] best_length = basic.tour_length(xy, best_order) climber = TwoOpt(xy) climber.tour.reset(best_order) for i in range(iterations): climber.tour.double_bridge_perturbation() climber.optimize() new_length = climber.tour.tour_length() if new_length < best_length: best_order = climber.tour.node_ids best_length = new_length else: climber.tour.reset(best_order) return climber.tour.node_ids
def perturbed_hill_climb(xy, tour): tries = 0 success = 0 best_length = tour_util.length(xy, tour) while True: new_tour, naive_new_length = two_opt.optimize(xy, tour_util.double_bridge(tour)) # double bridge #test_tour = tour[:] #random.shuffle(test_tour) #new_tour, naive_new_length = two_opt.optimize(xy, test_tour) # random restart segments = Splitter(tour, new_tour).get_segments() kmoves = segments_to_beneficial_kmoves(xy, segments, tour) max_gain = 0 if kmoves: max_gain = sum([k[0] for k in kmoves]) naive_gain = best_length - naive_new_length # There may be cases where naive gain is more than decomposed gains: # decomposed gains currently only return moves that can be independently performed. # Infeasible moves that are improvements but only can be combined with other moves to become feasible # (a potentially computationally expensive search) wil be excluded from the decomposed moves. dd_gain = 0 # gain due to decomposed kmoves. if kmoves: for k in kmoves: print(' trying {}-opt move with gain {}'.format(len(k[1]['adds']), k[0])) test_tour = perform_kmove(tour, k[1]) if len(test_tour) == len(tour): tour = test_tour best_length -= k[0] dd_gain += k[0] if naive_gain > dd_gain: print('naive_gain ({}) greater than dd_gain ({})'.format(naive_gain, dd_gain)) tour = new_tour best_length = naive_new_length if naive_gain > 0 or dd_gain > 0: success += 1 if dd_gain > 0 and dd_gain > naive_gain: print(' dd gain {} greater than naive gain {}'.format(dd_gain, naive_gain)) tries += 1 current_length = basic.tour_length(xy, tour) assert(best_length == current_length) if current_length <= TARGET_LENGTH: break print('current best: {} (iteration {}), improvement rate: {}'.format(best_length, tries, success / tries))
def perturbed_hill_climb_naive(xy, tour): tries = 0 success = 0 best_length = tour_util.length(xy, tour) while True: new_tour, naive_new_length = two_opt.optimize(xy, tour_util.double_bridge(tour)) # double bridge #test_tour = tour[:] #random.shuffle(test_tour) #new_tour, naive_new_length = two_opt.optimize(xy, test_tour) # random restart naive_gain = best_length - naive_new_length if naive_gain > 0: tour = new_tour best_length = naive_new_length success += 1 tries += 1 current_length = basic.tour_length(xy, tour) assert(best_length == current_length) if current_length <= TARGET_LENGTH: break print('current best: {} (iteration {}), improvement rate: {}'.format(best_length, tries, success / tries))
basic.write_edges(old_edges, "output/old_edges_test.txt") basic.write_edges(new_edges, "output/new_edges_test.txt") best_order = merge(xy, best_order, trial_order) new_length = basic.tour_length(xy, best_order) print("new length: " + str(new_length)) assert (trial_length >= new_length) assert (len(best_order) == original_length) return best_order if __name__ == "__main__": xy = reader.read_xy("../data/xqf131.tsp") order = [i for i in range(len(xy))] random.shuffle(order) order = opt2(order) print("initial tour length: " + str(basic.tour_length(xy, order))) for i in range(1000): basic.write_edges_from_order(order, "output/order_test.txt") print("merge iteration: " + str(i)) premerge_length = basic.tour_length(xy, order) #order = merge_nn(xy, order, i) order = merge_double_bridge(xy, order, i) postmerge_length = basic.tour_length(xy, order) if postmerge_length != premerge_length: order = opt2(order) postmerge_climb_length = basic.tour_length(xy, order) if postmerge_climb_length != postmerge_length: print("post-merge hill climb: " + str(postmerge_climb_length))
def tour_length(self): return basic.tour_length(self.xy, self.node_ids)