├── .gitattributes ├── .gitignore ├── Intelligent optimization algorithm ├── ACO_CVRP.py ├── DE_CVRP.py ├── DPSO_CVRP.py ├── DQPSO_CVRP.py ├── GA_CVRP.py ├── SA_CVRP.py └── TS_CVRP.py ├── LICENSE ├── README.md └── data └── cvrp.xlsx /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .nox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | .pytest_cache/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | db.sqlite3 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # IPython 77 | profile_default/ 78 | ipython_config.py 79 | 80 | # pyenv 81 | .python-version 82 | 83 | # celery beat schedule file 84 | celerybeat-schedule 85 | 86 | # SageMath parsed files 87 | *.sage.py 88 | 89 | # Environments 90 | .env 91 | .venv 92 | env/ 93 | venv/ 94 | ENV/ 95 | env.bak/ 96 | venv.bak/ 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | 105 | # mkdocs documentation 106 | /site 107 | 108 | # mypy 109 | .mypy_cache/ 110 | .dmypy.json 111 | dmypy.json 112 | 113 | # Pyre type checker 114 | .pyre/ 115 | -------------------------------------------------------------------------------- /Intelligent optimization algorithm/ACO_CVRP.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import math 3 | import random 4 | import numpy as np 5 | import copy 6 | import xlsxwriter 7 | import matplotlib.pyplot as plt 8 | class Sol(): 9 | def __init__(self): 10 | self.nodes_seq=None 11 | self.obj=None 12 | self.routes=None 13 | class Node(): 14 | def __init__(self): 15 | self.id=0 16 | self.name='' 17 | self.seq_no=0 18 | self.x_coord=0 19 | self.y_coord=0 20 | self.demand=0 21 | class Model(): 22 | def __init__(self): 23 | self.best_sol=None 24 | self.node_list=[] 25 | self.sol_list=[] 26 | self.node_seq_no_list=[] 27 | self.depot=None 28 | self.number_of_nodes=0 29 | self.opt_type=0 30 | self.vehicle_cap=0 31 | self.distance={} 32 | self.popsize=100 33 | self.alpha=2 34 | self.beta=3 35 | self.Q=100 36 | self.rho=0.5 37 | self.tau={} 38 | def readXlsxFile(filepath,model): 39 | node_seq_no = -1 40 | df = pd.read_excel(filepath) 41 | for i in range(df.shape[0]): 42 | node=Node() 43 | node.id=node_seq_no 44 | node.seq_no=node_seq_no 45 | node.x_coord= df['x_coord'][i] 46 | node.y_coord= df['y_coord'][i] 47 | node.demand=df['demand'][i] 48 | if df['demand'][i] == 0: 49 | model.depot=node 50 | else: 51 | model.node_list.append(node) 52 | model.node_seq_no_list.append(node_seq_no) 53 | try: 54 | node.name=df['name'][i] 55 | except: 56 | pass 57 | try: 58 | node.id=df['id'][i] 59 | except: 60 | pass 61 | node_seq_no=node_seq_no+1 62 | model.number_of_nodes=len(model.node_list) 63 | 64 | def initParam(model): 65 | for i in range(model.number_of_nodes): 66 | for j in range(i+1,model.number_of_nodes): 67 | d=math.sqrt((model.node_list[i].x_coord-model.node_list[j].x_coord)**2+ 68 | (model.node_list[i].y_coord-model.node_list[j].y_coord)**2) 69 | model.distance[i,j]=d 70 | model.distance[j,i]=d 71 | model.tau[i,j]=10 72 | model.tau[j,i]=10 73 | def movePosition(model): 74 | sol_list=[] 75 | local_sol=Sol() 76 | local_sol.obj=float('inf') 77 | for k in range(model.popsize): 78 | #Random ant position 79 | nodes_seq=[int(random.randint(0,model.number_of_nodes-1))] 80 | all_nodes_seq=copy.deepcopy(model.node_seq_no_list) 81 | all_nodes_seq.remove(nodes_seq[-1]) 82 | #Determine the next moving position according to pheromone 83 | while len(all_nodes_seq)>0: 84 | next_node_no=searchNextNode(model,nodes_seq[-1],all_nodes_seq) 85 | nodes_seq.append(next_node_no) 86 | all_nodes_seq.remove(next_node_no) 87 | sol=Sol() 88 | sol.nodes_seq=nodes_seq 89 | sol.obj,sol.routes=calObj(nodes_seq,model) 90 | sol_list.append(sol) 91 | if sol.obj 0).index(True)] 107 | return next_node_no 108 | def upateTau(model): 109 | rho=model.rho 110 | for k in model.tau.keys(): 111 | model.tau[k]=(1-rho)*model.tau[k] 112 | #update tau according to sol.nodes_seq(solution of TSP) 113 | for sol in model.sol_list: 114 | nodes_seq=sol.nodes_seq 115 | for i in range(len(nodes_seq)-1): 116 | from_node_no=nodes_seq[i] 117 | to_node_no=nodes_seq[i+1] 118 | model.tau[from_node_no,to_node_no]+=model.Q/sol.obj 119 | 120 | #update tau according to sol.routes(solution of CVRP) 121 | # for sol in model.sol_list: 122 | # routes=sol.routes 123 | # for route in routes: 124 | # for i in range(len(route)-1): 125 | # from_node_no=route[i] 126 | # to_node_no=route[i+1] 127 | # model.tau[from_node_no,to_node_no]+=model.Q/sol.obj 128 | 129 | def splitRoutes(nodes_seq,model): 130 | num_vehicle = 0 131 | vehicle_routes = [] 132 | route = [] 133 | remained_cap = model.vehicle_cap 134 | for node_no in nodes_seq: 135 | if remained_cap - model.node_list[node_no].demand >= 0: 136 | route.append(node_no) 137 | remained_cap = remained_cap - model.node_list[node_no].demand 138 | else: 139 | vehicle_routes.append(route) 140 | route = [node_no] 141 | num_vehicle = num_vehicle + 1 142 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 143 | vehicle_routes.append(route) 144 | return num_vehicle,vehicle_routes 145 | def calDistance(route,model): 146 | distance=0 147 | depot=model.depot 148 | for i in range(len(route)-1): 149 | from_node=model.node_list[route[i]] 150 | to_node=model.node_list[route[i+1]] 151 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 152 | first_node=model.node_list[route[0]] 153 | last_node=model.node_list[route[-1]] 154 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 155 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 156 | return distance 157 | def calObj(nodes_seq,model): 158 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 159 | if model.opt_type==0: 160 | return num_vehicle,vehicle_routes 161 | else: 162 | distance=0 163 | for route in vehicle_routes: 164 | distance+=calDistance(route,model) 165 | return distance,vehicle_routes 166 | def plotObj(obj_list): 167 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 168 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 169 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 170 | plt.xlabel('Iterations') 171 | plt.ylabel('Obj Value') 172 | plt.grid() 173 | plt.xlim(1,len(obj_list)+1) 174 | plt.show() 175 | def outPut(model): 176 | work=xlsxwriter.Workbook('result.xlsx') 177 | worksheet=work.add_worksheet() 178 | worksheet.write(0,0,'opt_type') 179 | worksheet.write(1,0,'obj') 180 | if model.opt_type==0: 181 | worksheet.write(0,1,'number of vehicles') 182 | else: 183 | worksheet.write(0, 1, 'drive distance of vehicles') 184 | worksheet.write(1,1,model.best_sol.obj) 185 | for row,route in enumerate(model.best_sol.routes): 186 | worksheet.write(row+2,0,'v'+str(row+1)) 187 | r=[str(i)for i in route] 188 | worksheet.write(row+2,1, '-'.join(r)) 189 | work.close() 190 | def run(filepath,Q,alpha,beta,rho,epochs,v_cap,opt_type,popsize): 191 | """ 192 | :param filepath:Xlsx file path 193 | :param Q:Total pheromone 194 | :param alpha:Information heuristic factor 195 | :param beta:Expected heuristic factor 196 | :param rho:Information volatilization factor 197 | :param epochs:Iterations 198 | :param v_cap:Vehicle capacity 199 | :param opt_type:Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 200 | :param popsize:Population size 201 | :return: 202 | """ 203 | model=Model() 204 | model.vehicle_cap=v_cap 205 | model.opt_type=opt_type 206 | model.alpha=alpha 207 | model.beta=beta 208 | model.Q=Q 209 | model.rho=rho 210 | model.popsize=popsize 211 | sol=Sol() 212 | sol.obj=float('inf') 213 | model.best_sol=sol 214 | history_best_obj = [] 215 | readXlsxFile(filepath,model) 216 | initParam(model) 217 | for ep in range(epochs): 218 | movePosition(model) 219 | upateTau(model) 220 | history_best_obj.append(model.best_sol.obj) 221 | print("%s/%s, best obj: %s" % (ep,epochs, model.best_sol.obj)) 222 | plotObj(history_best_obj) 223 | outPut(model) 224 | if __name__=='__main__': 225 | file='../data/cvrp.xlsx' 226 | run(filepath=file,Q=10,alpha=1,beta=5,rho=0.1,epochs=100,v_cap=60,opt_type=1,popsize=60) 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /Intelligent optimization algorithm/DE_CVRP.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import math 3 | import random 4 | import numpy as np 5 | import copy 6 | import xlsxwriter 7 | import matplotlib.pyplot as plt 8 | class Sol(): 9 | def __init__(self): 10 | self.nodes_seq=None 11 | self.obj=None 12 | self.routes=None 13 | class Node(): 14 | def __init__(self): 15 | self.id=0 16 | self.name='' 17 | self.seq_no=0 18 | self.x_coord=0 19 | self.y_coord=0 20 | self.demand=0 21 | class Model(): 22 | def __init__(self): 23 | self.best_sol=None 24 | self.node_list=[] 25 | self.sol_list=[] 26 | self.node_seq_no_list=[] 27 | self.depot=None 28 | self.number_of_nodes=0 29 | self.opt_type=0 30 | self.vehicle_cap=0 31 | self.Cr=0.5 32 | self.F=0.5 33 | self.popsize=4*self.number_of_nodes 34 | 35 | def readXlsxFile(filepath,model): 36 | # It is recommended that the vehicle depot data be placed in the first line of xlsx file 37 | node_seq_no =-1 #the depot node seq_no is -1,and demand node seq_no is 0,1,2,... 38 | df = pd.read_excel(filepath) 39 | for i in range(df.shape[0]): 40 | node=Node() 41 | node.id=node_seq_no 42 | node.seq_no=node_seq_no 43 | node.x_coord= df['x_coord'][i] 44 | node.y_coord= df['y_coord'][i] 45 | node.demand=df['demand'][i] 46 | if df['demand'][i] == 0: 47 | model.depot=node 48 | else: 49 | model.node_list.append(node) 50 | model.node_seq_no_list.append(node_seq_no) 51 | try: 52 | node.name=df['name'][i] 53 | except: 54 | pass 55 | try: 56 | node.id=df['id'][i] 57 | except: 58 | pass 59 | node_seq_no=node_seq_no+1 60 | model.number_of_nodes=len(model.node_list) 61 | def genInitialSol(model): 62 | nodes_seq=copy.deepcopy(model.node_seq_no_list) 63 | for i in range(model.popsize): 64 | seed=int(random.randint(0,10)) 65 | random.seed(seed) 66 | random.shuffle(nodes_seq) 67 | sol=Sol() 68 | sol.nodes_seq=copy.deepcopy(nodes_seq) 69 | sol.obj,sol.routes=calObj(nodes_seq,model) 70 | model.sol_list.append(sol) 71 | if sol.obj= 0: 81 | route.append(node_no) 82 | remained_cap = remained_cap - model.node_list[node_no].demand 83 | else: 84 | vehicle_routes.append(route) 85 | route = [node_no] 86 | num_vehicle = num_vehicle + 1 87 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 88 | vehicle_routes.append(route) 89 | return num_vehicle,vehicle_routes 90 | def calDistance(route,model): 91 | distance=0 92 | depot=model.depot 93 | for i in range(len(route)-1): 94 | from_node=model.node_list[route[i]] 95 | to_node=model.node_list[route[i+1]] 96 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 97 | first_node=model.node_list[route[0]] 98 | last_node=model.node_list[route[-1]] 99 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 100 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 101 | return distance 102 | def calObj(nodes_seq,model): 103 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 104 | if model.opt_type==0: 105 | return num_vehicle,vehicle_routes 106 | else: 107 | distance=0 108 | for route in vehicle_routes: 109 | distance+=calDistance(route,model) 110 | return distance,vehicle_routes 111 | def adjustRoutes(nodes_seq,model): 112 | all_node_list=copy.deepcopy(model.node_seq_no_list) 113 | repeat_node=[] 114 | for id,node_no in enumerate(nodes_seq): 115 | if node_no in all_node_list: 116 | all_node_list.remove(node_no) 117 | else: 118 | repeat_node.append(id) 119 | for i in range(len(repeat_node)): 120 | nodes_seq[repeat_node[i]]=all_node_list[i] 121 | return nodes_seq 122 | #Differential mutation; mutation strategies: DE/rand/1/bin 123 | def muSol(model,v1): 124 | x1=model.sol_list[v1].nodes_seq 125 | while True: 126 | v2=random.randint(0,model.number_of_nodes-1) 127 | if v2!=v1: 128 | break 129 | while True: 130 | v3=random.randint(0,model.number_of_nodes-1) 131 | if v3!=v2 and v3!=v1: 132 | break 133 | x2=model.sol_list[v2].nodes_seq 134 | x3=model.sol_list[v3].nodes_seq 135 | mu_x=[min(int(x1[i]+model.F*(x2[i]-x3[i])),model.number_of_nodes-1) for i in range(model.number_of_nodes) ] 136 | return mu_x 137 | #Differential Crossover 138 | def crossSol(model,vx,vy): 139 | cro_x=[] 140 | for i in range(model.number_of_nodes): 141 | if random.random()0: 99 | new_v.append(min(v_,model.Vmax)) 100 | else: 101 | new_v.append(max(v_,-model.Vmax)) 102 | new_x=[min(int(x[i]+new_v[i]),model.number_of_nodes-1) for i in range(model.number_of_nodes) ] 103 | new_x=adjustRoutes(new_x,model) 104 | model.v[id]=new_v 105 | 106 | new_x_obj,new_x_routes=calObj(new_x,model) 107 | if new_x_obj= 0: 136 | route.append(node_no) 137 | remained_cap = remained_cap - model.node_list[node_no].demand 138 | else: 139 | vehicle_routes.append(route) 140 | route = [node_no] 141 | num_vehicle = num_vehicle + 1 142 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 143 | vehicle_routes.append(route) 144 | return num_vehicle,vehicle_routes 145 | def calDistance(route,model): 146 | distance=0 147 | depot=model.depot 148 | for i in range(len(route)-1): 149 | from_node=model.node_list[route[i]] 150 | to_node=model.node_list[route[i+1]] 151 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 152 | first_node=model.node_list[route[0]] 153 | last_node=model.node_list[route[-1]] 154 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 155 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 156 | return distance 157 | def calObj(nodes_seq,model): 158 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 159 | if model.opt_type==0: 160 | return num_vehicle,vehicle_routes 161 | else: 162 | distance=0 163 | for route in vehicle_routes: 164 | distance+=calDistance(route,model) 165 | return distance,vehicle_routes 166 | def plotObj(obj_list): 167 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 168 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 169 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 170 | plt.xlabel('Iterations') 171 | plt.ylabel('Obj Value') 172 | plt.grid() 173 | plt.xlim(1,len(obj_list)+1) 174 | plt.show() 175 | def outPut(model): 176 | work=xlsxwriter.Workbook('result.xlsx') 177 | worksheet=work.add_worksheet() 178 | worksheet.write(0,0,'opt_type') 179 | worksheet.write(1,0,'obj') 180 | if model.opt_type==0: 181 | worksheet.write(0,1,'number of vehicles') 182 | else: 183 | worksheet.write(0, 1, 'drive distance of vehicles') 184 | worksheet.write(1,1,model.best_sol.obj) 185 | for row,route in enumerate(model.best_sol.routes): 186 | worksheet.write(row+2,0,'v'+str(row+1)) 187 | r=[str(i)for i in route] 188 | worksheet.write(row+2,1, '-'.join(r)) 189 | work.close() 190 | def run(filepath,epochs,popsize,Vmax,v_cap,opt_type,w,c1,c2): 191 | """ 192 | :param filepath: Xlsx file path 193 | :param epochs: Iterations 194 | :param popsize: Population size 195 | :param v_cap: Vehicle capacity 196 | :param Vmax: Max speed 197 | :param opt_type: Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 198 | :param w: Inertia weight 199 | :param c1:Learning factors 200 | :param c2:Learning factors 201 | :return: 202 | """ 203 | model=Model() 204 | model.vehicle_cap=v_cap 205 | model.opt_type=opt_type 206 | model.w=w 207 | model.c1=c1 208 | model.c2=c2 209 | model.Vmax = Vmax 210 | readXlsxFile(filepath,model) 211 | history_best_obj=[] 212 | genInitialSol(model,popsize) 213 | history_best_obj.append(model.best_sol.obj) 214 | for ep in range(epochs): 215 | updatePosition(model) 216 | history_best_obj.append(model.best_sol.obj) 217 | print("%s/%s: best obj: %s"%(ep,epochs,model.best_sol.obj)) 218 | plotObj(history_best_obj) 219 | outPut(model) 220 | if __name__=='__main__': 221 | file='../data/cvrp.xlsx' 222 | run(filepath=file,epochs=100,popsize=150,Vmax=2,v_cap=70,opt_type=1,w=0.9,c1=1,c2=5) 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /Intelligent optimization algorithm/DQPSO_CVRP.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import math 3 | import random 4 | import numpy as np 5 | import copy 6 | import xlsxwriter 7 | import matplotlib.pyplot as plt 8 | class Sol(): 9 | def __init__(self): 10 | self.nodes_seq=None 11 | self.obj=None 12 | self.routes=None 13 | class Node(): 14 | def __init__(self): 15 | self.id=0 16 | self.name='' 17 | self.seq_no=0 18 | self.x_coord=0 19 | self.y_coord=0 20 | self.demand=0 21 | class Model(): 22 | def __init__(self): 23 | self.sol_list=[] 24 | self.best_sol=None 25 | self.node_list=[] 26 | self.node_seq_no_list=[] 27 | self.depot=None 28 | self.number_of_nodes=0 29 | self.opt_type=0 30 | self.vehicle_cap=0 31 | self.popsize=100 32 | self.pl=[] 33 | self.pg=None 34 | self.mg=None 35 | self.alpha=1.0 36 | def readXlsxFile(filepath,model): 37 | # It is recommended that the vehicle depot data be placed in the first line of xlsx file 38 | node_seq_no = -1 #the depot node seq_no is -1,and demand node seq_no is 0,1,2,... 39 | df = pd.read_excel(filepath) 40 | for i in range(df.shape[0]): 41 | node=Node() 42 | node.id=node_seq_no 43 | node.seq_no=node_seq_no 44 | node.x_coord= df['x_coord'][i] 45 | node.y_coord= df['y_coord'][i] 46 | node.demand=df['demand'][i] 47 | if df['demand'][i] == 0: 48 | model.depot=node 49 | else: 50 | model.node_list.append(node) 51 | model.node_seq_no_list.append(node_seq_no) 52 | try: 53 | node.name=df['name'][i] 54 | except: 55 | pass 56 | try: 57 | node.id=df['id'][i] 58 | except: 59 | pass 60 | node_seq_no=node_seq_no+1 61 | model.number_of_nodes=len(model.node_list) 62 | def genInitialSol(model): 63 | node_seq=copy.deepcopy(model.node_seq_no_list) 64 | best_sol=Sol() 65 | best_sol.obj=float('inf') 66 | mg=[0]*model.number_of_nodes 67 | for i in range(model.popsize): 68 | seed = int(random.randint(0, 10)) 69 | random.seed(seed) 70 | random.shuffle(node_seq) 71 | sol=Sol() 72 | sol.nodes_seq= copy.deepcopy(node_seq) 73 | sol.obj,sol.routes=calObj(sol.nodes_seq,model) 74 | model.sol_list.append(sol) 75 | #init the optimal position of each particle 76 | model.pl.append(sol.nodes_seq) 77 | #init the average optimal position of particle population 78 | mg=[mg[k]+node_seq[k]/model.popsize for k in range(model.number_of_nodes)] 79 | #init the optimal position of particle population 80 | if sol.obj= 0: 141 | route.append(node_no) 142 | remained_cap = remained_cap - model.node_list[node_no].demand 143 | else: 144 | vehicle_routes.append(route) 145 | route = [node_no] 146 | num_vehicle = num_vehicle + 1 147 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 148 | vehicle_routes.append(route) 149 | return num_vehicle,vehicle_routes 150 | def calDistance(route,model): 151 | distance=0 152 | depot=model.depot 153 | for i in range(len(route)-1): 154 | from_node=model.node_list[route[i]] 155 | to_node=model.node_list[route[i+1]] 156 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 157 | first_node=model.node_list[route[0]] 158 | last_node=model.node_list[route[-1]] 159 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 160 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 161 | return distance 162 | def calObj(nodes_seq,model): 163 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 164 | if model.opt_type==0: 165 | return num_vehicle,vehicle_routes 166 | else: 167 | distance=0 168 | for route in vehicle_routes: 169 | distance+=calDistance(route,model) 170 | return distance,vehicle_routes 171 | 172 | def plotObj(obj_list): 173 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 174 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 175 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 176 | plt.xlabel('Iterations') 177 | plt.ylabel('Obj Value') 178 | plt.grid() 179 | plt.xlim(1,len(obj_list)+1) 180 | plt.show() 181 | def outPut(model): 182 | work=xlsxwriter.Workbook('result.xlsx') 183 | worksheet=work.add_worksheet() 184 | worksheet.write(0,0,'opt_type') 185 | worksheet.write(1,0,'obj') 186 | if model.opt_type==0: 187 | worksheet.write(0,1,'number of vehicles') 188 | else: 189 | worksheet.write(0, 1, 'drive distance of vehicles') 190 | worksheet.write(1,1,model.best_sol.obj) 191 | for row,route in enumerate(model.best_sol.routes): 192 | worksheet.write(row+2,0,'v'+str(row+1)) 193 | r=[str(i)for i in route] 194 | worksheet.write(row+2,1, '-'.join(r)) 195 | work.close() 196 | def run(filepath,epochs,popsize,alpha,v_cap,opt_type): 197 | """ 198 | :param filepath: Xlsx file path 199 | :type str 200 | :param epochs:Iterations 201 | :type int 202 | :param popsize:Population size 203 | :type int 204 | :param alpha:Innovation(Control) parameters,(0,1] 205 | :type float, 206 | :param v_cap:Vehicle capacity 207 | :type float 208 | :param opt_type:Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 209 | :type int,0 or 1 210 | :return: 211 | """ 212 | model=Model() 213 | model.vehicle_cap=v_cap 214 | model.opt_type=opt_type 215 | model.alpha=alpha 216 | model.popsize=popsize 217 | readXlsxFile(filepath,model) 218 | history_best_obj=[] 219 | genInitialSol(model) 220 | history_best_obj.append(model.best_sol.obj) 221 | for ep in range(epochs): 222 | updatePosition(model) 223 | history_best_obj.append(model.best_sol.obj) 224 | print("%s/%s: best obj: %s"%(ep,epochs,model.best_sol.obj)) 225 | plotObj(history_best_obj) 226 | outPut(model) 227 | if __name__=='__main__': 228 | file='../data/cvrp.xlsx' 229 | run(filepath=file,epochs=300,popsize=150,alpha=0.8,v_cap=80,opt_type=1) 230 | -------------------------------------------------------------------------------- /Intelligent optimization algorithm/GA_CVRP.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import math 3 | import random 4 | import numpy as np 5 | import copy 6 | import xlsxwriter 7 | import matplotlib.pyplot as plt 8 | class Sol(): 9 | def __init__(self): 10 | self.nodes_seq=None 11 | self.obj=None 12 | self.fit=None 13 | self.routes=None 14 | class Node(): 15 | def __init__(self): 16 | self.id=0 17 | self.name='' 18 | self.seq_no=0 19 | self.x_coord=0 20 | self.y_coord=0 21 | self.demand=0 22 | class Model(): 23 | def __init__(self): 24 | self.best_sol=None 25 | self.node_list=[] 26 | self.sol_list=[] 27 | self.node_seq_no_list=[] 28 | self.depot=None 29 | self.number_of_nodes=0 30 | self.opt_type=0 31 | self.vehicle_cap=0 32 | self.pc=0.5 33 | self.pm=0.2 34 | self.n_select=80 35 | self.popsize=100 36 | 37 | def readXlsxFile(filepath,model): 38 | #It is recommended that the vehicle depot data be placed in the first line of xlsx file 39 | node_seq_no =-1 #the depot node seq_no is -1,and demand node seq_no is 0,1,2,... 40 | df = pd.read_excel(filepath) 41 | for i in range(df.shape[0]): 42 | node=Node() 43 | node.id=node_seq_no 44 | node.seq_no=node_seq_no 45 | node.x_coord= df['x_coord'][i] 46 | node.y_coord= df['y_coord'][i] 47 | node.demand=df['demand'][i] 48 | if df['demand'][i] == 0: 49 | model.depot=node 50 | else: 51 | model.node_list.append(node) 52 | model.node_seq_no_list.append(node_seq_no) 53 | try: 54 | node.name=df['name'][i] 55 | except: 56 | pass 57 | try: 58 | node.id=df['id'][i] 59 | except: 60 | pass 61 | node_seq_no=node_seq_no+1 62 | model.number_of_nodes=len(model.node_list) 63 | def genInitialSol(model): 64 | nodes_seq=copy.deepcopy(model.node_seq_no_list) 65 | for i in range(model.popsize): 66 | seed=int(random.randint(0,10)) 67 | random.seed(seed) 68 | random.shuffle(nodes_seq) 69 | sol=Sol() 70 | sol.nodes_seq=copy.deepcopy(nodes_seq) 71 | model.sol_list.append(sol) 72 | 73 | def splitRoutes(nodes_seq,model): 74 | num_vehicle = 0 75 | vehicle_routes = [] 76 | route = [] 77 | remained_cap = model.vehicle_cap 78 | for node_no in nodes_seq: 79 | if remained_cap - model.node_list[node_no].demand >= 0: 80 | route.append(node_no) 81 | remained_cap = remained_cap - model.node_list[node_no].demand 82 | else: 83 | vehicle_routes.append(route) 84 | route = [node_no] 85 | num_vehicle = num_vehicle + 1 86 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 87 | vehicle_routes.append(route) 88 | return num_vehicle,vehicle_routes 89 | def calDistance(route,model): 90 | distance=0 91 | depot=model.depot 92 | for i in range(len(route)-1): 93 | from_node=model.node_list[route[i]] 94 | to_node=model.node_list[route[i+1]] 95 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 96 | first_node=model.node_list[route[0]] 97 | last_node=model.node_list[route[-1]] 98 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 99 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 100 | return distance 101 | def calFit(model): 102 | #calculate fit value:fit=Objmax-obj 103 | Objmax=-float('inf') 104 | best_sol=Sol()#record the local best solution 105 | best_sol.obj=float('inf') 106 | #计算目标函数 107 | for sol in model.sol_list: 108 | nodes_seq=sol.nodes_seq 109 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 110 | if model.opt_type==0: 111 | sol.obj=num_vehicle 112 | sol.routes=vehicle_routes 113 | if sol.obj>Objmax: 114 | Objmax=sol.obj 115 | if sol.objObjmax: 124 | Objmax=sol.obj 125 | if sol.obj < best_sol.obj: 126 | best_sol = copy.deepcopy(sol) 127 | #calculate fit value 128 | for sol in model.sol_list: 129 | sol.fit=Objmax-sol.obj 130 | #update the global best solution 131 | if best_sol.objmodel.popsize: 190 | break 191 | #mutation 192 | def muSol(model): 193 | sol_list=copy.deepcopy(model.sol_list) 194 | model.sol_list=[] 195 | while True: 196 | if random.random()<=model.pm: 197 | f1_index = int(random.randint(0, len(sol_list) - 1)) 198 | f1 = copy.deepcopy(sol_list[f1_index]) 199 | m1_index=random.randint(0,model.number_of_nodes-1) 200 | m2_index=random.randint(0,model.number_of_nodes-1) 201 | if m1_index!=m2_index: 202 | node1=f1.nodes_seq[m1_index] 203 | f1.nodes_seq[m1_index]=f1.nodes_seq[m2_index] 204 | f1.nodes_seq[m2_index]=node1 205 | model.sol_list.append(copy.deepcopy(f1)) 206 | if len(model.sol_list)>model.popsize: 207 | break 208 | def plotObj(obj_list): 209 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 210 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 211 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 212 | plt.xlabel('Iterations') 213 | plt.ylabel('Obj Value') 214 | plt.grid() 215 | plt.xlim(1,len(obj_list)+1) 216 | plt.show() 217 | def outPut(model): 218 | work=xlsxwriter.Workbook('result.xlsx') 219 | worksheet=work.add_worksheet() 220 | worksheet.write(0,0,'opt_type') 221 | worksheet.write(1,0,'obj') 222 | if model.opt_type==0: 223 | worksheet.write(0,1,'number of vehicles') 224 | else: 225 | worksheet.write(0, 1, 'drive distance of vehicles') 226 | worksheet.write(1,1,model.best_sol.obj) 227 | for row,route in enumerate(model.best_sol.routes): 228 | worksheet.write(row+2,0,'v'+str(row+1)) 229 | r=[str(i)for i in route] 230 | worksheet.write(row+2,1, '-'.join(r)) 231 | work.close() 232 | 233 | 234 | def run(filepath,epochs,pc,pm,popsize,n_select,v_cap,opt_type): 235 | """ 236 | :param filepath:Xlsx file path 237 | :param epochs:Iterations 238 | :param pc:Crossover probability 239 | :param pm:Mutation probability 240 | :param popsize:Population size 241 | :param n_select:Number of excellent individuals selected 242 | :param v_cap:Vehicle capacity 243 | :param opt_type:Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 244 | :return: 245 | """ 246 | model=Model() 247 | model.vehicle_cap=v_cap 248 | model.opt_type=opt_type 249 | model.pc=pc 250 | model.pm=pm 251 | model.popsize=popsize 252 | model.n_select=n_select 253 | 254 | readXlsxFile(filepath,model) 255 | genInitialSol(model) 256 | history_best_obj = [] 257 | best_sol=Sol() 258 | best_sol.obj=float('inf') 259 | model.best_sol=best_sol 260 | for ep in range(epochs): 261 | calFit(model) 262 | selectSol(model) 263 | crossSol(model) 264 | muSol(model) 265 | history_best_obj.append(model.best_sol.obj) 266 | print("%s/%s, best obj: %s" % (ep,epochs,model.best_sol.obj)) 267 | plotObj(history_best_obj) 268 | outPut(model) 269 | if __name__=='__main__': 270 | file='../data/cvrp.xlsx' 271 | run(filepath=file,epochs=150,pc=0.6,pm=0.2,popsize=100,n_select=80,v_cap=80,opt_type=1) 272 | -------------------------------------------------------------------------------- /Intelligent optimization algorithm/SA_CVRP.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import math 3 | import random 4 | import numpy as np 5 | import copy 6 | import xlsxwriter 7 | import matplotlib.pyplot as plt 8 | class Sol(): 9 | def __init__(self): 10 | self.nodes_seq=None 11 | self.obj=None 12 | self.routes=None 13 | class Node(): 14 | def __init__(self): 15 | self.id=0 16 | self.name='' 17 | self.seq_no=0 18 | self.x_coord=0 19 | self.y_coord=0 20 | self.demand=0 21 | class Model(): 22 | def __init__(self): 23 | self.best_sol=None 24 | self.node_list=[] 25 | self.node_seq_no_list=[] 26 | self.depot=None 27 | self.number_of_nodes=0 28 | self.opt_type=0 29 | self.vehicle_cap=0 30 | 31 | def readXlsxFile(filepath,model): 32 | # It is recommended that the vehicle depot data be placed in the first line of xlsx file 33 | node_seq_no = -1#the depot node seq_no is -1,and demand node seq_no is 0,1,2,... 34 | df = pd.read_excel(filepath) 35 | for i in range(df.shape[0]): 36 | node=Node() 37 | node.id=node_seq_no 38 | node.seq_no=node_seq_no 39 | node.x_coord= df['x_coord'][i] 40 | node.y_coord= df['y_coord'][i] 41 | node.demand=df['demand'][i] 42 | if df['demand'][i] == 0: 43 | model.depot=node 44 | else: 45 | model.node_list.append(node) 46 | model.node_seq_no_list.append(node_seq_no) 47 | try: 48 | node.name=df['name'][i] 49 | except: 50 | pass 51 | try: 52 | node.id=df['id'][i] 53 | except: 54 | pass 55 | node_seq_no=node_seq_no+1 56 | model.number_of_nodes=len(model.node_list) 57 | 58 | def genInitialSol(node_seq): 59 | node_seq=copy.deepcopy(node_seq) 60 | random.seed(0) 61 | random.shuffle(node_seq) 62 | return node_seq 63 | def createActions(n): 64 | action_list=[] 65 | nswap=n//2 66 | # Single point exchange 67 | for i in range(nswap): 68 | action_list.append([1, i, i + nswap]) 69 | # Two point exchange 70 | for i in range(0, nswap, 2): 71 | action_list.append([2, i, i + nswap]) 72 | # Reverse sequence 73 | for i in range(0, n, 4): 74 | action_list.append([3, i, i + 3]) 75 | return action_list 76 | def doACtion(nodes_seq,action): 77 | nodes_seq=copy.deepcopy(nodes_seq) 78 | if action[0]==1: 79 | index_1=action[1] 80 | index_2=action[2] 81 | temporary=nodes_seq[index_1] 82 | nodes_seq[index_1]=nodes_seq[index_2] 83 | nodes_seq[index_2]=temporary 84 | return nodes_seq 85 | elif action[0]==2: 86 | index_1 = action[1] 87 | index_2 = action[2] 88 | temporary=[nodes_seq[index_1],nodes_seq[index_1+1]] 89 | nodes_seq[index_1]=nodes_seq[index_2] 90 | nodes_seq[index_1+1]=nodes_seq[index_2+1] 91 | nodes_seq[index_2]=temporary[0] 92 | nodes_seq[index_2+1]=temporary[1] 93 | return nodes_seq 94 | elif action[0]==3: 95 | index_1=action[1] 96 | index_2=action[2] 97 | nodes_seq[index_1:index_2+1]=list(reversed(nodes_seq[index_1:index_2+1])) 98 | return nodes_seq 99 | def splitRoutes(nodes_seq,model): 100 | num_vehicle = 0 101 | vehicle_routes = [] 102 | route = [] 103 | remained_cap = model.vehicle_cap 104 | for node_no in nodes_seq: 105 | if remained_cap - model.node_list[node_no].demand >= 0: 106 | route.append(node_no) 107 | remained_cap = remained_cap - model.node_list[node_no].demand 108 | else: 109 | vehicle_routes.append(route) 110 | route = [node_no] 111 | num_vehicle = num_vehicle + 1 112 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 113 | vehicle_routes.append(route) 114 | return num_vehicle,vehicle_routes 115 | def calDistance(route,model): 116 | distance=0 117 | depot=model.depot 118 | for i in range(len(route)-1): 119 | from_node=model.node_list[route[i]] 120 | to_node=model.node_list[route[i+1]] 121 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 122 | first_node=model.node_list[route[0]] 123 | last_node=model.node_list[route[-1]] 124 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 125 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 126 | return distance 127 | def calObj(nodes_seq,model): 128 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 129 | if model.opt_type==0: 130 | return num_vehicle,vehicle_routes 131 | else: 132 | distance=0 133 | for route in vehicle_routes: 134 | distance+=calDistance(route,model) 135 | return distance,vehicle_routes 136 | def plotObj(obj_list): 137 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 138 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 139 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 140 | plt.xlabel('Iterations') 141 | plt.ylabel('Obj Value') 142 | plt.grid() 143 | plt.xlim(1,len(obj_list)+1) 144 | plt.show() 145 | def outPut(model): 146 | work = xlsxwriter.Workbook('result.xlsx') 147 | worksheet = work.add_worksheet() 148 | worksheet.write(0, 0, 'opt_type') 149 | worksheet.write(1, 0, 'obj') 150 | if model.opt_type == 0: 151 | worksheet.write(0, 1, 'number of vehicles') 152 | else: 153 | worksheet.write(0, 1, 'drive distance of vehicles') 154 | worksheet.write(1, 1, model.best_sol.obj) 155 | for row, route in enumerate(model.best_sol.routes): 156 | worksheet.write(row + 2, 0, 'v' + str(row + 1)) 157 | r = [str(i) for i in route] 158 | worksheet.write(row + 2, 1, '-'.join(r)) 159 | work.close() 160 | def run(filepath,T0,Tf,detaT,v_cap,opt_type): 161 | """ 162 | :param filepath: Xlsx file path 163 | :param T0: Initial temperature 164 | :param Tf: Termination temperature 165 | :param deltaT: Step or proportion of temperature drop 166 | :param v_cap: Vehicle capacity 167 | :param opt_type: Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 168 | :return: 169 | """ 170 | model=Model() 171 | model.vehicle_cap=v_cap 172 | model.opt_type=opt_type 173 | readXlsxFile(filepath,model) 174 | action_list=createActions(model.number_of_nodes) 175 | history_best_obj=[] 176 | sol=Sol() 177 | sol.nodes_seq=genInitialSol(model.node_seq_no_list) 178 | sol.obj,sol.routes=calObj(sol.nodes_seq,model) 179 | model.best_sol=copy.deepcopy(sol) 180 | history_best_obj.append(sol.obj) 181 | Tk=T0 182 | nTk=len(action_list) 183 | while Tk>=Tf: 184 | for i in range(nTk): 185 | new_sol = Sol() 186 | new_sol.nodes_seq = doACtion(sol.nodes_seq, action_list[i]) 187 | new_sol.obj, new_sol.routes = calObj(new_sol.nodes_seq, model) 188 | deta_f=new_sol.obj-sol.obj 189 | #New interpretation of acceptance criteria 190 | if deta_f<0 or math.exp(-deta_f/Tk)>random.random(): 191 | sol=copy.deepcopy(new_sol) 192 | if sol.obj= 0: 108 | route.append(node_no) 109 | remained_cap = remained_cap - model.node_list[node_no].demand 110 | else: 111 | vehicle_routes.append(route) 112 | route = [node_no] 113 | num_vehicle = num_vehicle + 1 114 | remained_cap =model.vehicle_cap - model.node_list[node_no].demand 115 | vehicle_routes.append(route) 116 | return num_vehicle,vehicle_routes 117 | def calDistance(route,model): 118 | distance=0 119 | depot=model.depot 120 | for i in range(len(route)-1): 121 | from_node=model.node_list[route[i]] 122 | to_node=model.node_list[route[i+1]] 123 | distance+=math.sqrt((from_node.x_coord-to_node.x_coord)**2+(from_node.y_coord-to_node.y_coord)**2) 124 | first_node=model.node_list[route[0]] 125 | last_node=model.node_list[route[-1]] 126 | distance+=math.sqrt((depot.x_coord-first_node.x_coord)**2+(depot.y_coord-first_node.y_coord)**2) 127 | distance+=math.sqrt((depot.x_coord-last_node.x_coord)**2+(depot.y_coord - last_node.y_coord)**2) 128 | return distance 129 | def calObj(nodes_seq,model): 130 | # calculate obj value 131 | num_vehicle, vehicle_routes = splitRoutes(nodes_seq, model) 132 | if model.opt_type==0: 133 | return num_vehicle,vehicle_routes 134 | else: 135 | distance=0 136 | for route in vehicle_routes: 137 | distance+=calDistance(route,model) 138 | return distance,vehicle_routes 139 | def plotObj(obj_list): 140 | plt.rcParams['font.sans-serif'] = ['SimHei'] #show chinese 141 | plt.rcParams['axes.unicode_minus'] = False # Show minus sign 142 | plt.plot(np.arange(1,len(obj_list)+1),obj_list) 143 | plt.xlabel('Iterations') 144 | plt.ylabel('Obj Value') 145 | plt.grid() 146 | plt.xlim(1,len(obj_list)+1) 147 | plt.show() 148 | def outPut(model): 149 | work = xlsxwriter.Workbook('result.xlsx') 150 | worksheet = work.add_worksheet() 151 | worksheet.write(0, 0, 'opt_type') 152 | worksheet.write(1, 0, 'obj') 153 | if model.opt_type == 0: 154 | worksheet.write(0, 1, 'number of vehicles') 155 | else: 156 | worksheet.write(0, 1, 'drive distance of vehicles') 157 | worksheet.write(1, 1, model.best_sol.obj) 158 | for row, route in enumerate(model.best_sol.routes): 159 | worksheet.write(row + 2, 0, 'v' + str(row + 1)) 160 | r = [str(i) for i in route] 161 | worksheet.write(row + 2, 1, '-'.join(r)) 162 | work.close() 163 | def run(filepath,epochs,v_cap,opt_type): 164 | """ 165 | :param filepath: :Xlsx file path 166 | :param epochs: Iterations 167 | :param v_cap: Vehicle capacity 168 | :param opt_type:Optimization type:0:Minimize the number of vehicles,1:Minimize travel distance 169 | :return: 无 170 | """ 171 | model=Model() 172 | model.vehicle_cap=v_cap 173 | model.opt_type=opt_type 174 | readXlsxFile(filepath,model) 175 | action_list=createActions(model.number_of_nodes) 176 | model.tabu_list=np.zeros(len(action_list)) 177 | history_best_obj=[] 178 | sol=Sol() 179 | sol.nodes_seq=genInitialSol(model.node_seq_no_list) 180 | sol.obj,sol.routes=calObj(sol.nodes_seq,model) 181 | model.best_sol=copy.deepcopy(sol) 182 | history_best_obj.append(sol.obj) 183 | for ep in range(epochs): 184 | local_new_sol=Sol() 185 | local_new_sol.obj=float('inf') 186 | for i in range(len(action_list)): 187 | if model.tabu_list[i]==0: 188 | new_sol=Sol() 189 | new_sol.nodes_seq=doACtion(sol.nodes_seq,action_list[i]) 190 | new_sol.obj,new_sol.routes=calObj(new_sol.nodes_seq,model) 191 | new_sol.action_id=i 192 | if new_sol.obj 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms_for_solving_VRP 2 | -------------------------------------------------------------------------------- /data/cvrp.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangchb/Algorithms_for_solving_VRP/dcc49c72ab792dfb4acce31b1add6f43375f9fb8/data/cvrp.xlsx --------------------------------------------------------------------------------