!pip install geopandas
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from geopy.geocoders import Nominatim
from geopy import distance
import folium
from folium import features
'''clientes = ["Av. Vitacura 6195, Vitacura",
"Av. Las Condes 11931, Las Condes",
"Av. Vitacura 5951, Vitacura",
"Luis Pasteur 5419, Vitacura",
"Av. Manquehue 1499, Vitacura",
"Av Santa Maria 7030 , Vitacura, Chile",
"Av. Vitacura 5648, Vitacura",
"Av. Las Tranqueras 1327, Vitacura",
"Av. Vitacura 9019, Vitacura",
"Av. Vitacura 6980, Vitacura",
"Av. Vitacura, 6805,Vitacura",
"Av. Padre Hurtado 1382, Vitacura",
"Av. Luis Pasteur 6500 , Vitacura"]'''
clientes = ['Av. Vitacura 6195, Vitacura',
'Av. Las Condes 11931, Las Condes',
'Av. Vitacura 5951, Vitacura',
'Luis Pasteur 5419, Vitacura',
'Av. Manquehue 1499, Vitacura',
'Av Santa Maria 7030 , Vitacura, Chile',
'Av. Vitacura 5648, Vitacura',
'Av. Las Tranqueras 1327, Vitacura',
'Av. Vitacura 9019, Vitacura',
'Av. Vitacura 6980, Vitacura',
'Av. Vitacura, 6805,Vitacura',
'Av. Padre Hurtado 1382, Vitacura',
'Av. Luis Pasteur 6500 , Vitacura']
df = pd.DataFrame(clientes,
columns=['direccion'])
geolocator = Nominatim()
df['Coordenadas'] = df['direccion'].apply(geolocator.geocode)
df['Latitud, logitud'] = df['Coordenadas'].apply(lambda x: (x.latitude, x.longitude))
df['x'] = df['Coordenadas'].apply(lambda x: (x.latitude))
df['y'] = df['Coordenadas'].apply(lambda x: (x.longitude))
df
n=len(clientes)-1
nodos=[i for i in range(n)]
plt.figure(figsize=(5,5))
x = df.loc[n][3]
y = df.loc[n][4]
plt.scatter(x,y)
for n in range(len(nodos)):
plt.scatter(df.loc[n][3], df.loc[n][4], c= 'Red', marker = 'o')
plt.annotate(str(nodos[n]),xy=(df.loc[n][3], df.loc[n][4]),color="Blue")
plt.xlabel("Coord X",fontsize=16)
plt.ylabel("Coord Y",fontsize=16)
plt.title("Plot TSP",fontsize=16)
plt.show()
distancia_nodo=[]
for n in range(len(df)):
distancia = []
for i in range (len(df)):
distancia.append(np.around(distance.distance(df.iloc[n][2], df.iloc[i][2]).km, decimals=1))
distancia_nodo.append(distancia)
distancia_nodo
Data1 = pd.DataFrame(distancia_nodo,
columns = df['direccion'],
index = df['direccion'])
#Data1 = Data1*1000
Data1 = Data1.astype(float)
#Data1 = Data1.astype(int)
#print(Data1.info())
Data1
distancia_nodo=[]
for n in range(len(df)):
distancia = []
for i in range (len(df)):
distancia.append(np.around(distance.distance(df.iloc[n][2], df.iloc[i][2]).km, decimals=1))
distancia_nodo.append(distancia)
distancia_nodo
Data1 = pd.DataFrame(distancia_nodo)
#Data1 = Data1*1000
Data1 = Data1.astype(float)
#Data1 = Data1.astype(int)
#print(Data1.info())
sales_record=Data1
# Specify the name of the excel file
file_name = 'ProductSales_sheet.xlsx'
# saving the excelsheet
sales_record.to_excel(file_name)
print('Sales record successfully exported into Excel File')
print(Data1.info())
Data1 = pd.DataFrame(distancia_nodo,
columns= df['direccion'],
index= df['direccion'])
#"A","B","C","D","E","F","G","H","I","K","L","N","M"
# Esta solucion tiene que ser la arrojele vecino mas cercano o cualquier heuristica de contruccion
X0 = clientes
Distances = [] # The OF of the initial solution
t = 0
for i in range(len(X0)-1):
X1 = Data1.loc[X0[t],X0[t+1]] # se visita cada cliente y el siguiente
Distances.append(X1) # agregar distnacias
t = t+1
Length_of_Travel = sum(Distances) # Add up the distances
print("Length_of_Travel:",Length_of_Travel)
#PARAMETROS
T0 = 50 #Temperatura 3000
M = 10 #1000
N = 5 #50
Alpha = 0.50 #0.85
# estos son para para la grafica y ver como se comporta el algoritmo
Temp = []
Min_Distance = []
Ran1 = np.random.randint(0,len(X0))
Ran2 = np.random.randint(0,len(X0))
while Ran1 == Ran2:
Ran2 = np.random.randint(0,len(X0))
Xtemp = []
A1 = X0[Ran1] # Select the city to swap
A2 = X0[Ran2] # Select the city to swap
w = 0
for i in X0:
if X0[w]==A1:
Xtemp=np.append(Xtemp,A2)
elif X0[w]==A2:
Xtemp=np.append(Xtemp,A1)
else:
Xtemp=np.append(Xtemp,X0[w])
w = w+1
a = []
contador = []
c = 0
tipo = []
for i in range(M):
for j in range(N):
# se van generando numeros aleatorios para ir cambiando los clientes
Ran1 = np.random.randint(0,len(X0))
Ran2 = np.random.randint(0,len(X0))
while Ran1 == Ran2:
Ran2 = np.random.randint(0,len(X0))
Xtemp = []
#seleccionar los clientes que se cambiaron segun su posicion
A1 = X0[Ran1]
A2 = X0[Ran2]
# una lista nueva de clientes
w = 0
for i in X0:
if X0[w]==A1:
Xtemp=np.append(Xtemp,A2)
elif X0[w]==A2:
Xtemp=np.append(Xtemp,A1)
else:
Xtemp=np.append(Xtemp,X0[w])
w = w+1
Xtemp = list(Xtemp)
Distances_X0 = [] # La distancia de la primera solucion, la solucion X0 es la que se le va haciendo cambios
t = 0
for i in range(len(X0)-1):
X1_1 = Data1.loc[X0[t],X0[t+1]] # se rocorre el cliente i y el cliente j
Distances_X0.append(X1_1) # Append the distances
t = t+1
#Distances_X0.append(X11)
Len_X0 = sum(Distances_X0) # agregar distancias
Distances_Xtemp = [] # La solucion objetivo, de la solución potencial (n+1)
t = 0
for i in range(len(Xtemp)-1):
X1_2 = Data1.loc[Xtemp[t],Xtemp[t+1]] # se rocorre el cliente i y el cliente j
Distances_Xtemp.append(X1_2) #agregar distnacias
t = t+1
Len_Xtemp = sum(Distances_Xtemp) # suma de distnacias
############################################################################################
rand_num = np.random.rand() # random para la formula de abajo que acepta o no los movimientos
form_1 = 1/(np.exp((Len_Xtemp-Len_X0)/T0)) # la formula con un numero aletorio evalua la funcion objetivo dentro de una fumcion exponencial, me falta agragar este modelo en el informe
############################################################################################
if Len_Xtemp <= Len_X0: # evaluar si la funcion objetivo posible es mejor o no a lo que hay
X0 = Xtemp
elif rand_num <= form_1: # evaluar si el randmon es menor a la formula
X0 = Xtemp
else: # si es menor no se acepta la solucion y se queda con lo que tiene
X0 = X0
Temp = np.append(Temp, T0) # agregar las temperaturas, esto es para la grafica
Min_Distance = np.append(Min_Distance,Len_Xtemp) # este es el costo asociado de elegir una ruta, y se agrega para los graficos y la solucion
T0 = Alpha*T0 # dentro del SA la temperatura tiene que ir decreciendo en funcion del alpha incial
c+=1
contador.append(c)
tipo.append('sa')
#a.append(Len_Xtemp)
Len_X0
Min_Distance
a = list(Min_Distance)
#en(a)
a
len(contador)
df = pd.DataFrame({'cuenta':contador ,
'soluciones':a ,
't': tipo})
print(df)
Min_Distance
a
b=min(a)
b
Min_Distance
print("Solucion final: ", X0)
print("Distancia minima: ", Len_X0)
plt.figure(figsize=(20,7))
plt.plot(Temp,Min_Distance)
plt.title("Distancia vs. Temperatura",fontsize=20,fontweight='bold')
plt.xlabel("Temperatura",fontsize=20,fontweight='bold')
plt.ylabel("Distancia",fontsize=20,fontweight='bold')
plt.xlim(50, 0)
plt.xticks(np.arange(min(Temp), max(Temp), 100),fontweight='bold')
plt.yticks(fontweight='bold')
plt.show()
indices_X0 =[]
for n in range (len(X0)):
#print (df.loc[df['direccion'] == X0[n]])
#print (df.index[df['direccion'] == X0[n]])
#print (df.index[df['direccion'] == X0[n]].tolist())
#plt.plot(df.loc[df['direccion'] == X0[n]][3]
#lista_orden=df[df['direccion']==X0[n]].index.tolist()
lista_orden=df[df['direccion']==X0[n]].index
indices_X0.append(lista_orden[0])
#indices_X0.append(df.index[df['direccion'] == X0[n]])
indices_X0
n=len(df)
nodos=[i for i in range(n)]
plt.figure(figsize=(10,10))
for n in range(len(nodos)):
plt.scatter(df.loc[n][3], df.loc[n][4], c= 'Red', marker = 'o')
plt.annotate(str(nodos[n]),xy=(df.loc[n][3], df.loc[n][4]),color="Blue")
for n in range (len(indices_X0)-1):
plt.plot([df.loc[indices_X0[n]][3],df.loc[indices_X0[n+1]][3]],[df.loc[indices_X0[n]][4],df.loc[indices_X0[n+1]][4]],color='blue')
plt.xlabel("LATITUD",fontsize=14)
plt.ylabel("LONGITUD",fontsize=14)
plt.title("TSP Simulated annealing",fontsize=20)
plt.show()
nodos=[]
for n in range(len(indices_X0)-1):
nodos.append([indices_X0[n],indices_X0[n+1]])
coord_mapa=[]
for n in range (len(df)):
lista_aux=[]
lista_aux.append(df.iloc[n][3])
lista_aux.append(df.iloc[n][4])
coord_mapa.append(lista_aux)
nombres=[]
for n in range(len(df)):
nombres.append(df.iloc[n][0])
mapa = folium.Map(location=[coord_mapa[0][0],coord_mapa[0][1]])
mapa
for i,j in nodos:
linea=folium.PolyLine(locations = [[coord_mapa[i][0],coord_mapa[i][1]],[coord_mapa[j][0],coord_mapa[j][1]]],weight=5)
mapa.add_child(linea)
fg=folium.FeatureGroup(name="Direcciones")
for n in range (len(df)) :
fg.add_child(folium.Marker(location=coord_mapa[n],popup=folium.Popup(nombres[n]),
icon=folium.Icon(color='blue',icon_color='white',icon='info-sign')))
mapa.add_child(fg)
mapa