【BI Learning Experience 21-Common Planning Problem 2】


1. The traveling salesman problem

Traveling Salesman Problem, a traveling salesman wants to visit several cities, and then return to his starting point, given the travel time required between each city, how to plan his route so that he can travel to each city exactly once access, and the total time is the shortest.

2. Vehicle Routing Problem (VRP)

The vehicle routing problem (VRP) was first proposed by Dantzig and Ramser in 1959. It refers to a certain number of customers, each with a different quantity of goods demand. The distribution center provides goods to customers, and a fleet is responsible for distributing goods. The goal of organizing an appropriate driving route is to meet the needs of customers and achieve the goals such as the shortest distance, minimum cost, and minimum time-consuming under certain constraints [1].

From this definition, it is not difficult to see that the Traveling Salesman Problem (TSP) is a special case of VRP. Since Gaery[2] has proved that the TSP problem is an NP problem, VRP is also an NP problem.

Since it was proposed in 1959, the vehicle routing problem has always been one of the most basic problems in network optimization. Due to its wide application and great economic value, it has been widely concerned by scholars at home and abroad. The vehicle routing problem can be described as follows (as shown in the figure):

insert image description here
There is a station (depot), a total of M trucks, the vehicle capacity is Q, there are N customers (customers), and each customer has its demand D. Vehicles depart from the station to provide delivery services to customers and return to the station. All customers are required to be delivered, and each customer is delivered once, and the vehicle capacity limit cannot be violated. The purpose is to minimize the total distance of all vehicle routes. Practical issues of vehicle routing include distribution center distribution, bus routing, letter and newspaper delivery, air and rail scheduling, industrial waste collection, and more.

2.1 Question types

Generally speaking, vehicle routing problems can be roughly divided into the following three types (Ballou, 1992):

  1. Distinct single origin and single end
  2. same single start and end
  3. Multiple origins and destinations

2.2 Approaches to the Vehicle Routing Problem

There are many academic research documents on the vehicle routing problem, and quite a few solving strategies and methods have been proposed. Bodin and Golden (1981) summarized the numerous solving methods into the following seven types:

2.3 Solution method

1. Evolution of solution methods

Based on the previous solutions to vehicle routing problems, they can be divided into exact algorithms and heuristics. The precise algorithms include branch-and-bound methods, branch-and-cut methods, and set-and-cover methods; heuristic solutions include economical methods. , simulated annealing, deterministic annealing, tabu search, genetic algorithm, neural network, ant colony algorithm, etc. In 1995, Fisher[5] divided the algorithm for solving the vehicle routing problem into three stages. The first stage is from 1960 to 1970, which is a simple heuristic method, including various local improvement heuristic algorithms and greedy method (Greedy), etc.; the second stage is from 1970 to 1980, which belongs to a mathematical method Planning-based heuristic solutions, including assignment method, set partition method and set cover method; the third stage is from 1990 to the present, which is a relatively new method, including the use of rigorous heuristic methods, artificial intelligence methods, etc.

2. Heuristic algorithm
Since VRP is an NP-hard problem, it is difficult to solve it with precise calculations. Heuristic algorithm is the main method to solve the vehicle transportation problem. Many scholars have studied the vehicle transportation problem over the years and proposed various heuristic method. The heuristic methods for vehicle transportation problems can be divided into simple heuristic algorithms, two-stage heuristic algorithms, and heuristic methods established by artificial intelligence methods.

Simple heuristics include parsing or insertion, intra/inter-route node exchange, greedy and local search. Savings or insertion is the process of constructing routes using the most cost-saving feasible way during the solution process until no savings are possible. The exchange method relies on other methods to generate an initial route, and then iteratively uses the exchange improvement method to reduce the route distance until it cannot be improved. In 1960, Clarke and Wright [6] first proposed a heuristic savings method (savings methods) to establish fleet distribution routes. The simple heuristic method is easy to understand and fast to solve, but it is only suitable for solving small and simple VRP problems.

The two-stage method includes two heuristic strategies: cluster first-route second and route first-cluster second. The former roughly divides all the demand points into several groups, and then sorts the routes of each group separately; the latter constructs all the demand points into a route, and then divides the route into several groups according to the vehicle capacity. Many suitable individual routes.

Since 1990, artificial intelligence methods have shown powerful functions in solving combinatorial optimization problems and have been fully applied in various fields. Many scholars have also introduced artificial intelligence into the solution of vehicle routing problems, and constructed a large number of heuristics based on artificial intelligence. algorithm. Tabu Search (TS) is basically an artificial intelligence (AI) local search method. Willard first used this algorithm to solve VRP, and many scholars later published TS algorithms for solving VRP. Yuan Qingda [7] of Southwest Jiaotong University designed a tabu algorithm considering time windows and different vehicle types. This algorithm mainly uses the GENIUS method to generate an initial solution, and then the tabu algorithm optimizes the initial solution. The simulated annealing method has the characteristics of fast convergence and global search. Osman [8] studied the simulated annealing algorithm of VRP, and the simulated annealing method he proposed is mainly suitable for solving route grouping. Genetic algorithm has good characteristics for solving combinatorial optimization problems. Holland first used genetic algorithm (GA) coding to solve VRPTW problem. Most scholars now adopt a mixed strategy, using two artificial intelligence methods for route grouping and route optimization. Ombuki [9] proposed a hybrid algorithm that uses genetic algorithm for route grouping and then uses tabu search method for route optimization. Bent and Van Hentenryck first used simulated annealing algorithm to minimize the number of vehicle routes, and then used large neighborhood search (largneighborhood search) to minimize transportation costs.

3. Genetic algorithm

Genetic Algorithm (Genetic Algorithm) is a calculation model of the biological evolution process that simulates the natural selection and genetic mechanism of Darwin's biological evolution theory, and searches for the optimal solution by simulating the natural evolution process.

The genetic algorithm is to initialize a population first, then determine the fitness of the individual according to the fitness function, select the individual for crossover based on the fitness, and let the individual mutate with a certain probability, so as to continuously select individuals with high fitness, and then Update the population.

Its main feature is to directly operate on structural objects, without the limitation of derivative and function continuity; it has inherent implicit parallelism and better global optimization ability; it adopts probabilistic optimization method and does not require definite rules It can automatically obtain and guide the optimized search space, and adjust the search direction adaptively.

The genetic algorithm takes all individuals in a population as objects, and uses randomization techniques to guide an efficient search of an encoded parameter space. Among them, selection, crossover and mutation constitute the genetic operation of the genetic algorithm; the core content of the genetic algorithm is composed of five elements: parameter coding, initial population setting, fitness function design, genetic operation design, and control parameter setting.

insert image description here

The genetic algorithm has the following steps:

  1. Initialization: set the evolution algebra counter t=0, set the maximum evolution algebra T, crossover probability, mutation probability, randomly generate M individuals as the initial population P
  2. Individual evaluation: calculate the fitness of each individual in the population P
  3. Selection operation: apply the selection operator to the group. Based on individual fitness, select the optimal individual to directly inherit to the next generation or generate new individuals through paired crossover and then pass on to the next generation
  4. Crossover operation: Under the control of the crossover probability, crossover the individuals in the group two by two
  5. Mutation operation: Under the control of the mutation probability, the individuals in the group are mutated in pairs, that is, the genes of an individual are randomly adjusted
  6. After selection, crossover, and mutation operations, the next generation population P' is obtained

Code and data download link : https://pan.baidu.com/s/1Tu5ZFPm2ZbITz6f8Jiyg9Q
Extraction code: 91g1

Specific code:

import numpy as np
import random
import copy
import matplotlib.pyplot as plt
 
class City:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __repr__(self):
        return "(" + str(self.x) + "," + str(self.y) + ")"
 
def distance(ca, cb):
    dx = abs(ca.x - cb.x)
    dy = abs(ca.y - cb.y)
    distance = np.sqrt((dx ** 2) + (dy ** 2))
    return distance
 
def init_pop(city_list, popSize):
    pop = []
    for i in range(popSize):
        new_city_list = random.sample(city_list, len(city_list))
        pop.append(new_city_list)
 
    return pop
 
def fitness(pop):
    dis_citys = distance_citys(pop)
    return 1.0/dis_citys
 
def distance_citys(pop):
    temp_dis = 0
    for i in range(len(pop)-1):
        temp_dis += distance(pop[i], pop[i+1])
    temp_dis += distance(pop[len(pop)-1], pop[0])
 
    return temp_dis
 
def rank(poplulation):
    rankPop_dic = {
    
    }
    for i in range(len(poplulation)):
        fit = fitness(poplulation[i])
        rankPop_dic[i] = fit
 
    return sorted(rankPop_dic.items(), key=lambda x:x[1], reverse=True)
 
 
def select(pop, pop_rank, eliteSize):
    select_pop = []
    for i in range(eliteSize):
        select_pop.append(pop[pop_rank[i][0]])
 
    cumsum = 0
    cumsum_list = []
    temp_pop = copy.deepcopy(pop_rank)
    for i in range(len(temp_pop)):
        cumsum += temp_pop[i][1]
        cumsum_list.append(cumsum)
    for i in range(len(temp_pop)):
        cumsum_list[i] /= cumsum
 
    for i in range(len(temp_pop)-eliteSize):
        rate = random.random()
        for j in range(len(temp_pop)):
            if cumsum_list[j] > rate:
                select_pop.append(pop[pop_rank[i][0]])
                break
 
    return select_pop
 
def breed(pop, eliteSize):
    breed_pop = []
    for i in range(eliteSize):
        breed_pop.append(pop[i])
 
    i = 0
    while i < (len(pop)-eliteSize):
        a = random.randint(0, len(pop)-1)
        b = random.randint(0, len(pop)-1)
        if a != b:
            fa, fb = pop[a], pop[b]
            genea, geneb = random.randint(0, len(pop[a])-1), random.randint(0, len(pop[b])-1)
            startgene = min(genea, geneb)
            endgene = max(genea, geneb)
            child1 = []
            for j in range(startgene, endgene):
                child1.append(fa[j])
            # child1 = copy.deepcopy(fa[:-1])
            child2 = []
            for j in fb:
                if j not in child1:
                    child2.append(j)
            # child2 = [j for j in fb if j not in child1]
            breed_pop.append(child1+child2)
            i = i+1
 
    return breed_pop
 
def mutate(pop, mutationRate):
    mutation_pop = []
    for i in range(len(pop)):
        for j in range(len(pop[i])):
            rate = random.random()
            if rate < mutationRate:
                a = random.randint(0, len(pop[i])-1)
                pop[i][a], pop[i][j] = pop[i][j], pop[i][a]
        mutation_pop.append(pop[i])
 
    return mutation_pop
 
 
def next_pop(population, eliteSize, mutationRate):
    pop_rank = rank(population) #按照适应度排序
    select_pop = select(population, pop_rank, eliteSize) #精英选择策略,加上轮盘赌选择
    breed_pop = breed(select_pop, eliteSize) #繁殖
    next_generation = mutate(breed_pop, mutationRate) #变异
 
    return next_generation
 
#画出路线图的动态变化
def GA_plot_dynamic(city_list, popSize, eliteSize, mutationRate, generations):
    plt.figure('Map')
    plt.ion()
    population = init_pop(city_list, popSize)
 
    print("initial distance:{}".format(1.0/(rank(population)[0][1])))
    for i in range(generations):
        plt.cla()
        population = next_pop(population, eliteSize, mutationRate)
        idx_rank_pop = rank(population)[0][0]
        best_route = population[idx_rank_pop]
        city_x = []
        city_y = []
        for j in range(len(best_route)):
            city = best_route[j]
            city_x.append(city.x)
            city_y.append(city.y)
        city_x.append(best_route[0].x)
        city_y.append(best_route[0].y)
        plt.scatter(city_x, city_y, c='r', marker='*', s=200, alpha=0.5)
        plt.plot(city_x, city_y, "b", ms=20)
        plt.pause(0.1)
 
    plt.ioff()
    plt.show()
 
 
 
    print("final distance:{}".format(1.0 / (rank(population)[0][1])))
    bestRouteIndex = rank(population)[0][0]
    bestRoute = population[bestRouteIndex]
    return bestRoute
 
def GA(city_list, popSize, eliteSize, mutationRate, generations):
    population = init_pop(city_list, popSize) #初始化种群
    process = []
 
    print("initial distance:{}".format(1.0/(rank(population)[0][1])))
    for i in range(generations):
        population = next_pop(population, eliteSize, mutationRate) #产生下一代种群
        process.append(1.0 / (rank(population)[0][1]))
 
 
 
    plt.figure(1)
    print("final distance:{}".format(1.0 / (rank(population)[0][1])))
    plt.plot(process)
    plt.ylabel('Distance')
    plt.xlabel('Generation')
    plt.savefig(str(generations)+ '_' + str(1.0 / (rank(population)[0][1])) + '_' + str(mutationRate) +'_process.jpg')
 
    plt.figure(2)
    idx_rank_pop = rank(population)[0][0]
    best_route = population[idx_rank_pop]
    city_x = []
    city_y = []
    for j in range(len(best_route)):
        city = best_route[j]
        city_x.append(city.x)
        city_y.append(city.y)
    city_x.append(best_route[0].x)
    city_y.append(best_route[0].y)
    plt.scatter(city_x, city_y, c='r', marker='*', s=200, alpha=0.5)
    plt.plot(city_x, city_y, "b", ms=20)
 
    plt.savefig(str(generations)+'_' + str(mutationRate) + '_route.jpg')
    plt.show()
 
num_city = 25
city_list = []
 
 
# for i in range(num_city):
#     x = random.randint(1, 200)
#     y = random.randint(1, 200)
#     city_list.append(City(x, y))
with open('city.txt', 'r', encoding='UTF-8') as f:
    lines = f.readlines()
for line in lines:
    line = line.replace('\n', '')
    # line = line.replace('\t', '')
    city = line.split('\t')
    city_list.append( City( float(city[1]), float(city[2]) ) )
 
# mutationRates = [0.001, 0.002, 0.005, 0.008, 0.01, 0.02]
# for mut in mutationRates:
GA(city_list, 100, 20, 0.01, 5000)

The result is as follows:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_43849871/article/details/117634598