MFLP / app.py
苏泓源
update
a257639
raw
history blame
12.1 kB
import gradio as gr
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from sklearn.metrics import pairwise_distances
import torch
from facility_location import multi_eval
import pickle
def solver_plot(data_npy, boost=False):
multi_eval.main(data_npy, boost)
all_solutions = pickle.loads(open('./facility_location/solutions.pkl', 'rb').read())
data = data_npy.split('\n')
n = len(data)
p = int((len(data[0].split(' '))-2) / 2)
positions = []
demands = []
actual_facilities = []
for row in data:
row = row.split(' ')
row = [x for x in row if len(x)]
positions.append([float(row[0]), float(row[1])])
demand = []
for i in range(2, 2+p):
demand.append(float(row[i]))
demands.append(demand)
actual_facility = []
for i in range(2+p, 2+2*p):
actual_facility.append(bool(int(float(row[i]))))
actual_facilities.append(actual_facility)
positions = np.array(positions)
demands = np.array(demands)
actual_facilities = np.array(actual_facilities)
solution_facilities = np.array(all_solutions).T
# print(solution_facilities)
# print(actual_facilities)
actual_fig = go.Figure()
solution_fig = go.Figure()
for i in range(p):
actual_fig.add_trace(go.Scattermapbox(
lat=positions[actual_facilities[:, i]][:, 0],
lon=positions[actual_facilities[:, i]][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=f'Facility {i+1}'
))
solution_fig.add_trace(go.Scattermapbox(
lat=positions[solution_facilities[:, i]][:, 0],
lon=positions[solution_facilities[:, i]][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=f'Facility {i+1}'
))
actual_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[actual_facilities[:, i]][:, 0]), \
lon=np.mean(positions[actual_facilities[:, i]][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
solution_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[solution_facilities[:, i]][:, 0]), \
lon=np.mean(positions[solution_facilities[:, i]][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
# show legend
actual_fig.update_layout(showlegend=True)
solution_fig.update_layout(showlegend=True)
positions = np.deg2rad(positions)
dist = pairwise_distances(positions, metric='haversine') * 6371
actual_ac = 0
solution_ac = 0
for i in range(p):
ac_matrix = dist * demands[:, i][:, None]
actual_ac += ac_matrix[:, actual_facilities[:, i]].min(axis=-1).sum()
solution_ac += ac_matrix[:, solution_facilities[:, i]].min(axis=-1).sum()
return actual_fig, solution_fig, actual_ac, solution_ac
def demo_plot(city, facility):
facility_name = ["🏫 School", "πŸ₯ Hospital", "🌳 Park"]
all_facility = ["🏫 School", "πŸ₯ Hospital", "🌳 Park"]
for i in range(len(all_facility)):
if all_facility[i] in facility:
all_facility[i] = True
else:
all_facility[i] = False
city_name = city.replace(' ', '_')
data = np.loadtxt(f'demo/{city_name}.npy')
positions = data[:, :2]
demands = data[:, 2:5]
actual_facility = data[:, 5:8]
solution_facility = data[:, 8:11]
actual_fig = go.Figure()
solution_fig = go.Figure()
for i in range(len(all_facility)):
if not all_facility[i]:
continue
actual_fig.add_trace(go.Scattermapbox(
lat=positions[actual_facility[:, i] == 1][:, 0],
lon=positions[actual_facility[:, i] == 1][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=facility_name[i],
))
solution_fig.add_trace(go.Scattermapbox(
lat=positions[solution_facility[:, i] == 1][:, 0],
lon=positions[solution_facility[:, i] == 1][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=facility_name[i],
))
actual_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[actual_facility[:, i] == 1][:, 0]), \
lon=np.mean(positions[actual_facility[:, i] == 1][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
solution_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[solution_facility[:, i] == 1][:, 0]), \
lon=np.mean(positions[solution_facility[:, i] == 1][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
# show legend
actual_fig.update_layout(showlegend=True)
solution_fig.update_layout(showlegend=True)
positions = np.deg2rad(positions)
dist = pairwise_distances(positions, metric='haversine') * 6371
actual_ac = 0
solution_ac = 0
for i in range(len(all_facility)):
if not all_facility[i]:
continue
ac_matrix = dist * demands[:, i][:, None]
actual_ac += ac_matrix[:, actual_facility[:, i] == 1].min(axis=-1).sum()
solution_ac += ac_matrix[:, solution_facility[:, i] == 1].min(axis=-1).sum()
return actual_fig, solution_fig, actual_ac, solution_ac
def solver_plot1(data_npy, boost=False):
data = data_npy.split('\n')
n = len(data)
p = int((len(data[0].split(' '))-2) / 2)
positions = []
demands = []
actual_facilities = []
for row in data:
row = row.split(' ')
row = [x for x in row if len(x)]
positions.append([float(row[0]), float(row[1])])
demand = []
for i in range(2, 2+p):
demand.append(float(row[i]))
demands.append(demand)
actual_facility = []
for i in range(2+p, 2+2*p):
actual_facility.append(bool(int(float(row[i]))))
actual_facilities.append(actual_facility)
positions = np.array(positions)
demands = np.array(demands)
actual_facilities = np.array(actual_facilities)
solution_facilities = ~actual_facilities
actual_fig = go.Figure()
solution_fig = go.Figure()
for i in range(p):
actual_fig.add_trace(go.Scattermapbox(
lat=positions[actual_facilities[:, i]][:, 0],
lon=positions[actual_facilities[:, i]][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=f'Facility {i+1}'
))
solution_fig.add_trace(go.Scattermapbox(
lat=positions[solution_facilities[:, i]][:, 0],
lon=positions[solution_facilities[:, i]][:, 1],
mode='markers',
marker=go.scattermapbox.Marker(
size=10,
color=px.colors.qualitative.Plotly[i]
),
name=f'Facility {i+1}'
))
actual_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[actual_facilities[:, i]][:, 0]), \
lon=np.mean(positions[actual_facilities[:, i]][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
solution_fig.update_layout(
mapbox=dict(
style='carto-positron',
center=dict(lat=np.mean(positions[solution_facilities[:, i]][:, 0]), \
lon=np.mean(positions[solution_facilities[:, i]][:, 1])),
zoom=11.0
),
margin=dict(l=0, r=0, b=0, t=0),)
# show legend
actual_fig.update_layout(showlegend=True)
solution_fig.update_layout(showlegend=True)
positions = np.deg2rad(positions)
dist = pairwise_distances(positions, metric='haversine') * 6371
actual_ac = 0
solution_ac = 0
for i in range(p):
ac_matrix = dist * demands[:, i][:, None]
actual_ac += ac_matrix[:, actual_facilities[:, i]].min(axis=-1).sum()
solution_ac += ac_matrix[:, solution_facilities[:, i]].min(axis=-1).sum()
return actual_fig, solution_fig, actual_ac, solution_ac
def get_example():
return [
('40.71 -73.93 213 1\n40.72 -73.99 15 1\n40.65 -73.88 365 1\n40.57 -73.96 629 0\n40.70 -73.97 106 0\n40.61 -73.95 189 1'),
("40.71 -73.93 213 124 0 1\n40.72 -73.99 15 43 1 0\n40.65 -73.88 365 214 1 0\n40.57 -73.96 629 431 0 1\n40.70 -73.97 106 241 0 1\n40.60 -73.92 129 214 1 0\n40.61 -73.95 189 264 0 1\n40.63 -73.94 124 164 1 0"),
]
def load_npy_file(file_obj):
data = np.loadtxt(file_obj.name)
string_array = '\n'.join([' '.join(map(str, row)) for row in data])
return string_array
with gr.Blocks() as demo:
gr.Markdown("## Demo")
with gr.Column():
city = gr.Radio(choices=["New York", "Boston", "Los Angeles", "Chicago"], value="New York", label="Select City:")
facility = gr.CheckboxGroup(choices=["🏫 School", "πŸ₯ Hospital", "🌳 Park"], value=["πŸ₯ Hospital"], label="Select Facility:")
btn = gr.Button(value="πŸš€ Generate")
with gr.Row():
actual_map = gr.Plot(label='Actual Facility Distribution')
solution_map = gr.Plot(label='Relocated Facility Distribution')
with gr.Row():
actual_ac = gr.Textbox(label='Real-world Access Cost')
solution_ac = gr.Textbox(label='Relocated Access Cost')
demo.load(fn=demo_plot, inputs=[city, facility], outputs=[actual_map, solution_map, actual_ac, solution_ac])
btn.click(fn=demo_plot, inputs=[city, facility], outputs=[actual_map, solution_map, actual_ac, solution_ac])
gr.Markdown("## FLP & IUMFLP Solver")
with gr.Column():
with gr.Row():
data_npy = gr.Textbox(label="Input")
data_file = gr.UploadButton(
label="πŸ“ Upload a npy file",
file_count="single",
file_types=[".npy"])
with gr.Row():
gr.Examples(
examples=get_example(),
inputs=[data_npy],
fn=solver_plot1,
outputs=[actual_map, solution_map, actual_ac, solution_ac],
)
with gr.Row():
boost = gr.Checkbox(label="Turbo Boost (accelerate solution generation with fewer SWAP steps)", value=False)
btn2 = gr.Button(value="πŸš€ Generate")
with gr.Row():
actual_map = gr.Plot(label='Initial Solution')
solution_map = gr.Plot(label='Final Solution')
with gr.Row():
actual_ac = gr.Textbox(label='Initial Access Cost')
solution_ac = gr.Textbox(label='Final Access Cost')
data_file.upload(fn=load_npy_file, inputs=[data_file], outputs=[data_npy])
btn2.click(fn=solver_plot, inputs=[data_npy, boost], outputs=[actual_map, solution_map, actual_ac, solution_ac])
if __name__ == "__main__":
demo.launch()