# Fire station location example using SciPy sparse arrays for efficiency.
#
# The fire station location problem attemps to minimize the number of fire stations
# to build amongst a set of towns, with each town being a candidate for
# hosting a fire station. Each town must be served by a fire station built
# on a town with a travel time no longer than a defined threshold (e.g. 15 minutes).
# In this example, we solve the location problem using a SciPy sparse
# matrix with the xpress.Dot() operator for efficiency.
#
# (C) 1983-2025 Fair Isaac Corporation
import xpress as xp
import numpy as np
import scipy
num_towns = 6 # Number of towns.
t_time = np.array([[ 0, 15, 25, 35, 35, 25], # Travel times between towns.
[15, 0, 30, 40, 25, 15],
[25, 30, 0, 20, 30, 25],
[35, 40, 20, 0, 20, 30],
[35, 25, 35, 20, 0, 19],
[25, 15, 25, 30, 19, 0]])
avail = (t_time <= 15).astype(int) # NumPy array of binary values equal to 1 if t_time <= 15.
avail_sparse = scipy.sparse.csr_array(avail) # Convert to SciPy sparse matrix format.
# Print travel times in both formats for comparison.
print("NumPy format: ", avail, sep="\n")
print("SciPy format: ", avail_sparse, sep="\n")
p = xp.problem() # Create Xpress problem.
x = p.addVariables(num_towns, vartype=xp.binary) # Create NumPy array of variables.
# Serve all towns, amongst those eligible to be selected for each.
p.addConstraint(xp.Dot(avail_sparse,x) >= 1) # Creates set of constraints with RHS = 1.
p.setObjective(xp.Sum(x)) # Minimize number of towns selected for a fire station.
p.optimize()
# Print solution.
print("Number of stations: ", round(p.attributes.objval))
xsol = p.getSolution(x)
print("Located at towns",[s+1 for s in range(num_towns) if xsol[s] >= 0.99])
|