Skip to content

Commit

Permalink
doc: add examples section
Browse files Browse the repository at this point in the history
  • Loading branch information
gegen07 committed Sep 24, 2021
1 parent 06ae670 commit a1f02b3
Show file tree
Hide file tree
Showing 6 changed files with 436 additions and 6 deletions.
11 changes: 11 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@ Model based approaches for aggregating a large set of geographic units (with sma
region.Spenc
region.WardSpatial

Locate Methods
--------------

.. autosummary::
:toctree: generated/

locate.coverage.LSCP
locate.coverage.MCLP
locate.PCenter
locate.PMedian


19 changes: 17 additions & 2 deletions spopt/locate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class BaseOutputMixin:

def client_facility_array(self) -> None:
"""
Create an array 2d $m$ x $n$, where m is number of clients and n is number of facilities.
Create an array 2d MxN, where m is number of clients and n is number of facilities.
"""
if hasattr(self, "fac2cli"):
self.cli2fac = [[] for i in range(self.aij.shape[0])]
Expand All @@ -63,7 +63,7 @@ def uncovered_clients(self) -> None:

class CoveragePercentageMixin:
"""
Mixin for calculate the percentage of area covered
Mixin to calculate the percentage of area covered
"""

def get_percentage(self):
Expand All @@ -74,7 +74,22 @@ def get_percentage(self):


class MeanDistanceMixin:
"""
Mixin to calculate the mean distance between demand and facility sites chosen
"""

def get_mean_distance(self, weight: np.array):
"""
Calculate the mean distance
Parameters
----------
weight: np.array
weight of all demand points
Returns
-------
None
"""
self.mean_dist = self.problem.objective.value() / weight.sum()


Expand Down
195 changes: 193 additions & 2 deletions spopt/locate/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,51 @@ def from_cost_matrix(
Returns
-------
LSCP object
Examples
--------
>>> from spopt.locate.coverage import LSCP
>>> from spopt.locate.util import simulated_geo_points
>>> import pulp
>>> import spaghetti
Create regular lattice
>>> lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)
>>> ntw = spaghetti.Network(in_data=lattice)
>>> street = spaghetti.element_as_gdf(ntw, arcs=True)
>>> street_buffered = geopandas.GeoDataFrame(
... geopandas.GeoSeries(street["geometry"].buffer(0.2).unary_union),
... crs=street.crs,
... columns=["geometry"])
Simulate points belong to lattice
>>> demand_points = simulated_geo_points(street_buffered, needed=100, seed=5)
>>> facility_points = simulated_geo_points(street_buffered, needed=5, seed=6)
Snap points to the network
>>> ntw.snapobservations(demand_points, "clients", attribute=True)
>>> clients_snapped = spaghetti.element_as_gdf(ntw, pp_name="clients", snapped=True)
>>> ntw.snapobservations(facility_points, "facilities", attribute=True)
>>> facilities_snapped = spaghetti.element_as_gdf(ntw, pp_name="facilities", snapped=True)
Calculate the cost matrix
>>> cost_matrix = ntw.allneighbordistances(
... sourcepattern=ntw.pointpatterns["clients"],
... destpattern=ntw.pointpatterns["facilities"])
Create LSCP instance from cost matrix
>>> lscp_from_cost_matrix = LSCP.from_cost_matrix(cost_matrix, max_coverage=8)
>>> lscp_from_cost_matrix = lscp_from_cost_matrix.solve(pulp.PULP_CBC_CMD(msg=False))
Get facility lookup demand coverage array
>>> lscp_from_cost_matrix.facility_client_array()
>>> lscp_from_cost_matrix.fac2cli
"""

r_fac = range(cost_matrix.shape[1])
Expand Down Expand Up @@ -116,6 +161,48 @@ def from_geodataframe(
Returns
-------
LSCP object
Examples
--------
>>> from spopt.locate.coverage import LSCP
>>> from spopt.locate.util import simulated_geo_points
>>> import pulp
>>> import spaghetti
Create regular lattice
>>> lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)
>>> ntw = spaghetti.Network(in_data=lattice)
>>> street = spaghetti.element_as_gdf(ntw, arcs=True)
>>> street_buffered = geopandas.GeoDataFrame(
... geopandas.GeoSeries(street["geometry"].buffer(0.2).unary_union),
... crs=street.crs,
... columns=["geometry"])
Simulate points belong to lattice
>>> demand_points = simulated_geo_points(street_buffered, needed=100, seed=5)
>>> facility_points = simulated_geo_points(street_buffered, needed=5, seed=6)
Snap points to the network
>>> ntw.snapobservations(demand_points, "clients", attribute=True)
>>> clients_snapped = spaghetti.element_as_gdf(ntw, pp_name="clients", snapped=True)
>>> ntw.snapobservations(facility_points, "facilities", attribute=True)
>>> facilities_snapped = spaghetti.element_as_gdf(ntw, pp_name="facilities", snapped=True)
Create LSCP instance from cost matrix
>>> lscp_from_geodataframe = LSCP.from_geodataframe(clients_snapped, facilities_snapped,
... "geometry", "geometry",
... max_coverage=8, distance_metric="euclidean")
>>> lscp_from_geodataframe = lscp_from_geodataframe.solve(pulp.PULP_CBC_CMD(msg=False))
Get facility lookup demand coverage array
>>> lscp_from_geodataframe.facility_client_array()
>>> lscp_from_geodataframe.fac2cli
"""

dem = gdf_demand[demand_col]
Expand Down Expand Up @@ -152,7 +239,7 @@ def from_geodataframe(

def facility_client_array(self) -> None:
"""
Create an array 2d $m$ x $n$, where m is number of facilities and n is number of clients. Each row represent a facility and has an array containing clients index meaning that the $facility_0$ cover the entire array.
Create an array 2d MxN, where m is number of facilities and n is number of clients. Each row represent a facility and has an array containing clients index meaning that the facility-i cover the entire array.
Returns
-------
Expand Down Expand Up @@ -250,6 +337,56 @@ def from_cost_matrix(
Returns
-------
MCLP object
Examples
--------
>>> from spopt.locate.coverage import MCLP
>>> from spopt.locate.util import simulated_geo_points
>>> import pulp
>>> import spaghetti
Create regular lattice
>>> lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)
>>> ntw = spaghetti.Network(in_data=lattice)
>>> street = spaghetti.element_as_gdf(ntw, arcs=True)
>>> street_buffered = geopandas.GeoDataFrame(
... geopandas.GeoSeries(street["geometry"].buffer(0.2).unary_union),
... crs=street.crs,
... columns=["geometry"])
Simulate points belong to lattice
>>> demand_points = simulated_geo_points(street_buffered, needed=100, seed=5)
>>> facility_points = simulated_geo_points(street_buffered, needed=5, seed=6)
Snap points to the network
>>> ntw.snapobservations(demand_points, "clients", attribute=True)
>>> clients_snapped = spaghetti.element_as_gdf(ntw, pp_name="clients", snapped=True)
>>> ntw.snapobservations(facility_points, "facilities", attribute=True)
>>> facilities_snapped = spaghetti.element_as_gdf(ntw, pp_name="facilities", snapped=True)
Calculate the cost matrix
>>> cost_matrix = ntw.allneighbordistances(
... sourcepattern=ntw.pointpatterns["clients"],
... destpattern=ntw.pointpatterns["facilities"])
Simulate demand weights from 1 to 12
>>> ai = numpy.random.randint(1, 12, 100)
Create MCLP instance from cost matrix
>>> mclp_from_cost_matrix = MCLP.from_cost_matrix(cost_matrix, ai, max_coverage=7, p_facilities=4)
>>> mclp_from_cost_matrix = mclp_from_cost_matrix.solve(pulp.PULP_CBC_CMD(msg=False))
Get facility lookup demand coverage array
>>> mclp_from_cost_matrix.facility_client_array()
>>> mclp_from_cost_matrix.fac2cli
"""
r_fac = range(cost_matrix.shape[1])
r_cli = range(cost_matrix.shape[0])
Expand Down Expand Up @@ -313,6 +450,60 @@ def from_geodataframe(
Returns
-------
MCLP object
Examples
--------
>>> from spopt.locate.coverage import MCLP
>>> from spopt.locate.util import simulated_geo_points
>>> import pulp
>>> import spaghetti
Create regular lattice
>>> lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)
>>> ntw = spaghetti.Network(in_data=lattice)
>>> street = spaghetti.element_as_gdf(ntw, arcs=True)
>>> street_buffered = geopandas.GeoDataFrame(
... geopandas.GeoSeries(street["geometry"].buffer(0.2).unary_union),
... crs=street.crs,
... columns=["geometry"])
Simulate points belong to lattice
>>> demand_points = simulated_geo_points(street_buffered, needed=100, seed=5)
>>> facility_points = simulated_geo_points(street_buffered, needed=5, seed=6)
Snap points to the network
>>> ntw.snapobservations(demand_points, "clients", attribute=True)
>>> clients_snapped = spaghetti.element_as_gdf(ntw, pp_name="clients", snapped=True)
>>> ntw.snapobservations(facility_points, "facilities", attribute=True)
>>> facilities_snapped = spaghetti.element_as_gdf(ntw, pp_name="facilities", snapped=True)
Simulate demand weights from 1 to 12
>>> ai = numpy.random.randint(1, 12, 100)
>>> clients_snapped['weights'] = ai
Create MCLP instance from geodataframe
>>> mclp_from_geodataframe = MCLP.from_geodataframe(
... clients_snapped,
... facilities_snapped,
... "geometry",
... "geometry",
... "weights",
... max_coverage=7,
... p_facilities=4,
... distance_metric="euclidean"
... )
>>> mclp_from_geodataframe = mclp_from_geodataframe.solve(pulp.PULP_CBC_CMD(msg=False))
Get facility lookup demand coverage array
>>> mclp_from_geodataframe.facility_client_array()
>>> mclp_from_geodataframe.fac2cli
"""
service_load = gdf_demand[weights_cols].to_numpy()
dem = gdf_demand[demand_col]
Expand Down Expand Up @@ -351,7 +542,7 @@ def from_geodataframe(

def facility_client_array(self) -> None:
"""
Create an array 2d $m$ x $n$, where m is number of facilities and n is number of clients. Each row represent a facility and has an array containing clients index meaning that the $facility_0$ cover the entire array.
Create an array 2d MxN, where m is number of facilities and n is number of clients. Each row represent a facility and has an array containing clients index meaning that the facility-i cover the entire array.
Returns
-------
Expand Down
Loading

0 comments on commit a1f02b3

Please sign in to comment.