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)
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)
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)
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
# 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(
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(
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"]))