Giter Club home page Giter Club logo

spopt's Introduction

spopt: Spatial Optimization

Regionalization, facility location, and transportation-oriented modeling

tag unittests codecov Documentation License Code style: black status DOI

Spopt is an open-source Python library for solving optimization problems with spatial data. Originating from the region module in PySAL (Python Spatial Analysis Library), it is under active development for the inclusion of newly proposed models and methods for regionalization, facility location, and transportation-oriented solutions.

Regionalization

import spopt, libpysal, geopandas, numpy
mexico = geopandas.read_file(libpysal.examples.get_path("mexicojoin.shp"))
mexico["count"] = 1
attrs = [f"PCGDP{year}" for year in range(1950, 2010, 10)]
w = libpysal.weights.Queen.from_dataframe(mexico)
mexico["count"], threshold_name, threshold, top_n = 1, "count", 4, 2
numpy.random.seed(123456)
model = spopt.MaxPHeuristic(mexico, w, attrs, threshold_name, threshold, top_n)
model.solve()
mexico["maxp_new"] = model.labels_
mexico.plot(column="maxp_new", categorical=True, figsize=(12,8), ec="w");

Locate

from spopt.locate.coverage import MCLP
from spopt.locate.util import simulated_geo_points
import numpy
import geopandas
import pulp
import spaghetti

solver = pulp.PULP_CBC_CMD(msg=False)
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"],
)
client_points = simulated_geo_points(street_buffered, needed=CLIENT_COUNT, seed=CLIENT_SEED)
facility_points = simulated_geo_points(
    street_buffered, needed=FACILITY_COUNT, seed=FACILITY_SEED
)
ntw.snapobservations(client_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
)
cost_matrix = ntw.allneighbordistances(
    sourcepattern=ntw.pointpatterns["clients"],
    destpattern=ntw.pointpatterns["facilities"],
)
mclp_from_cost_matrix = MCLP.from_cost_matrix(cost_matrix, ai, MAX_COVERAGE, p_facilities=P_FACILITIES)
mclp_from_cost_matrix = mclp_from_cost_matrix.solve(solver)

Examples

More examples can be found in the Tutorials section of the documentation.

All examples can be run interactively by launching this repository as a Binder.

Requirements

Installation

spopt is available on the Python Package Index. Therefore, you can either install directly with pip from the command line:

$ pip install -U spopt

or download the source distribution (.tar.gz) and decompress it to your selected destination. Open a command shell and navigate to the decompressed folder. Type:

$ pip install .

You may also install the latest stable spopt via conda-forge channel by running:

$ conda install --channel conda-forge spopt

Contribute

PySAL-spopt is under active development and contributors are welcome.

If you have any suggestions, feature requests, or bug reports, please open new issues on GitHub. To submit patches, please review PySAL's documentation for developers, the PySAL development guidelines, the spopt contributing guidelines before opening a pull request. Once your changes get merged, you’ll automatically be added to the Contributors List.

Support

If you are having trouble, please create an issue, start a discussion, or talk to us in the gitter room.

Code of Conduct

As a PySAL-federated project, spopt follows the Code of Conduct under the PySAL governance model.

License

The project is licensed under the BSD 3-Clause license.

Citation

If you use PySAL-spopt in a scientific publication, we would appreciate using the following citations:

@misc{spopt2021,
    author    = {Feng, Xin, and Gaboardi, James D. and Knaap, Elijah and
                Rey, Sergio J. and Wei, Ran},
    month     = {jan},
    year      = {2021},
    title     = {pysal/spopt},
    url       = {https://github.com/pysal/spopt},
    doi       = {10.5281/zenodo.4444156},
    keywords  = {python,regionalization,spatial-optimization,location-modeling}
}

@article{spopt2022,
    author    = {Feng, Xin and Barcelos, Germano and Gaboardi, James D. and
                Knaap, Elijah and Wei, Ran and Wolf, Levi J. and
                Zhao, Qunshan and Rey, Sergio J.},
    year      = {2022},
    title     = {spopt: a python package for solving spatial optimization problems in PySAL},
    journal   = {Journal of Open Source Software},
    publisher = {The Open Journal},
    volume    = {7},
    number    = {74},
    pages     = {3330},
    url       = {https://doi.org/10.21105/joss.03330},
    doi       = {10.21105/joss.03330},
}

Funding

This project is/was partially funded through:

National Science Foundation Award #1831615: RIDIR: Scalable Geospatial Analytics for Social Science Research

spopt's People

Contributors

jgaboardi avatar sjsrey avatar erinrolson avatar gegen07 avatar knaaptime avatar xf37 avatar dependabot[bot] avatar rwei5 avatar martinfleis avatar pedrocamargo avatar

Watchers

 avatar  avatar

spopt's Issues

Add backup constraint raising AttributeError

@erinrolson I think for statement should be ident inside if, and the else of LOC 402 will be for the if clause and not for the for statements.

if len(fac_vars) > 0: #hasattr(self, "fac_vars"):
#!fac_vars = getattr(self, "fac_vars")
fac_vars = self.fac_vars
#!cli_vars = getattr(self, "cli_vars")
cli_vars = self.cli_vars
for i in range_client:
if sum(ni[i]) >= 2: # demand unit has backup coverage
model += (
pulp.lpSum( [ int( ni[i][j] ) * fac_vars[j] for j in range_facility ] ) >= 1 + 1*cli_vars[i]
)
else: #demand unit does not have backup coverage
model += (
pulp.lpSum( [ int( ni[i][j] ) * fac_vars[j] for j in range_facility ] ) >= 1 + 0*cli_vars[i]
)
else:
raise AttributeError(
"before setting constraints must set facility variable"
)

self.AssertWarns(Warning) LSCPB testing

I modified the following functions to account for LSCP solving producing a RuntimeError. Is this an appropriate way to handle the LSCP error and still test the warnings? These tests are passing with my modifications.

def test_warning_lscpb_facility_geodataframe(self):
with self.assertWarns(Warning):
with self.assertRaises(RuntimeError):
dummy_class = LSCPB.from_geodataframe(
self.gdf_dem,
self.gdf_fac,
"geometry",
"geometry",
10,
pulp.PULP_CBC_CMD(msg=False),
)

def test_warning_lscpb_demand_geodataframe(self):
    with self.assertWarns(Warning):
        with self.assertRaises(RuntimeError):
            dummy_class = LSCPB.from_geodataframe(
                self.gdf_dem_buffered,
                self.gdf_fac,
                "geometry",
                "geometry",
                10,
                pulp.PULP_CBC_CMD(msg=False),
            )

self.AssertRaises(RuntimeError) for LSCPB testing

The tests listed below are failing, but are producing a RuntimeError as desired. I think this is because when the LSCPB object fails it is because LSCP is infeasible, thus the error is produced from the LSCP object not the LSCPB object. How can we get these tests to pass?

FAILED spopt/tests/test_lscpb.py::TestRealWorldLocate::test_infeasibility_lscpb_from_geodataframe - RuntimeError: Mode...
FAILED spopt/tests/test_lscpb.py::TestErrorsWarnings::test_warning_lscpb_demand_geodataframe - RuntimeError: Model is ...
FAILED spopt/tests/test_lscpb.py::TestErrorsWarnings::test_warning_lscpb_facility_geodataframe - RuntimeError: Model i...
FAILED spopt/tests/test_lscpb.py::TestRealWorldLocate::test_infeasibility_lscpb_from_cost_matrix - RuntimeError: Model...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.