solution_reader.py 4.94 KiB
import json
import datetime
import enum
import folium
import numpy as np
import pandas as pd
import osmnx as ox
import networkx as nx
def read_json(file):
try:
with open(file, 'r') as file:
data = json.load(file)
return data
except FileNotFoundError:
print(f"Error : The file {file} does not exist.")
except json.JSONDecodeError:
print(f"Error : The file {file} is not a valid JSON file.")
except Exception as e:
print(f"Error : {e}")
G_drive = ox.graph_from_point((47.213811, -1.553168), dist=10000,
network_type='bike')
class PDPTWSolution:
def __init__(self, filename: str):
with open(filename, mode="r", encoding="utf-8") as f:
self._json_file = json.load(f)
self._parse_json()
def _parse_json(self):
if self._json_file is None:
raise "Trying to parse json, but was not loaded"
self._routes: list[dict] = self._json_file["routes"]
def get_routes(self):
return self._routes
def get_json(self):
return self._json_file
class PDPTWData:
def __init__(self, filename: str):
with open(filename, mode="r", encoding="utf-8") as f:
self._json_file = json.load(f)
self._parse_json()
def _parse_json(self):
if self._json_file is None:
raise "Trying to parse json, but was not loaded"
self._locations: list[dict] = self._json_file["locations"]
self._depot: list[dict] = self._json_file["depot"]
self._capacity = self._json_file["capacity"]
def get_depot(self):
return self._depot
def get_locations(self):
return self._locations
def get_capacity(self):
return self._capacity
def get_json(self):
return self._json_file
def get_route_as_dataframe(data: PDPTWData, solution: PDPTWSolution, route_index:int) -> pd.DataFrame:
route_df=pd.DataFrame()
route_ids = solution.get_routes()[route_index]["locationIDs"]
for id in route_ids:
line = {"route": route_index,
"location": id,
"type": data.get_locations()[id - 1]["locType"],
"latitude": data.get_locations()[id - 1]["latitude"],
"longitude": data.get_locations()[id - 1]["longitude"]}
route_df = pd.concat([route_df, pd.DataFrame.from_dict([line])], ignore_index=True)
return route_df
def display_points_of_interest(map: folium.Map, data: PDPTWData):
folium.Marker(location=[data.get_depot()["latitude"], data.get_depot()["longitude"]],
icon=folium.Icon(color="red", popup="DEPOT")).add_to(map)
for location in data.get_locations():
if location["locType"] == "PICKUP":
color = "darkblue"
text = "pickup"
elif location["locType"] == "DELIVERY":
color = "lightblue"
text = "delivery"
else:
continue
folium.Marker(location=[location["latitude"], location["longitude"]],
icon=folium.Icon(color=color, popup=text)).add_to(map)
def display_route(map: folium.Map, data: PDPTWData, solution: PDPTWSolution, route_index: int, color: str="red"):
df = get_route_as_dataframe(data, solution, route_index)
# add depot at the begining and the end
types = ["DEPOT"] + list(df["type"]) + ["DEPOT"]
depot_coord = (data.get_depot()["latitude"], data.get_depot()["longitude"])
locations = [depot_coord] + list(zip(df["latitude"], df["longitude"])) + [depot_coord]
real_path_locations = []
network_locations = ox.nearest_nodes(G_drive,
[data.get_depot()["longitude"]] + list(df["longitude"]) + [data.get_depot()["longitude"]],
[data.get_depot()["latitude"]] + list(df["latitude"]) + [data.get_depot()["latitude"]])
for i in range(1, len(locations)):
edge = [network_locations[i - 1], network_locations[i]]
real_nodes = ox.shortest_path(G_drive, edge[0], edge[1], weight="length")
if real_nodes is not None:
long_lat_edges = []
for node in real_nodes:
g_drive_node = G_drive.nodes[node]
if "x" in g_drive_node and "y" in g_drive_node:
long_lat_edges.append((g_drive_node["y"], g_drive_node["x"]))
real_path_locations.extend(long_lat_edges)
else:
real_path_locations.append(locations[i])
folium.PolyLine(real_path_locations, color=color, weight=5, opacity=0.5, smooth_factor=0).add_to(map)
for index, row in df.iterrows():
if row["type"] == "REQUEST":
text = f'{index} - {row["latitude"], row["longitude"]} : times ({row["arrival"]},{row["service"]},{row["departure"]}), time window [{row["Hmin"]},{row["Hmax"]}]'
folium.Circle(location=(row["latitude"], row["longitude"]), fill_color="orange", radius=4,
tooltip=text).add_to(map)