|
import streamlit as st |
|
|
|
|
|
|
|
|
|
|
|
st.set_page_config( |
|
page_title="LupercAI", |
|
page_icon= "🚛", |
|
layout="centered", |
|
initial_sidebar_state="collapsed", |
|
menu_items={ |
|
'Get Help': "https://www.inta.es/INTA/es/index.html", |
|
'Report a bug': "https://www.inta.es/INTA/es/index.html", |
|
'About': "Si necesitas ayuda, puedes dirigirte a *cortnav@inta.es*." |
|
} |
|
) |
|
|
|
|
|
|
|
|
|
|
|
if "alg_genetico" in st.session_state: del st.session_state["alg_genetico"] |
|
|
|
st.title("LupercAI 🚛") |
|
|
|
st.header("Entrada de archivos") |
|
|
|
import pandas as pd |
|
|
|
tab1, tab2 = st.tabs(["Excel", "Manual"]) |
|
|
|
with tab1: |
|
uploaded_file = st.file_uploader("Elige un archivo", accept_multiple_files=False, type=["xlsx"], help="Solo acepta excel") |
|
if uploaded_file is not None: |
|
st.write(uploaded_file.name) |
|
|
|
datos = pd.read_excel(uploaded_file, sheet_name=None) |
|
nombres_hojas = list(datos.keys()) |
|
|
|
if "Distancias" not in nombres_hojas or "Demandas_clientes" not in nombres_hojas or "Capacidad_vehiculos" not in nombres_hojas: |
|
st.error("Falta una hoja", icon = "❌") |
|
|
|
else: |
|
|
|
valores = dict() |
|
for hoja in ["Num_nodos", "Distancias", "Demandas_clientes", "Num_vehiculos", "Capacidad_vehiculos"]: |
|
|
|
if hoja in nombres_hojas: |
|
dataframe = pd.read_excel(uploaded_file, engine='openpyxl', sheet_name=hoja, header=None, names=[]) |
|
matriz = dataframe.values.tolist() |
|
valores[hoja] = matriz |
|
|
|
if "Num_nodos" in nombres_hojas: num_nodos = valores["Num_nodos"][0][0] |
|
distancias = valores["Distancias"] |
|
demandas_clientes = [valor[0] for valor in valores["Demandas_clientes"]] |
|
if "Num_vehiculos" in nombres_hojas: num_vehiculos = valores["Num_vehiculos"][0][0] |
|
capacidad_vehiculos = [valor[0] for valor in valores["Capacidad_vehiculos"]] |
|
|
|
|
|
|
|
with tab2: |
|
|
|
left_column, right_column = st.columns(2) |
|
|
|
with left_column: |
|
form1 = st.form("Grafo") |
|
num_nodosB = form1.number_input('Número de paradas', value = 1, help="Incluye el almacén") |
|
form1.form_submit_button("OK") |
|
|
|
st.subheader("Demandas") |
|
form2 = st.form("Demanda de cada parada") |
|
demandas_clientesB = [] |
|
demandas_clientesB.append(form2.number_input('Demanda del Almacén', value = 0, max_value=0, min_value=0)) |
|
for i in range(1, num_nodosB): |
|
demandas_clientesB.append(form2.number_input('Demanda de la parada ' + str(i), value = 1)) |
|
boton2 = form2.form_submit_button("OK") |
|
|
|
if boton2: |
|
form2.success("Demandas actualizado") |
|
|
|
|
|
with right_column: |
|
form3 = st.form("número de vehiculos") |
|
num_vehiculosB = form3.number_input('Número de vehiculos', value = 1) |
|
form3.form_submit_button("OK") |
|
|
|
st.subheader("Vehiculos") |
|
form4 = st.form("Carga de vehiculos") |
|
capacidad_vehiculosB = [] |
|
for i in range(1, num_vehiculosB + 1): |
|
capacidad_vehiculosB.append(form4.number_input('Carga del vehiculo ' + str(i), value = 1)) |
|
boton4 = form4.form_submit_button("OK") |
|
|
|
if boton4: |
|
form4.success("Cargas actualizado") |
|
|
|
st.subheader("Distancias") |
|
form5 = st.form("Distancias") |
|
|
|
|
|
data_inicial = [dict([(str(i),None) for i in range(num_nodosB)])] * num_nodosB |
|
data_df = pd.DataFrame(data_inicial) |
|
for i in range(num_nodosB): data_df[str(i)][i] = 0 |
|
edited_df = form5.data_editor(data_df) |
|
|
|
(fila, columna) = (0, 0) |
|
favorite_command = edited_df[str(columna)][fila] |
|
form5.write(f"Fila {fila} Columna {columna}: **{favorite_command}** ") |
|
|
|
distanciasB = edited_df.values.tolist() |
|
|
|
boton5 = form5.form_submit_button("OK") |
|
|
|
if boton5: |
|
form5.success("Distancias actualizado") |
|
|
|
if boton2 or boton4 or boton5: |
|
uploaded_file = None |
|
|
|
if uploaded_file == None: |
|
num_nodos = num_nodosB |
|
distancias = distanciasB |
|
demandas_clientes = demandas_clientesB |
|
num_vehiculos = num_vehiculosB |
|
capacidad_vehiculos = capacidad_vehiculosB |
|
|
|
|
|
|
|
|
|
st.header("Variables genéticas") |
|
|
|
chosen = st.radio( |
|
'¿Desea incluir alguna variable genética?', |
|
("Variables predefinidas", "Escoger variables"), |
|
0) |
|
|
|
if not chosen == "Escoger variables": |
|
st.session_state["activar_generaciones"] = False |
|
|
|
else: |
|
|
|
c1, c2, c3 = st.columns(3) |
|
|
|
|
|
with c1: |
|
tamano_poblacion_bool = st.checkbox('Tamaño poblacion') |
|
tamano_poblacion = 50 |
|
if tamano_poblacion_bool: tamano_poblacion = st.number_input('Tamaño poblacion', value = 50, min_value = 1, label_visibility = "hidden") |
|
|
|
tamano_torneo_bool = st.checkbox('Tamaño torneo') |
|
tamano_torneo = 5 |
|
if tamano_torneo_bool: tamano_torneo = st.number_input('Tamaño poblacion', value = 5, min_value = 1, |
|
help = 'El tamaño del torneo debe ser menor al tamaño de la población', label_visibility = "hidden") |
|
|
|
if tamano_poblacion <= tamano_torneo: |
|
st.warning('El tamaño del torneo debe ser menor al tamaño de la población.', icon="⚠️") |
|
tamano_torneo = 1 |
|
|
|
with c2: |
|
generaciones_bool = st.checkbox('Generaciones') |
|
generaciones = 100 |
|
if generaciones_bool: generaciones = st.number_input('Generaciones', value = 100, min_value = 1, label_visibility = "hidden") |
|
|
|
st.session_state['generaciones'] = generaciones |
|
|
|
with c3: |
|
crossover_prob_bool = st.checkbox('Probabilidad de cruce') |
|
crossover_prob = 0.8 |
|
if crossover_prob_bool: crossover_prob = st.number_input('Probabilidad de cruce', value = 0.8, min_value = 0.0, max_value = 1.0, label_visibility = "hidden") |
|
|
|
mutation_prob_bool = st.checkbox('Probabilidad de mutación') |
|
mutation_prob = 0.2 |
|
if mutation_prob_bool: mutation_prob = st.number_input('Probabilidad de mutación', value = 0.2, min_value = 0.0, max_value = 1.0, label_visibility = "hidden") |
|
|
|
if tamano_poblacion_bool or tamano_torneo_bool or generaciones_bool or crossover_prob_bool or mutation_prob_bool: |
|
st.session_state["activar_generaciones"] = True |
|
st.session_state["tamano_poblacion"] = tamano_poblacion |
|
st.session_state["tamano_torneo"] = tamano_torneo |
|
st.session_state["generaciones"] = generaciones |
|
st.session_state["crossover_prob"] = crossover_prob |
|
st.session_state["mutation_prob"] = mutation_prob |
|
else: |
|
st.session_state["activar_generaciones"] = False |
|
|
|
st.header("Guardar") |
|
boton = st.button("¿Guardar variables?", type="primary") |
|
|
|
if boton: |
|
|
|
if distancias == None or demandas_clientes == None or capacidad_vehiculos == None: st.error(f"Falta un valor fundamental") |
|
elif len(distancias) != len(demandas_clientes): st.error(f"Distancias: {distancias} no coincide con Demandas: {demandas_clientes}") |
|
else: |
|
st.session_state["distancias"] = distancias |
|
st.session_state["demandas_clientes"] = demandas_clientes |
|
st.session_state["capacidad_vehiculos"] = capacidad_vehiculos |
|
|
|
if num_nodos != None: |
|
if num_nodos != len(distancias): st.warning(f"Número de paradas: {num_nodos} no coincide con Distancias: {distancias}") |
|
else: st.session_state["num_nodos"] = num_nodos |
|
|
|
if num_vehiculos != None: |
|
if num_vehiculos != len(capacidad_vehiculos): st.warning(f"Número de vehiculos: {num_vehiculos} no coincide con Cargas Vehiculos: {capacidad_vehiculos}") |
|
else: st.session_state["num_vehiculos"] = num_vehiculos |
|
|
|
st.success(f"Valores actualizados") |