Spaces:
Sleeping
Sleeping
File size: 6,784 Bytes
ff39e1a 6f1635e ff39e1a 6c7d496 ff39e1a 6c7d496 ff39e1a 7c640f7 6c7d496 7c640f7 ff39e1a 4afd3e0 6c7d496 ff39e1a fa99f2c ff39e1a fa99f2c ff39e1a 4afd3e0 ff39e1a 8ba070b ff39e1a fa99f2c ff39e1a 6f1635e ff39e1a 4afd3e0 be99ee8 4afd3e0 be99ee8 4afd3e0 ff39e1a ad68f89 ff39e1a ad68f89 ff39e1a fa99f2c ff39e1a 4afd3e0 ff39e1a be99ee8 ff39e1a 223e856 4afd3e0 223e856 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | import requests
import folium
import colorcet as cc
import plotly.express as px
import panel as pn
import pandas as pd
import geopandas as gpd
from time import sleep
from bokeh.models.widgets.tables import DateFormatter
from vrp import calcul_routes
from tableur import Tableur
from routingmat import fetch_matrices
pn.extension("tabulator", 'plotly')
wgs84="EPSG:4326"
l93="EPSG:9794"
pal=cc.glasbey_dark
def mat_figs(dfadr, mat_dist, mat_dur):
labels=[ f'{row["oid"]}:{row["lieu"]}' for _, row in dfadr.iterrows()]
fig_dist = px.imshow(mat_dur, height=1500, x=labels, y=labels, title = "Distance (m) entre deux adresses")
fig_dur = px.imshow(mat_dist, height=1500, x=labels, y=labels, title = "Temps (minutes) entre deux adresses")
return fig_dist, fig_dur
duree_taxi=pn.widgets.IntInput(name='Durée max taxi', value=45, step=1, start=0, end=300)
duree_ecole=pn.widgets.IntInput(name='Durée max devant école', value=10, step=1, start=0, end=60)
capacité=pn.widgets.IntInput(name='Capacité taxi', value=3, step=1, start=0, end=10)
def mise_en_forme_dfinal(sol, dfadr):
dfsol=sol.routes
dfsol["num_vehicule"]=dfsol.groupby("vehicle_id").ngroup()
dfsol["durée (minutes)"]=dfsol["duration"]//60
dfsol["temps d'attente (minutes)"]=dfsol["waiting_time"]//60
dfsol["indice"]=dfsol.location_index.map(dfadr["oid"].to_dict())
dfsol["lieu"] = dfsol.location_index.map(dfadr["lieu"].to_dict())
dfsol["geometry"] = dfsol.location_index.map(dfadr["geometry"].to_dict())
dfsol["heure"]=dfsol.arrival.astype("datetime64[s]").dt.time
dfsol["événement"]=dfsol.type.map({"pickup": "prise en charge", "delivery": "dépôt"})
goodcols=['num_vehicule', 'événement', 'distance', 'durée (minutes)',
"temps d'attente (minutes)", 'indice', 'lieu', 'geometry', 'heure']
dffinal=dfsol[goodcols].dropna()
return dffinal
def fetch_itinéraires(dffinal):
dres={}
for igp, gp in dffinal.groupby("num_vehicule"):
coo=[f"{p.x},{p.y}" for p in gp.geometry.to_list()]
params=dict(resource= "bdtopo-osrm",
start=coo[0],
end=coo[-1],
intermediates="|".join(coo[1:-2]),
geometryFormat="geojson",
getSteps='false',
getBbox='true',
timeUnit="minute",
crs=wgs84)
r=requests.get(url="https://data.geopf.fr/navigation/itineraire",
params=params)
sleep(0.1)
if r.ok:
dres[igp]=r.json()
return dres
def carte(dffinal, dres, dfadr):
tiles='GeoportailFrance.plan'
bbox=dfadr.total_bounds #[0.036343, 48.41117, 0.109909, 48.465001]
m = folium.Map(location=[(bbox[3]+bbox[1])/2, (bbox[2]+bbox[0])/2], tiles=tiles)#, zoom_start=10)
for igp, gp in dffinal.groupby("num_vehicule"):
dirs=dres[igp]
color=pal[igp]
folium.GeoJson(
name=f'Vehicle {igp}',
data={"type": "FeatureCollection",
"features": [{"type": "Feature",
"geometry": dirs['geometry'],
"properties": {"color": color} }]},
style_function=lambda x: {"color": x['properties']['color']}
).add_to(m)
for _, step in gp.iterrows():
icon='user' if step['événement']=='prise en charge' else 'briefcase'
folium.Marker(
location=[step["geometry"].y, step["geometry"].x],
icon=folium.Icon(color="lightgray", icon_color=color, icon=icon),
popup=f'{step["lieu"]}\n{step["heure"]}'
).add_to(m)
return m
tabd=Tableur(idx_offset=1)
tabp=Tableur(idx_offset=1001, delivery_tab=tabd)
def tableau_resultats(dffinal):
tab_final=pn.widgets.Tabulator(dffinal.drop("geometry", axis=1).value_counts().reset_index().sort_values(by=["num_vehicule", "heure"]).reset_index(drop=True),
formatters={"heure" : DateFormatter(format="%H:%M")},
disabled=True,
height=1000)
tab_final.style.map(lambda v: f'background-color:{pal[v]};color:white', subset="num_vehicule")
fichier_exp, bouton_exp = tab_final.download_menu(
text_kwargs={'label': 'Nom csv résultats', 'value': 'Résultats.csv'},
button_kwargs={'label': 'Télécharger'}
)
return pn.Column(
pn.Row(fichier_exp, bouton_exp), tab_final
)
def tous_calculs(_):
dfp=tabp.df.dropna()
dest_col=tabp.dest_col.value
gdfadr=gpd.GeoDataFrame(pd.concat([
dfp[["suggestion", "geometry_p"]].rename(columns={"suggestion" : "lieu", "geometry_p": "geometry"}),
tabd.df[[dest_col, "geometry"]][tabd.df[dest_col].isin(tabp.df.dropna()[dest_col])].rename(columns={dest_col : "lieu"})],
keys=["p", "d"], names=['type', 'oid']).drop_duplicates().reset_index() )
ladr=gdfadr["lieu"].to_list()
mat_dist, mat_dur=fetch_matrices(gdfadr)
fig_dist, fig_dur=mat_figs(gdfadr, mat_dist, mat_dur)
tabs.append(('Matrice de distances', pn.pane.Plotly(fig_dist, width=1100, height=1000 )))
tabs.append(('Matrice de durées', pn.pane.Plotly(fig_dur, width=1100, height=1000 )))
sol=calcul_routes(dfp, ladr, mat_dist, mat_dur, duree_taxi.value, duree_ecole.value, capacité.value)
unass=sol.to_dict()["unassigned"]
if len(unass):
gpu=dfp.loc[list({u["id"] for u in unass})][['suggestion', 'indice école', 'ECOLE', 'arrivée_max']].copy()
gpu["Distance (km)"]=gpu.apply(lambda row: mat_dist[ladr.index(row["suggestion"])][ladr.index( row["ECOLE"])], axis=1)
gpu["Durée (min)"]=gpu.apply(lambda row: mat_dur[ladr.index( row["suggestion"])][ladr.index( row["ECOLE"])]//60, axis=1)
tabs.append(('Non assignés', pn.widgets.Tabulator(gpu, disabled=True, height=1000)))
dffinal=mise_en_forme_dfinal(sol, gdfadr)
tabs.append(('Tableau des résultats', tableau_resultats(dffinal)))
dres=fetch_itinéraires(dffinal)
m=carte(dffinal, dres, gdfadr)
tabs.append(('Carte des résultats', pn.pane.plot.Folium(m, height=1000) ))
return
bouton=pn.widgets.Button(name="Lancer les calculs", button_type="primary", on_click=tous_calculs)
tabs=pn.Tabs(
('Destinations', tabd.get_panel()),
('Usagers', tabp.get_panel()),
('Calculs des routes', pn.Column(duree_taxi, duree_ecole, capacité, bouton) ), )
template= pn.template.MaterialTemplate(title="Problème de tournée des véhicules avec capacités et fenêtre temporelle")
template.main.append(tabs)
template.header.append("v0.3.0")
template.servable() |