Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8,912 changes: 186 additions & 8,726 deletions notebooks/lscp.ipynb

Large diffs are not rendered by default.

3,014 changes: 207 additions & 2,807 deletions notebooks/mclp.ipynb

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions spopt/locate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,37 @@ def add_facility_constraint(
"before setting constraints must set facility variable"
)

@staticmethod
def add_predefined_facility_constraint(
obj: T_FacModel, model: pulp.LpProblem, predefined_fac: np.array
) -> None:
"""
predefined demand constraint

Parameters
----------
obj: T_FacModel
bounded type of LocateSolver class
model: pulp.LpProblem
optimization model problem
facility_indexes: np.array
facility indexes zeroindexed already located

Returns
-------
None
"""
if hasattr(obj, "fac_vars"):
fac_vars = getattr(obj, "fac_vars")
for ind in range(len(predefined_fac)):
if predefined_fac[ind]:
fac_vars[ind].setInitialValue(1)
fac_vars[ind].fixValue()
else:
raise AttributeError(
"before predefined facility must set facility variable"
)

@staticmethod
def add_maximal_coverage_constraint(
obj: T_FacModel, model, ni, range_facility, range_client
Expand Down Expand Up @@ -306,6 +337,7 @@ def add_maximal_coverage_constraint(
if hasattr(obj, "fac_vars") and hasattr(obj, "cli_vars"):
fac_vars = getattr(obj, "fac_vars")
dem_vars = getattr(obj, "cli_vars")

for i in range_client:
model += (
pulp.lpSum([ni[i][j] * fac_vars[j] for j in range_facility])
Expand Down
31 changes: 28 additions & 3 deletions spopt/locate/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def __add_obj(self) -> None:

@classmethod
def from_cost_matrix(
cls, cost_matrix: np.array, max_coverage: float, name: str = "LSCP"
cls, cost_matrix: np.array, max_coverage: float, predefined_facilities_arr: np.array = None, name: str = "LSCP"
):
"""
Create a LSCP object based on cost matrix.
Expand Down Expand Up @@ -119,6 +119,9 @@ def from_cost_matrix(
lscp.aij = np.zeros(cost_matrix.shape)
lscp.aij[cost_matrix <= max_coverage] = 1

if predefined_facilities_arr is not None:
FacilityModelBuilder.add_predefined_facility_constraint(lscp, lscp.problem, predefined_facilities_arr)

lscp.__add_obj()
FacilityModelBuilder.add_set_covering_constraint(
lscp, lscp.problem, lscp.aij, r_fac, r_cli
Expand All @@ -134,6 +137,7 @@ def from_geodataframe(
demand_col: str,
facility_col: str,
max_coverage: float,
predefined_facility_col: str = None,
distance_metric: str = "euclidean",
name: str = "LSCP",
):
Expand Down Expand Up @@ -205,6 +209,10 @@ def from_geodataframe(

"""

predefined_facilities_arr = None
if predefined_facility_col is not None:
predefined_facilities_arr = gdf_fac[predefined_facility_col].to_numpy()

dem = gdf_demand[demand_col]
fac = gdf_fac[facility_col]

Expand Down Expand Up @@ -235,7 +243,7 @@ def from_geodataframe(

distances = cdist(dem_data, fac_data, distance_metric)

return cls.from_cost_matrix(distances, max_coverage, name)
return cls.from_cost_matrix(distances, max_coverage, predefined_facilities_arr, name)

def facility_client_array(self) -> None:
"""
Expand Down Expand Up @@ -316,6 +324,7 @@ def from_cost_matrix(
weights: np.array,
max_coverage: float,
p_facilities: int,
predefined_facilities_arr: np.array = None,
name: str = "MCLP",
):
"""
Expand All @@ -331,6 +340,8 @@ def from_cost_matrix(
maximum acceptable service distance by problem
p_facilities: int
number of facilities to be located
predefined_facilities_arr: np.array, default=None
bool array defining which facilities are already defined
name: str, default="MCLP"
name of the problem

Expand Down Expand Up @@ -402,11 +413,17 @@ def from_cost_matrix(
weights = np.reshape(weights, (cost_matrix.shape[0], 1))

mclp.__add_obj(weights, r_cli)

if predefined_facilities_arr is not None:
FacilityModelBuilder.add_predefined_facility_constraint(mclp, mclp.problem, predefined_facilities_arr)

FacilityModelBuilder.add_maximal_coverage_constraint(
mclp, mclp.problem, mclp.aij, r_fac, r_cli
)

FacilityModelBuilder.add_facility_constraint(mclp, mclp.problem, p_facilities)


return mclp

@classmethod
Expand All @@ -419,6 +436,7 @@ def from_geodataframe(
weights_cols: str,
max_coverage: float,
p_facilities: int,
predefined_facility_col: str = None,
distance_metric: str = "euclidean",
name: str = "MCLP",
):
Expand All @@ -442,6 +460,8 @@ def from_geodataframe(
maximum acceptable service distance by problem
p_facilities: int
number of facilities to be located
predefined_facility_col: np.array, default=None
column name representing facilities are already defined
distance_metric: str, default="euclidean"
metrics supported by :method: `scipy.spatial.distance.cdist` used for the distance calculations
name: str, default="MCLP"
Expand Down Expand Up @@ -505,6 +525,11 @@ def from_geodataframe(
>>> mclp_from_geodataframe.facility_client_array()
>>> mclp_from_geodataframe.fac2cli
"""

predefined_facilities_arr = None
if predefined_facility_col is not None:
predefined_facilities_arr = gdf_fac[predefined_facility_col].to_numpy()

service_load = gdf_demand[weights_cols].to_numpy()
dem = gdf_demand[demand_col]
fac = gdf_fac[facility_col]
Expand Down Expand Up @@ -537,7 +562,7 @@ def from_geodataframe(
distances = cdist(dem_data, fac_data, distance_metric)

return cls.from_cost_matrix(
distances, service_load, max_coverage, p_facilities, name
distances, service_load, max_coverage, p_facilities, predefined_facilities_arr, name
)

def facility_client_array(self) -> None:
Expand Down
Binary file not shown.
Binary file not shown.
Loading