Make an application for facility location otpimization.
To upload files, please first save the app
import streamlit as st
import numpy as np
import pandas as pd
import plotly.express as px
from scipy.spatial.distance import cdist
from scipy.optimize import minimize
def objective_function(facility_locations, customer_locations, weights):
"""Calculate total weighted distance from facilities to customers"""
# Reshape facility locations to correct format (num_facilities x 2)
facility_coords = facility_locations.reshape(-1, 2)
# Calculate distances between all facilities and customers
distances = cdist(facility_coords, customer_locations)
# For each customer, find the nearest facility
min_distances = np.min(distances, axis=0)
# Calculate total weighted distance
total_cost = np.sum(min_distances * weights)
return total_cost
st.title("Facility Location Optimizer")
st.write("""
This app helps optimize the placement of facilities to minimize the total weighted distance to customers.
Upload your customer data or use random data to simulate the optimization.
""")
# Sidebar controls
st.sidebar.header("Parameters")
num_facilities = st.sidebar.slider("Number of facilities", 1, 10, 3)
num_customers = st.sidebar.slider("Number of customers", 10, 200, 50)
use_random = st.sidebar.checkbox("Use random data", True)
if use_random:
# Generate random customer locations
np.random.seed(42)
customer_locations = np.random.rand(num_customers, 2) * 100
weights = np.random.uniform(1, 10, num_customers) # Random weights/demand
else:
st.write("Upload customer data (CSV with columns: x, y, weight)")
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
if uploaded_file is not None:
data = pd.read_csv(uploaded_file)
customer_locations = data[['x', 'y']].values
weights = data['weight'].values
num_customers = len(customer_locations)
else:
st.warning("Please upload data or use random data")
st.stop()
# Initialize facility locations randomly
initial_locations = np.random.rand(num_facilities * 2) * 100
# Optimize facility locations
if st.button("Optimize Locations"):
with st.spinner("Optimizing facility locations..."):
result = minimize(
objective_function,
initial_locations,
args=(customer_locations, weights),
method='Nelder-Mead'
)
optimal_locations = result.x.reshape(-1, 2)
# Create DataFrame for visualization
facility_df = pd.DataFrame(optimal_locations, columns=['x', 'y'])
customer_df = pd.DataFrame(customer_locations, columns=['x', 'y'])
customer_df['weight'] = weights
# Plot results
fig = px.scatter(customer_df, x='x', y='y', size='weight',
title="Optimal Facility Locations",
labels={'x': 'X Coordinate', 'y': 'Y Coordinate'},
size_max=20)
# Add facilities to the plot
fig.add_scatter(x=facility_df['x'], y=facility_df['y'],
mode='markers',
marker=dict(size=15, symbol='star', color='red'),
name='Facilities')
st.plotly_chart(fig)
st.success(f"Optimization complete! Final objective value: {result.fun:.2f}")
# Display facility coordinates
st.subheader("Optimal Facility Coordinates")
st.dataframe(facility_df.round(2))
# Show explanation
st.markdown("""
### How it works
1. The algorithm takes customer locations and their weights (demand) as input
2. It minimizes the total weighted distance between customers and their nearest facilities
3. The optimization uses the Nelder-Mead method to find the best facility locations
4. Results show optimal facility locations (red stars) and customer locations (blue circles)
5. Circle size represents customer weight/demand
### Tips
- Use the sidebar to adjust the number of facilities and customers
- Toggle between random data and your own CSV file
- Click the "Optimize Locations" button to run the optimization
- The optimization might give slightly different results each time due to random initialization
""")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?