Delete pages
Browse files- pages/Ejecucion.py +0 -108
- pages/vrp/Algoritmo_gen茅tico.py +0 -84
- pages/vrp/Evolucion.py +0 -57
- pages/vrp/Origen.py +0 -28
- pages/vrp/Reparto.py +0 -80
- pages/vrp/__init__.py +0 -0
pages/Ejecucion.py
DELETED
@@ -1,108 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
|
3 |
-
from pages.vrp.Origen import Grafo, Vehiculos
|
4 |
-
from pages.vrp.Algoritmo_gen茅tico import Algoritmo_Genetico
|
5 |
-
|
6 |
-
#######################
|
7 |
-
## FUNCIONES AUXILIARES
|
8 |
-
#######################
|
9 |
-
|
10 |
-
def grafar(reparto : list[list[int]]):
|
11 |
-
|
12 |
-
result = "digraph { \n"
|
13 |
-
|
14 |
-
for ruta in reparto:
|
15 |
-
result += "Almac茅n ->"
|
16 |
-
for nodo in ruta:
|
17 |
-
result += str(nodo) + "\n"
|
18 |
-
result += str(nodo) + "->"
|
19 |
-
result += "Almac茅n \n"
|
20 |
-
|
21 |
-
result += "}"
|
22 |
-
|
23 |
-
return result
|
24 |
-
|
25 |
-
def presentar(reparto : list[list[int]]):
|
26 |
-
|
27 |
-
result = ""
|
28 |
-
|
29 |
-
for i in range(len(reparto)):
|
30 |
-
result += "Camion " + str(i) + ": " + "Almac茅n -> "
|
31 |
-
for parada in reparto[i]:
|
32 |
-
result += str(parada) + " -> "
|
33 |
-
result += "Almac茅n \n"
|
34 |
-
|
35 |
-
return result
|
36 |
-
|
37 |
-
st.set_page_config(page_title="LupercAI", page_icon= "馃殯")
|
38 |
-
|
39 |
-
st.title("LupercAI 馃殯")
|
40 |
-
|
41 |
-
valores_vitales = ["distancias", "demandas_clientes", "capacidad_vehiculos"]
|
42 |
-
importado = True
|
43 |
-
for valor in valores_vitales: importado = importado and valor in st.session_state
|
44 |
-
|
45 |
-
if not importado:
|
46 |
-
st.warning("Faltan datos", icon="鈿狅笍")
|
47 |
-
else:
|
48 |
-
#if "num_nodos" not in st.session_state: st.session_state["num_nodos"] = len(st.session_state["demandas_clientes"])
|
49 |
-
#if "num_vehiculos" not in st.session_state: st.session_state["num_vehiculos"] = len(st.session_state["capacidad_vehiculos"])
|
50 |
-
|
51 |
-
grafo = Grafo(st.session_state["distancias"], st.session_state["demandas_clientes"])
|
52 |
-
vehiculos = Vehiculos(st.session_state["capacidad_vehiculos"])
|
53 |
-
|
54 |
-
if "activar_generaciones" in st.session_state:
|
55 |
-
if st.session_state["activar_generaciones"]:
|
56 |
-
if "alg_genetico" not in st.session_state: st.session_state["alg_genetico"] = Algoritmo_Genetico(tamano_poblacion = st.session_state["tamano_poblacion"],
|
57 |
-
generaciones = st.session_state["generaciones"], tamano_torneo = st.session_state["tamano_torneo"],
|
58 |
-
crossover_prob = st.session_state["crossover_prob"], mutation_prob = st.session_state["mutation_prob"])
|
59 |
-
else:
|
60 |
-
if "alg_genetico" not in st.session_state: st.session_state["alg_genetico"] = Algoritmo_Genetico()
|
61 |
-
else:
|
62 |
-
if "alg_genetico" not in st.session_state: st.session_state["alg_genetico"] = Algoritmo_Genetico()
|
63 |
-
|
64 |
-
alg_genetico = st.session_state["alg_genetico"]
|
65 |
-
|
66 |
-
from threading import Thread
|
67 |
-
Thread(target=alg_genetico.generar, args = (grafo, vehiculos)).start()
|
68 |
-
|
69 |
-
|
70 |
-
#Computaci贸n:
|
71 |
-
|
72 |
-
empty_latest_iteration = st.empty()
|
73 |
-
empty_mejor_coste = st.empty()
|
74 |
-
|
75 |
-
st.subheader("Barra de progreso")
|
76 |
-
barra_progreso = st.progress(0)
|
77 |
-
|
78 |
-
st.subheader("Grafo del mejor recorrido actual")
|
79 |
-
|
80 |
-
empty_txt = st.empty()
|
81 |
-
|
82 |
-
empty_grafo = st.empty()
|
83 |
-
|
84 |
-
i = 0
|
85 |
-
while alg_genetico.generacion_actual < alg_genetico.generaciones:
|
86 |
-
#Generaci贸n por escrito
|
87 |
-
empty_latest_iteration.write("Generaci贸n: " + str(alg_genetico.generacion_actual))
|
88 |
-
|
89 |
-
#Barra de progreso
|
90 |
-
barra_progreso.progress( alg_genetico.generacion_actual/alg_genetico.generaciones)
|
91 |
-
|
92 |
-
#Mejor coste actual (texto)
|
93 |
-
empty_mejor_coste.write("**Mejor coste**: " + str(alg_genetico.mejor_candidato[1]))
|
94 |
-
|
95 |
-
#Descarga de grafo
|
96 |
-
empty_txt.download_button("Mejor recorrido 馃斀", presentar(alg_genetico.mejor_candidato[0]), file_name="Mejor reparto - Generacion " + str(alg_genetico.generacion_actual) + ".txt", key=str(i))
|
97 |
-
i += 1
|
98 |
-
|
99 |
-
#Mostrar el grafo
|
100 |
-
empty_grafo.graphviz_chart(grafar(alg_genetico.mejor_candidato[0]))
|
101 |
-
|
102 |
-
|
103 |
-
#Ultima iteracion
|
104 |
-
empty_latest_iteration.write("Generaci贸n: " + str(alg_genetico.generacion_actual))
|
105 |
-
barra_progreso.progress( alg_genetico.generacion_actual/alg_genetico.generaciones)
|
106 |
-
empty_mejor_coste.write("**Mejor coste**: " + str(alg_genetico.mejor_candidato[1]))
|
107 |
-
empty_txt.download_button("Mejor recorrido 馃斀", presentar(alg_genetico.mejor_candidato[0]), file_name="Mejor reparto - Generacion " + str(alg_genetico.generacion_actual) + ".txt", key=str(i))
|
108 |
-
empty_grafo.graphviz_chart(grafar(alg_genetico.mejor_candidato[0]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/vrp/Algoritmo_gen茅tico.py
DELETED
@@ -1,84 +0,0 @@
|
|
1 |
-
#VERSI脫N 4: VERSI脫N SEMI-ORIENTADA A OBJETOS
|
2 |
-
#(F): A a帽adir en (F)uturas versiones
|
3 |
-
|
4 |
-
### CLASES DEL ALGORITMO ###
|
5 |
-
|
6 |
-
from .Reparto import Reparto, division_rutas
|
7 |
-
|
8 |
-
class Algoritmo_Genetico:
|
9 |
-
def __init__(self, tamano_poblacion : int = 50, generaciones : int = 100, tamano_torneo : int = 5,
|
10 |
-
crossover_prob : float = 0.8, mutation_prob : float = 0.2):
|
11 |
-
|
12 |
-
#Variables del algoritmo (int)
|
13 |
-
self.tamano_poblacion = tamano_poblacion
|
14 |
-
self.generaciones = generaciones
|
15 |
-
self.tamano_torneo = tamano_torneo
|
16 |
-
|
17 |
-
#Variables del algoritmo (%)
|
18 |
-
self.crossover_prob = crossover_prob
|
19 |
-
self.mutation_prob = mutation_prob
|
20 |
-
|
21 |
-
#Variables en ejecuci贸n
|
22 |
-
self.generacion_actual = 0
|
23 |
-
self.mejor_candidato = ([[1,2,3],[4]], float("inf"))
|
24 |
-
|
25 |
-
|
26 |
-
def _poblar(self, grafo, vehiculos):
|
27 |
-
Reparto.grafo = grafo
|
28 |
-
Reparto.vehiculos = vehiculos
|
29 |
-
return crear_poblacion(self)
|
30 |
-
|
31 |
-
def generar(self, grafo, vehiculos):
|
32 |
-
|
33 |
-
#print("##############\n##EMPEZAMOS \n##############")
|
34 |
-
|
35 |
-
Poblacion = self._poblar(grafo, vehiculos)
|
36 |
-
poblacion = Poblacion()
|
37 |
-
|
38 |
-
from time import sleep
|
39 |
-
|
40 |
-
for _ in range(self.generaciones):
|
41 |
-
sleep(0.1)
|
42 |
-
poblacion = poblacion.evolucionar()
|
43 |
-
self.generacion_actual = self.generacion_actual + 1
|
44 |
-
self.mejor_candidato = (division_rutas(poblacion.poblacion[0]), poblacion.poblacion[0].coste)
|
45 |
-
|
46 |
-
from .Evolucion import mejor_individuo
|
47 |
-
|
48 |
-
return mejor_individuo(poblacion.poblacion)
|
49 |
-
|
50 |
-
def crear_poblacion(alg_genetico : Algoritmo_Genetico): #quizas haga falta , clase_Reparto : type = Reparto
|
51 |
-
import random
|
52 |
-
|
53 |
-
from .Evolucion import Evolucion
|
54 |
-
|
55 |
-
class Poblacion:
|
56 |
-
def __init__(self, poblacion : list[Reparto] = [Reparto()]*alg_genetico.tamano_poblacion):
|
57 |
-
self.poblacion = poblacion
|
58 |
-
|
59 |
-
def evolucionar(self):
|
60 |
-
new_poblacion = [Evolucion.elitismo(self.poblacion)]
|
61 |
-
|
62 |
-
for _ in range(alg_genetico.tamano_poblacion - 1):
|
63 |
-
new_poblacion += [self._evolucionar_individuo()]
|
64 |
-
|
65 |
-
return Poblacion(new_poblacion)
|
66 |
-
|
67 |
-
def _evolucionar_individuo(self):
|
68 |
-
parent1 = Evolucion.torneo(self.poblacion, alg_genetico.tamano_torneo)
|
69 |
-
|
70 |
-
child = parent1
|
71 |
-
|
72 |
-
if random.random() < alg_genetico.crossover_prob: #Cruce %
|
73 |
-
parent2 = Evolucion.torneo(self.poblacion, alg_genetico.tamano_torneo)
|
74 |
-
child = Evolucion.crossover(parent1, parent2)
|
75 |
-
if random.random() < alg_genetico.mutation_prob: #Mutaci贸n %
|
76 |
-
child = Evolucion.mutate(child)
|
77 |
-
|
78 |
-
return child
|
79 |
-
|
80 |
-
return Poblacion
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/vrp/Evolucion.py
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
#VERSI脫N 4: VERSI脫N SEMI-ORIENTADA A OBJETOS
|
2 |
-
#(F): A a帽adir en (F)uturas versiones
|
3 |
-
|
4 |
-
### FUNCIONES AUXILIARES ###
|
5 |
-
|
6 |
-
import random
|
7 |
-
|
8 |
-
from .Reparto import Reparto
|
9 |
-
|
10 |
-
|
11 |
-
def mejor_individuo(list_individuos : list[Reparto]) -> Reparto: #paralelizable
|
12 |
-
mejor_individuo = list_individuos[0]
|
13 |
-
for individuo in list_individuos[1:]:
|
14 |
-
mejor_individuo = individuo if individuo.coste < mejor_individuo.coste else mejor_individuo
|
15 |
-
#print("mejor_individuo: ", mejor_individuo.ruta, mejor_individuo.coste)
|
16 |
-
return mejor_individuo
|
17 |
-
|
18 |
-
class Evolucion:
|
19 |
-
|
20 |
-
@staticmethod
|
21 |
-
def elitismo(poblacion : list[Reparto]) -> Reparto: #mejor ruta de la poblacion
|
22 |
-
return mejor_individuo(poblacion)
|
23 |
-
|
24 |
-
@staticmethod
|
25 |
-
def torneo(poblacion : list[Reparto], tamano_torneo) -> list[Reparto]: #mejor ruta de una parte de la poblacion
|
26 |
-
selected_individuos = random.sample(poblacion, tamano_torneo)
|
27 |
-
return mejor_individuo(selected_individuos)
|
28 |
-
|
29 |
-
@staticmethod
|
30 |
-
def mutate(ruta : Reparto) -> Reparto: #intercambia dos posiciones en la ruta
|
31 |
-
idx1, idx2 = random.sample(range(Reparto.grafo.num_nodos + Reparto.vehiculos.num_vehiculos - 2), 2)
|
32 |
-
lista = ruta.ruta.copy()
|
33 |
-
lista[idx1], lista[idx2] = lista[idx2], lista[idx1]
|
34 |
-
return Reparto(lista)
|
35 |
-
|
36 |
-
@staticmethod
|
37 |
-
def crossover(parent1 : Reparto, parent2 : Reparto) -> Reparto: #cruza dos rutas, pegando un cacho de la primera en la segunda
|
38 |
-
num_total = Reparto.grafo.num_nodos + Reparto.vehiculos.num_vehiculos - 2
|
39 |
-
#-1 por el Almac茅n
|
40 |
-
#-1 porque si hay n vehiculos, solo a帽adimos n-1 simbolos
|
41 |
-
|
42 |
-
start = random.randint(0, num_total - 1) #random.randint(a, b) toma un n煤mero entero al azar entre [a,b], no entre [a,b)
|
43 |
-
end = random.randint(start, num_total - 1)
|
44 |
-
|
45 |
-
child = [None] * num_total
|
46 |
-
|
47 |
-
for i in range(start, end+1):
|
48 |
-
child[i] = parent1.ruta[i]
|
49 |
-
remaining = [item for item in parent2.ruta if item not in child]
|
50 |
-
remaining_index = 0
|
51 |
-
for i in range(num_total):
|
52 |
-
if child[i] == None:
|
53 |
-
child[i] = remaining[remaining_index]
|
54 |
-
remaining_index += 1
|
55 |
-
|
56 |
-
return Reparto(child)
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/vrp/Origen.py
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
#VERSI脫N 5: VRP
|
2 |
-
#(F): A a帽adir en (F)uturas versiones
|
3 |
-
|
4 |
-
### CLASES DEL GRAFO ###
|
5 |
-
class Grafo:
|
6 |
-
def __init__(self, distancias: list[list[float]], demandas_clientes: list[float], num_nodos: int = None):
|
7 |
-
if num_nodos == None: num_nodos = len(distancias)
|
8 |
-
|
9 |
-
if len(demandas_clientes) == num_nodos:
|
10 |
-
self.num_nodos = num_nodos
|
11 |
-
self.distancias = distancias
|
12 |
-
self.demandas_clientes = demandas_clientes ##El almac茅n ya est谩 incluido
|
13 |
-
else:
|
14 |
-
raise IndexError("Las demandas no son igual al n煤mero de clientes")
|
15 |
-
|
16 |
-
class Vehiculos:
|
17 |
-
def __init__(self, capacidad_vehiculos: list[float], num_vehiculos: int = None):
|
18 |
-
if num_vehiculos == None: num_vehiculos = len(capacidad_vehiculos)
|
19 |
-
|
20 |
-
if len(capacidad_vehiculos) == num_vehiculos or num_vehiculos == None:
|
21 |
-
self.num_vehiculos = num_vehiculos
|
22 |
-
self.capacidad_vehiculos = sorted(capacidad_vehiculos)
|
23 |
-
else:
|
24 |
-
raise IndexError("Las capacidades no son igual al n煤mero de vehiculos")
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/vrp/Reparto.py
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
|
2 |
-
from .Origen import Grafo, Vehiculos
|
3 |
-
|
4 |
-
class Reparto:
|
5 |
-
grafo = None
|
6 |
-
vehiculos = None
|
7 |
-
|
8 |
-
def __init__(self, ruta = None):
|
9 |
-
if type(self.grafo) == Grafo and type(self.vehiculos) == Vehiculos:
|
10 |
-
if ruta == None:
|
11 |
-
ruta = list(range(-self.vehiculos.num_vehiculos + 1, self.grafo.num_nodos))
|
12 |
-
ruta.remove(0)
|
13 |
-
|
14 |
-
self.ruta = ruta
|
15 |
-
self.coste = self._coste()
|
16 |
-
|
17 |
-
def __str__(self):
|
18 |
-
return str((self.ruta,self.coste))
|
19 |
-
|
20 |
-
def _coste(self):
|
21 |
-
# Funci贸n de aptitud para evaluar la calidad de las soluciones
|
22 |
-
(distancia_total , demanda_total) = (0,0)
|
23 |
-
capacidades_actual = self.vehiculos.capacidad_vehiculos.copy()
|
24 |
-
|
25 |
-
rutas = division_rutas(self)
|
26 |
-
|
27 |
-
i = 1
|
28 |
-
for ruta in rutas:
|
29 |
-
distancia_total += coste_1ruta(ruta)
|
30 |
-
(demanda_actual, capacidades_actual) = capacidad_1ruta(ruta, capacidades_actual)
|
31 |
-
demanda_total += demanda_actual
|
32 |
-
i += 1
|
33 |
-
|
34 |
-
if demanda_total < float('inf'):
|
35 |
-
return distancia_total
|
36 |
-
else:
|
37 |
-
return float('inf')
|
38 |
-
|
39 |
-
|
40 |
-
def coste_1ruta(ruta : list[int]) -> int: #ruta = [1,2,3] sin #
|
41 |
-
recorrido = [0] + ruta + [0] #recorrido = [0,1,2,3,0]
|
42 |
-
|
43 |
-
distacia_total = 0
|
44 |
-
|
45 |
-
prev_nodo = 0
|
46 |
-
for nodo in recorrido[1:]:
|
47 |
-
|
48 |
-
distacia_total += Reparto.grafo.distancias[prev_nodo][nodo]
|
49 |
-
prev_nodo = nodo
|
50 |
-
|
51 |
-
return distacia_total
|
52 |
-
|
53 |
-
def capacidad_1ruta(ruta : list[int], capacidades_actual : list[int]) -> int: #ruta = [1,2,3] sin #
|
54 |
-
demanda_total = 0
|
55 |
-
|
56 |
-
for nodo in ruta:
|
57 |
-
demanda_total += Reparto.grafo.demandas_clientes[nodo]
|
58 |
-
|
59 |
-
if demanda_total <= capacidades_actual[-1]:
|
60 |
-
indice_capacidad = 0
|
61 |
-
while demanda_total > capacidades_actual[indice_capacidad]:
|
62 |
-
indice_capacidad += 1
|
63 |
-
capacidades_actual.pop(indice_capacidad)
|
64 |
-
return (demanda_total, capacidades_actual)
|
65 |
-
else:
|
66 |
-
return (float('inf'), capacidades_actual)
|
67 |
-
|
68 |
-
def division_rutas(reparto : Reparto) -> list[list[int]]:
|
69 |
-
result = []
|
70 |
-
ruta = []
|
71 |
-
for nodo in reparto.ruta:
|
72 |
-
if nodo >= 0:
|
73 |
-
ruta += [nodo]
|
74 |
-
else:
|
75 |
-
result += [ruta.copy()]
|
76 |
-
ruta = []
|
77 |
-
result += [ruta.copy()]
|
78 |
-
return result
|
79 |
-
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/vrp/__init__.py
DELETED
File without changes
|