def test_cc_threshold(self):
     ccthreshold = covering.create_cc_threshold_model(self.partial_coverage2, 80)
     ccthreshold_i = covering.create_cc_threshold_model(self.partial_coverage2, 100)
     ccthreshold.solve(pulp.GUROBI())
     ccthreshold_i.solve(pulp.GUROBI())
     ids = utilities.get_ids(ccthreshold, "facility2_service_areas")
     self.assertEqual(['1', '10', '11', '13', '15', '17', '19', '20', '21', '22', '3', '4', '7', '9'], ids)
     self.assertEqual(ccthreshold_i.status, pulp.constants.LpStatusInfeasible)
예제 #2
0
 def test_cc_threshold(self):
     ccthreshold = covering.create_cc_threshold_model(
         self.partial_coverage2, 80)
     ccthreshold_i = covering.create_cc_threshold_model(
         self.partial_coverage2, 100)
     ccthreshold.solve(pulp.GLPK())
     ccthreshold_i.solve(pulp.GLPK())
     ids = utilities.get_ids(ccthreshold, "facility2_service_areas")
     self.assertEqual([
         '1', '11', '13', '15', '17', '19', '20', '21', '22', '3', '4', '5',
         '7', '9'
     ], ids)
     self.assertEqual(ccthreshold_i.status,
                      pulp.constants.LpStatusInfeasible)
예제 #3
0
 def test_cc_threshold(self):
     ccthreshold = covering.create_cc_threshold_model(
         self.partial_coverage2, 80, "ccthreshold.lp")
     ccthreshold.solve(pulp.GLPK())
     ids = utilities.get_ids(ccthreshold, "facility2_service_areas")
     self.assertEqual([
         '1', '11', '13', '15', '17', '19', '20', '21', '22', '3', '4', '5',
         '7', '9'
     ], ids)
예제 #4
0
    def model(self):
        # Run a threshold model on a provided demand and response_area layer

        self._create_run_dirs()

        # TODO: Figure out why it is necessary to reload here rather than just using the layer.
        block_layer = QgsVectorLayer(self.paths['block_shp_output'], "block_layer", "ogr")
        response_area_layer = QgsVectorLayer(self.paths['responder_shp_output'], "response_area_layer", "ogr")
        if self.logger:
            self.logger.info("Reloaded layers from file. Found {} blocks and {} response areas."
                             .format(len(list(block_layer.getFeatures())),
                              len(list(response_area_layer.getFeatures()))))

        binary_coverage_polygon = pyqgis_analysis.generate_partial_coverage(block_layer, response_area_layer,
                                                                            "demand", "point_id", "area_id")
        # TODO: Build a handler which selects the proper model based on config
        # TODO: Move this code into a function (class?) for partial_coverage_threshold
        # Create the mclp model
        if self.logger:
            self.logger.info("Creating MCLP model...")
        mclp = covering.create_cc_threshold_model(binary_coverage_polygon, self.model_run_config['thresholds'])
        # Solve the model using GLPK
        if self.logger:
            self.logger.info("Solving MCLP...")

        mclp.solve(solvers.PULP_CBC_CMD())
        self.problem = mclp
        if pulp.LpStatus[mclp.status] == "Infeasible":
            print(pulp.LpStatus[mclp.status])
            print("Model run {} deemed infeasible. Skipping...".format(self.model_run_config['run_name']))
            self.status = pulp.LpStatus[mclp.status]
            self.results.parse_model_output(self)
            return

        # TODO: Move result extraction into it's own function (or tie to partial_coverage_model object)
        if self.logger:
            self.logger.info("Extracting results")
        ids = utilities.get_ids(mclp, "responder_layer")
        self.area_ids = ids
        point_ids = [str(ft['from_point']) for ft in list(response_area_layer.getFeatures()) if str(ft['area_id']) in ids]
        self.point_ids = point_ids
        # Generate a query that could be used as a definition query or selection in arcpy
        select_query = pyqgis_analysis.generate_query(ids, unique_field_name="area_id")
        point_select_query = pyqgis_analysis.generate_query(point_ids, unique_field_name="point_id")
        if self.logger:
            self.logger.info("Output query to use to generate response area maps is: {}".format(select_query))
            self.logger.info("Output query to use to generate response point maps is: {}".format(point_select_query))
        # Determine how much demand is covered by the results
        self.selected_points = SelectedPointsLayer().copy(RoadPointLayer(layer=self.road_points))
        self.selected_points.layer.setSubsetString(point_select_query)
        self.selected_areas = SelectedAreasLayer().copy(ResponderLayer(layer=self.response_areas))
        self.selected_areas.layer.setSubsetString(select_query)
        self.results.parse_model_output(self)
        # TODO: Fix calculation of covered demand and add to output
        #total_coverage = pyqgis_analysis.get_covered_demand(block_layer, "demand", "partial",
        #                                                    response_area_layer)
        if self.logger:
            # self.logger.info(
            # "{0:.2f}% of demand is covered".format((100 * total_coverage) / binary_coverage_polygon["totalDemand"]))
            self.logger.info("{} responders".format(len(ids)))
        _write_shp_file(self.selected_areas.layer, self.paths['model_result_shp_output'])
        _write_shp_file(self.selected_points.layer, self.paths['selected_points_shp_output'])
        self._write_qgs_project()

        return self
예제 #5
0
    # Read the layers
    demand_polygon_fl = qgis.core.QgsVectorLayer(
        r"../sample_data/demand_polygon.shp", "demand_polygon_fl", "ogr")
    facility2_service_areas_fl = qgis.core.QgsVectorLayer(
        r"../sample_data/facility2_service_areas.shp",
        "facility2_service_areas_fl", "ogr")

    # Test partial coverage generation
    partial_coverage2 = pyqgis_analysis.generate_partial_coverage(
        demand_polygon_fl, facility2_service_areas_fl, "Population", "GEOID10",
        "ORIG_ID")

    # Create the model, minimize the number of facilities that still results in 80 percent coverage
    logger.info("Creating complemenatary coverage threshold model...")
    ccthreshold = covering.create_cc_threshold_model(partial_coverage2, 80)
    # Solve the model
    logger.info("Solving CC threshold model...")
    ccthreshold.solve(pulp.GLPK())
    # Extract the ids
    logger.info("Extracting results")
    ids = utilities.get_ids(ccthreshold, "facility2_service_areas")
    select_query = pyqgis_analysis.generate_query(ids,
                                                  unique_field_name="ORIG_ID")
    logger.info(
        "Output query to use to generate maps is: {}".format(select_query))
    # Determine how much demand is covered by the results
    facility2_service_areas_fl.setSubsetString(select_query)
    total_coverage = pyqgis_analysis.get_covered_demand(
        demand_polygon_fl, "Population", "partial", facility2_service_areas_fl)
    logger.info("{0:.2f}% of demand is covered".format(
예제 #6
0
    QgsVectorFileWriter.writeAsVectorFormat(response_area_layer,
                                            RESPONSE_AREA_LAYER_SHP, "System",
                                            response_area_layer.crs(),
                                            "ESRI Shapefile")

    block_layer = QgsVectorLayer(BLOCK_OUTLINE_SHP, "block_layer", "ogr")
    response_area_layer = QgsVectorLayer(RESPONSE_AREA_LAYER_SHP,
                                         "response_area_layer", "ogr")

    binary_coverage_polygon = pyqgis_analysis.generate_partial_coverage(
        block_layer, response_area_layer, "demand", "point_id", "area_id")

    print(binary_coverage_polygon)
    # Create the mclp model
    logger.info("Creating MCLP model...")
    mclp = covering.create_cc_threshold_model(binary_coverage_polygon, 80)
    # Solve the model using GLPK
    logger.info("Solving MCLP...")
    mclp.solve(pulp.GLPK(options=['--mipgap', '.1']))
    logger.info("Extracting results")
    ids = utilities.get_ids(mclp,
                            "{}_response_area_layer".format(SELECTION_VALUE))
    print(ids)
    # Generate a query that could be used as a definition query or selection in arcpy
    select_query = pyqgis_analysis.generate_query(ids,
                                                  unique_field_name="area_id")
    logger.info(
        "Output query to use to generate maps is: {}".format(select_query))
    # Determine how much demand is covered by the results
    response_area_layer.setSubsetString(select_query)
    total_coverage = pyqgis_analysis.get_covered_demand(
예제 #7
0
    sh = logging.StreamHandler(sys.stdout)
    sh.setFormatter(formatter)
    logger.addHandler(sh)

    # Read the layers
    demand_polygon_fl = qgis.core.QgsVectorLayer(r"../sample_data/demand_polygon.shp", "demand_polygon_fl", "ogr")
    facility2_service_areas_fl = qgis.core.QgsVectorLayer(r"../sample_data/facility2_service_areas.shp",
                                                          "facility2_service_areas_fl", "ogr")

    # Test partial coverage generation
    partial_coverage2 = pyqgis_analysis.generate_partial_coverage(demand_polygon_fl, facility2_service_areas_fl,
                                                                  "Population",
                                                                  "GEOID10", "ORIG_ID")

    # Create the model, minimize the number of facilities that still results in 80 percent coverage
    logger.info("Creating complemenatary coverage threshold model...")
    ccthreshold = covering.create_cc_threshold_model(partial_coverage2, 80)
    # Solve the model
    logger.info("Solving CC threshold model...")
    ccthreshold.solve(pulp.GLPK())
    # Extract the ids
    logger.info("Extracting results")
    ids = utilities.get_ids(ccthreshold, "facility2_service_areas")
    select_query = pyqgis_analysis.generate_query(ids, unique_field_name="ORIG_ID")
    logger.info("Output query to use to generate maps is: {}".format(select_query))
    # Determine how much demand is covered by the results
    facility2_service_areas_fl.setSubsetString(select_query)
    total_coverage = pyqgis_analysis.get_covered_demand(demand_polygon_fl, "Population", "partial",
                                                        facility2_service_areas_fl)
    logger.info("{0:.2f}% of demand is covered".format((100 * total_coverage) / partial_coverage2["totalDemand"]))