1
2<p align="center">
3<img src="docs/_static/images/pysal_banner.svg" width="370" height="200" />
4</p>
5
6# `spopt`: Spatial Optimization
7
8#### Regionalization, facility location, and transportation-oriented modeling
9
10![tag](https://img.shields.io/github/v/release/pysal/spopt?include_prereleases&sort=semver)
11[![unittests](https://github.com/pysal/spopt/workflows/.github/workflows/unittests.yml/badge.svg)](https://github.com/pysal/spopt/actions?query=workflow%3A.github%2Fworkflows%2Funittests.yml)
12[![codecov](https://codecov.io/gh/pysal/spopt/branch/main/graph/badge.svg)](https://codecov.io/gh/pysal/spopt)
13[![Documentation](https://img.shields.io/static/v1.svg?label=docs&message=current&color=9cf)](http://pysal.org/spopt/)
14[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
15[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
16[![status](https://joss.theoj.org/papers/1413cf2c0cf3c561386949f2e1208563/status.svg)](https://joss.theoj.org/papers/1413cf2c0cf3c561386949f2e1208563)
17[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4444156.svg)](https://doi.org/10.5281/zenodo.4444156)
18
19Spopt is an open-source Python library for solving optimization problems with spatial data. Originating from the `region` module in [PySAL (Python Spatial Analysis Library)](http://pysal.org), it is under active development for the inclusion of newly proposed models and methods for regionalization, facility location, and transportation-oriented solutions.
20
21### Regionalization
22
23```python
24import spopt, libpysal, geopandas, numpy
25mexico = geopandas.read_file(libpysal.examples.get_path("mexicojoin.shp"))
26mexico["count"] = 1
27attrs = [f"PCGDP{year}" for year in range(1950, 2010, 10)]
28w = libpysal.weights.Queen.from_dataframe(mexico)
29mexico["count"], threshold_name, threshold, top_n = 1, "count", 4, 2
30numpy.random.seed(123456)
31model = spopt.MaxPHeuristic(mexico, w, attrs, threshold_name, threshold, top_n)
32model.solve()
33mexico["maxp_new"] = model.labels_
34mexico.plot(column="maxp_new", categorical=True, figsize=(12,8), ec="w");
35```
36<p align="center">
37<img src="docs/_static/images/maxp.svg" height="350" />
38</p>
39
40### Locate
41```python
42from spopt.locate.coverage import MCLP
43from spopt.locate.util import simulated_geo_points
44import numpy
45import geopandas
46import pulp
47import spaghetti
48
49solver = pulp.PULP_CBC_CMD(msg=False)
50lattice = spaghetti.regular_lattice((0, 0, 10, 10), 9, exterior=True)
51ntw = spaghetti.Network(in_data=lattice)
52street = spaghetti.element_as_gdf(ntw, arcs=True)
53street_buffered = geopandas.GeoDataFrame(
54    geopandas.GeoSeries(street["geometry"].buffer(0.2).unary_union),
55    crs=street.crs,
56    columns=["geometry"],
57)
58client_points = simulated_geo_points(street_buffered, needed=CLIENT_COUNT, seed=CLIENT_SEED)
59facility_points = simulated_geo_points(
60    street_buffered, needed=FACILITY_COUNT, seed=FACILITY_SEED
61)
62ntw.snapobservations(client_points, "clients", attribute=True)
63clients_snapped = spaghetti.element_as_gdf(
64    ntw, pp_name="clients", snapped=True
65)
66
67ntw.snapobservations(facility_points, "facilities", attribute=True)
68facilities_snapped = spaghetti.element_as_gdf(
69    ntw, pp_name="facilities", snapped=True
70)
71cost_matrix = ntw.allneighbordistances(
72    sourcepattern=ntw.pointpatterns["clients"],
73    destpattern=ntw.pointpatterns["facilities"],
74)
75mclp_from_cost_matrix = MCLP.from_cost_matrix(cost_matrix, ai, MAX_COVERAGE, p_facilities=P_FACILITIES)
76mclp_from_cost_matrix = mclp_from_cost_matrix.solve(solver)
77```
78<p align="center">
79<img src="docs/_static/images/mclp.svg" height="350" />
80</p>
81
82## Examples
83More examples can be found in the [Tutorials](https://pysal.org/spopt/tutorials.html) section of the documentation.
84- [Max-p-regions problem](https://pysal.org/spopt/notebooks/maxp.html)
85- [Skater](https://pysal.org/spopt/notebooks/skater.html)
86- [Region K means](https://pysal.org/spopt/notebooks/reg-k-means.html)
87- [Facility Location Real World Problem](https://pysal.org/spopt/notebooks/facloc-real-world.html)
88
89All examples can be run interactively by launching this repository as a [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/pysal/spopt/main).
90
91## Requirements
92- [scipy](http://scipy.github.io/devdocs/)
93- [numpy](https://numpy.org/devdocs/)
94- [pandas](https://pandas.pydata.org/docs/)
95- [networkx](https://networkx.org/)
96- [libpysal](https://pysal.org/libpysal/)
97- [scikit-learn](https://scikit-learn.org/stable/)
98- [geopandas](https://geopandas.org/)
99- [pulp](https://coin-or.github.io/pulp/)
100- [spaghetti](https://github.com/pysal/spaghetti)
101
102## Installation
103spopt is available on the [Python Package Index](https://pypi.org/). Therefore, you can either install directly with pip from the command line:
104```
105$ pip install -U spopt
106```
107or download the source distribution (.tar.gz) and decompress it to your selected destination. Open a command shell and navigate to the decompressed folder. Type:
108```
109$ pip install .
110```
111You may also install the latest stable spopt via conda-forge channel by running:
112```
113$ conda install --channel conda-forge spopt
114```
115
116## Contribute
117
118PySAL-spopt is under active development and contributors are welcome.
119
120If you have any suggestions, feature requests, or bug reports, please open new [issues](https://github.com/pysal/spopt/issues) on GitHub. To submit patches, please review [PySAL's documentation for developers](https://pysal.org/docs/devs/), the PySAL [development guidelines](https://github.com/pysal/pysal/wiki), the `spopt` [contributing guidelines](https://github.com/pysal/spopt/blob/main/.github/CONTRIBUTING.md) before  opening a [pull request](https://github.com/pysal/spopt/pulls). Once your changes get merged, you’ll automatically be added to the [Contributors List](https://github.com/pysal/spopt/graphs/contributors).
121
122
123## Support
124If you are having trouble, please [create an issue](https://github.com/pysal/spopt/issues), [start a discussion](https://github.com/pysal/spopt/discussions), or talk to us in the [gitter room](https://gitter.im/pysal/spopt).
125
126## Code of Conduct
127
128As a PySAL-federated project, `spopt` follows the [Code of Conduct](https://github.com/pysal/governance/blob/main/conduct/code_of_conduct.rst) under the [PySAL governance model](https://github.com/pysal/governance).
129
130
131## License
132
133The project is licensed under the [BSD 3-Clause license](https://github.com/pysal/spopt/blob/main/LICENSE.txt).
134
135
136## Citation
137
138If you use PySAL-spopt in a scientific publication, we would appreciate using the following citation:
139
140```
141@misc{spopt2021,
142    author    = {Feng, Xin, and Gaboardi, James D. and Knaap, Elijah and Rey, Sergio J. and Wei, Ran},
143    month     = {jan},
144    year      = {2021},
145    title     = {pysal/spopt},
146    url       = {https://github.com/pysal/spopt},
147    doi       = {10.5281/zenodo.4444156},
148    keywords  = {python,regionalization,spatial-optimization,location-modeling}
149}
150```
151
152## Funding
153
154This project is/was partially funded through:
155
156[<img align="middle" src="docs/_static/images/nsf_logo.png" width="75">](https://www.nsf.gov/index.jsp) National Science Foundation Award #1831615: [RIDIR: Scalable Geospatial Analytics for Social Science Research](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1831615)
157
158<!-- [<img align="middle" src="docs/_static/image/IMAGE2.png" width="150">](link2) Some text2: [Project title 2](another_link2) -->
159