def run(self, n=500, realestate_dataset_name = 'building', current_year=None, occupied_spaces_variable="occupied_spaces", total_spaces_variable="total_spaces", minimum_spaces_attribute="minimum_spaces", within_parcel_selection_weight_string=None, within_parcel_selection_n=0, within_parcel_selection_compete_among_types=False, within_parcel_selection_threshold=75, within_parcel_selection_MU_same_weight=False, within_parcel_selection_transpose_interpcl_weight=True, run_config=None, debuglevel=0): """ run method of the Development Project Proposal Sampling Model **Parameters** **n** : int, sample size for each iteration sample n proposals at a time, which are then evaluated one by one until the target vacancies are satisfied or proposals are running out **realestate_dataset_name** : string, name of real estate dataset **current_year**: int, simulation year. If None, get value from SimulationState **occupied_spaces_variable** : string, variable name for calculating how much spaces are currently occupied It can either be a variable for real_estate dataset that returns the amount spaces being occupied or a target_vacancy attribute that contains the name of real_estate variables. **total_spaces_variable** : string, variable name for calculating total existing spaces **Returns** **proposal_set** : indices to proposal_set that are accepted **demolished_buildings** : buildings to be demolished for re-development """ self.accepted_proposals = [] self.demolished_buildings = [] #id of buildings to be demolished if self.proposal_set.n <= 0: logger.log_status("The size of proposal_set is 0; no proposals to consider, skipping DPPSM.") return (self.proposal_set, self.demolished_buildings) target_vacancy = self.dataset_pool.get_dataset('target_vacancy') if current_year is None: year = SimulationState().get_current_time() else: year = current_year this_year_index = where(target_vacancy['year']==year)[0] target_vacancy_for_this_year = DatasetSubset(target_vacancy, this_year_index) if target_vacancy_for_this_year.size() == 0: raise IOError, 'No target vacancy defined for year %s.' % year ## current_target_vacancy.target_attribute_name = 'target_vacancy_rate' ## each column provides a category for which a target vacancy is specified self.column_names = list(set( target_vacancy.get_known_attribute_names() ) - \ set( [ target_vacancy.target_attribute_name, 'year', '_hidden_id_', minimum_spaces_attribute, occupied_spaces_variable, total_spaces_variable ] ) ) self.column_names.sort(reverse=True) ## buildings table provides existing stocks self.realestate_dataset = self.dataset_pool.get_dataset(realestate_dataset_name) occupied_spaces_variables = [occupied_spaces_variable] total_spaces_variables = [total_spaces_variable] if occupied_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names(): occupied_spaces_variables += unique(target_vacancy_for_this_year[occupied_spaces_variable]).tolist() if total_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names(): total_spaces_variables += unique(target_vacancy_for_this_year[total_spaces_variable]).tolist() self._compute_variables_for_dataset_if_needed(self.realestate_dataset, self.column_names + occupied_spaces_variables + total_spaces_variables) self._compute_variables_for_dataset_if_needed(self.proposal_component_set, self.column_names + total_spaces_variables) self.proposal_set.compute_variables(["urbansim_parcel.development_project_proposal.number_of_components", "urbansim_parcel.development_project_proposal.land_area_taken"], dataset_pool=self.dataset_pool) n_column = len(self.column_names) self.column_names_index = {} for iname in range(n_column): self.column_names_index[self.column_names[iname]] = iname target_vacancy_for_this_year.column_values = target_vacancy_for_this_year.get_multiple_attributes(self.column_names).reshape((-1, n_column)) self.realestate_dataset.column_values = self.realestate_dataset.get_multiple_attributes(self.column_names).reshape((-1, n_column)) self.proposal_component_set.column_values = self.proposal_component_set.get_multiple_attributes(self.column_names).reshape((-1, n_column)) #defaults, can be changed later by spaces_variable specified in target_vacancy rates self.realestate_dataset.total_spaces = self.realestate_dataset[total_spaces_variable] self.proposal_component_set.total_spaces = self.proposal_component_set[total_spaces_variable] self.realestate_dataset.occupied_spaces = self.realestate_dataset[occupied_spaces_variable] self.accounting = {}; self.logging = {} #has_needed_components = zeros(self.proposal_set.size(), dtype='bool') for index in range(target_vacancy_for_this_year.size()): column_value = tuple(target_vacancy_for_this_year.column_values[index,:].tolist()) accounting = {'target_vacancy': target_vacancy_for_this_year[target_vacancy.target_attribute_name][index]} if minimum_spaces_attribute in target_vacancy_for_this_year.get_known_attribute_names(): accounting['minimum_spaces'] = target_vacancy_for_this_year[minimum_spaces_attribute][index] realestate_indexes = self.get_index_by_condition(self.realestate_dataset.column_values, column_value) component_indexes = self.get_index_by_condition(self.proposal_component_set.column_values, column_value) this_total_spaces_variable, this_occupied_spaces_variable = total_spaces_variable, occupied_spaces_variable ## total/occupied_spaces_variable can be specified either as a universal name for all realestate ## or in targe_vacancy_rate dataset for each vacancy category if occupied_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names(): this_occupied_spaces_variable = target_vacancy_for_this_year[occupied_spaces_variable][index] self.realestate_dataset.occupied_spaces[realestate_indexes] = (self.realestate_dataset[this_occupied_spaces_variable][realestate_indexes] ).astype(self.realestate_dataset.occupied_spaces.dtype) if total_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names(): this_total_spaces_variable = target_vacancy_for_this_year[total_spaces_variable][index] self.realestate_dataset.total_spaces[realestate_indexes] = (self.realestate_dataset[this_total_spaces_variable][realestate_indexes] ).astype(self.realestate_dataset.total_spaces.dtype) self.proposal_component_set.total_spaces[component_indexes] = (self.proposal_component_set[this_total_spaces_variable][component_indexes] ).astype(self.proposal_component_set.total_spaces.dtype) accounting["total_spaces_variable"] = this_total_spaces_variable accounting["total_spaces"] = self.realestate_dataset.total_spaces[realestate_indexes].sum() accounting["occupied_spaces_variable"] = this_occupied_spaces_variable accounting["occupied_spaces"] = self.realestate_dataset.occupied_spaces[realestate_indexes].sum() accounting["target_spaces"] = int( round( accounting["occupied_spaces"] /\ (1 - accounting["target_vacancy"]) ) ) accounting["proposed_spaces"] = 0 accounting["demolished_spaces"] = 0 self.accounting[column_value] = accounting if self._is_target_reached(column_value): proposal_indexes = self.proposal_set.get_id_index(unique(self.proposal_component_set['proposal_id'][component_indexes])) if n_column == 1: comp_indexes = where(ndimage.sum(self.proposal_component_set[self.column_names[0]]==column_value[0], labels=self.proposal_component_set['proposal_id'], index=self.proposal_set.get_id_attribute() ) == self.proposal_set["number_of_components"])[0] else: comp_indexes = where(self.proposal_set["number_of_components"]==1)[0] target_reached_prop_idx = intersect1d(proposal_indexes, comp_indexes) self.weight[target_reached_prop_idx] = 0.0 self.proposal_set["status_id"][intersect1d(target_reached_prop_idx, where(self.proposal_set["status_id"]==self.proposal_set.id_tentative)[0])] = self.proposal_set.id_no_demand ## handle planned proposals: all proposals with status_id == is_planned ## and start_year == year are accepted planned_proposal_indexes = where(logical_and( self.proposal_set.get_attribute("status_id") == self.proposal_set.id_planned, self.proposal_set.get_attribute("start_year") == year ) )[0] logger.start_block("Processing %s planned proposals" % planned_proposal_indexes.size) self.consider_proposals(planned_proposal_indexes, force_accepting=True) logger.end_block() if within_parcel_selection_n > 0: logger.start_block("Selecting proposals within parcels (%s proposals per parcel)" % within_parcel_selection_n) self.select_proposals_within_parcels(nmax=within_parcel_selection_n, weight_string=within_parcel_selection_weight_string, compete_among_types=within_parcel_selection_compete_among_types, filter_threshold=within_parcel_selection_threshold, MU_same_weight=within_parcel_selection_MU_same_weight, transpose_interpcl_weight=within_parcel_selection_transpose_interpcl_weight) logger.end_block() # consider proposals (in this order: proposed, tentative) for status in [self.proposal_set.id_proposed, self.proposal_set.id_tentative]: stat = (self.proposal_set.get_attribute("status_id") == status) if stat.sum() == 0: continue logger.log_status("Sampling from %s eligible proposals of status %s." % (stat.sum(), status)) iteration = 0 while (not self._is_target_reached()): ## prevent proposals from being sampled for vacancy type whose target is reached #for column_value in self.accounting.keys(): if self.weight[stat].sum() == 0.0: logger.log_warning("Running out of proposals of status %s before vacancy targets are reached; there aren't any proposals with non-zero weight" % status) break available_indexes = where(logical_and(stat, self.weight > 0))[0] sample_size = minimum(available_indexes.size, n) sampled_proposal_indexes = probsample_noreplace(available_indexes, sample_size, prob_array=self.weight[available_indexes], return_index=False) #sorted_sampled_indices = argsort(self.weight[sampled_proposal_indexes]) #self.consider_proposals(sampled_proposal_indexes[sorted_sampled_indices][::-1]) self.consider_proposals(sampled_proposal_indexes) self.weight[sampled_proposal_indexes] = 0 iteration += 1 self._log_status() # set status of accepted proposals to 'active' self.proposal_set.modify_attribute(name="status_id", data=self.proposal_set.id_active, index=array(self.accepted_proposals, dtype='int32')) # Code added by Jesse Ayers, MAG, 7/20/2009 # Get the active projects: stat_id = self.proposal_set.get_attribute('status_id') actv = where(stat_id==1)[0] # Where there are active projects, compute the total_land_area_taken # and store it on the development_project_proposals dataset # so it can be used by the building_construction_model for the proper # computation of units_proposed for those projects with velocity curves if actv.size > 0: total_land_area_taken_computed = self.proposal_set['land_area_taken'] self.proposal_set.modify_attribute('total_land_area_taken', total_land_area_taken_computed[actv], actv) return (self.proposal_set, self.realestate_dataset.get_id_attribute()[self.demolished_buildings])
def run(self, n=500, realestate_dataset_name='building', current_year=None, occupied_spaces_variable="occupied_spaces", total_spaces_variable="total_spaces", run_config=None, debuglevel=0): """ run method of the Development Project Proposal Sampling Model **Parameters** **n** : int, sample size for each iteration sample n proposals at a time, which are then evaluated one by one until the target vacancies are satisfied or proposals are running out **realestate_dataset_name** : string, name of real estate dataset **current_year**: int, simulation year. If None, get value from SimulationState **occupied_spaces_variable** : string, variable name for calculating how much spaces are currently occupied It can either be a variable for real_estate dataset that returns the amount spaces being occupied or a target_vacancy attribute that contains the name of real_estate variables. **total_spaces_variable** : string, variable name for calculating total existing spaces **Returns** **proposal_set** : indices to proposal_set that are accepted **demolished_buildings** : buildings to be demolished for re-development """ self.accepted_proposals = [] self.demolished_buildings = [] #id of buildings to be demolished if self.proposal_set.n <= 0: logger.log_status( "The size of proposal_set is 0; no proposals to consider, skipping DPPSM." ) return (self.proposal_set, self.demolished_buildings) target_vacancy = self.dataset_pool.get_dataset('target_vacancy') if current_year is None: year = SimulationState().get_current_time() else: year = current_year this_year_index = where(target_vacancy['year'] == year)[0] target_vacancy_for_this_year = DatasetSubset(target_vacancy, this_year_index) if target_vacancy_for_this_year.size() == 0: raise IOError, 'No target vacancy defined for year %s.' % year ## current_target_vacancy.target_attribute_name = 'target_vacancy_rate' ## each column provides a category for which a target vacancy is specified self.column_names = list(set( target_vacancy.get_known_attribute_names() ) - \ set( [ target_vacancy.target_attribute_name, 'year', '_hidden_id_', occupied_spaces_variable, total_spaces_variable ] ) ) self.column_names.sort(reverse=True) ## buildings table provides existing stocks self.realestate_dataset = self.dataset_pool.get_dataset( realestate_dataset_name) occupied_spaces_variables = [occupied_spaces_variable] total_spaces_variables = [total_spaces_variable] if occupied_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names( ): occupied_spaces_variables += unique( target_vacancy_for_this_year[occupied_spaces_variable]).tolist( ) if total_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names( ): total_spaces_variables += unique( target_vacancy_for_this_year[total_spaces_variable]).tolist() self._compute_variables_for_dataset_if_needed( self.realestate_dataset, self.column_names + occupied_spaces_variables + total_spaces_variables) self._compute_variables_for_dataset_if_needed( self.proposal_component_set, self.column_names + total_spaces_variables) self.proposal_set.compute_variables( "urbansim_parcel.development_project_proposal.number_of_components", dataset_pool=self.dataset_pool) n_column = len(self.column_names) target_vacancy_for_this_year.column_values = target_vacancy_for_this_year.get_multiple_attributes( self.column_names).reshape((-1, n_column)) self.realestate_dataset.column_values = self.realestate_dataset.get_multiple_attributes( self.column_names).reshape((-1, n_column)) self.proposal_component_set.column_values = self.proposal_component_set.get_multiple_attributes( self.column_names).reshape((-1, n_column)) #defaults, can be changed later by spaces_variable specified in target_vacancy rates self.realestate_dataset.total_spaces = self.realestate_dataset[ total_spaces_variable] self.proposal_component_set.total_spaces = self.proposal_component_set[ total_spaces_variable] self.realestate_dataset.occupied_spaces = self.realestate_dataset[ occupied_spaces_variable] self.accounting = {} self.logging = {} #has_needed_components = zeros(self.proposal_set.size(), dtype='bool') for index in range(target_vacancy_for_this_year.size()): column_value = tuple( target_vacancy_for_this_year.column_values[index, :].tolist()) accounting = { 'target_vacancy': target_vacancy_for_this_year[ target_vacancy.target_attribute_name][index] } realestate_indexes = self.get_index_by_condition( self.realestate_dataset.column_values, column_value) component_indexes = self.get_index_by_condition( self.proposal_component_set.column_values, column_value) this_total_spaces_variable, this_occupied_spaces_variable = total_spaces_variable, occupied_spaces_variable ## total/occupied_spaces_variable can be specified either as a universal name for all realestate ## or in targe_vacancy_rate dataset for each vacancy category if occupied_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names( ): this_occupied_spaces_variable = target_vacancy_for_this_year[ occupied_spaces_variable][index] self.realestate_dataset.occupied_spaces[realestate_indexes] = ( self.realestate_dataset[this_occupied_spaces_variable] [realestate_indexes]).astype( self.realestate_dataset.occupied_spaces.dtype) if total_spaces_variable in target_vacancy_for_this_year.get_known_attribute_names( ): this_total_spaces_variable = target_vacancy_for_this_year[ total_spaces_variable][index] self.realestate_dataset.total_spaces[realestate_indexes] = ( self.realestate_dataset[this_total_spaces_variable] [realestate_indexes]).astype( self.realestate_dataset.total_spaces.dtype) self.proposal_component_set.total_spaces[component_indexes] = ( self.proposal_component_set[this_total_spaces_variable] [component_indexes]).astype( self.proposal_component_set.total_spaces.dtype) accounting["total_spaces_variable"] = this_total_spaces_variable accounting["total_spaces"] = self.realestate_dataset.total_spaces[ realestate_indexes].sum() accounting[ "occupied_spaces_variable"] = this_occupied_spaces_variable accounting[ "occupied_spaces"] = self.realestate_dataset.occupied_spaces[ realestate_indexes].sum() accounting["target_spaces"] = int( round( accounting["occupied_spaces"] /\ (1 - accounting["target_vacancy"]) ) ) accounting["proposed_spaces"] = 0 accounting["demolished_spaces"] = 0 self.accounting[column_value] = accounting if self._is_target_reached(column_value): proposal_indexes = self.proposal_set.get_id_index( unique(self.proposal_component_set['proposal_id'] [component_indexes])) single_component_indexes = where( self.proposal_set["number_of_components"] == 1)[0] self.weight[intersect1d(proposal_indexes, single_component_indexes)] = 0.0 ## handle planned proposals: all proposals with status_id == is_planned ## and start_year == year are accepted planned_proposal_indexes = where( logical_and( self.proposal_set.get_attribute("status_id") == self.proposal_set.id_planned, self.proposal_set.get_attribute("start_year") == year))[0] self.consider_proposals(planned_proposal_indexes, force_accepting=True) # consider proposals (in this order: proposed, tentative) for status in [ self.proposal_set.id_proposed, self.proposal_set.id_tentative ]: stat = (self.proposal_set.get_attribute("status_id") == status) if stat.sum() == 0: continue logger.log_status( "Sampling from %s eligible proposals of status %s." % (stat.sum(), status)) iteration = 0 while (not self._is_target_reached()): ## prevent proposals from being sampled for vacancy type whose target is reached #for column_value in self.accounting.keys(): if self.weight[stat].sum() == 0.0: logger.log_warning( "Running out of proposals of status %s before vacancy targets are reached; there aren't any proposals with non-zero weight" % status) break available_indexes = where(logical_and(stat, self.weight > 0))[0] sample_size = minimum(available_indexes.size, n) sampled_proposal_indexes = probsample_noreplace( available_indexes, sample_size, prob_array=self.weight[available_indexes], return_index=False) self.consider_proposals(sampled_proposal_indexes) self.weight[sampled_proposal_indexes] = 0 #sample_size = 1 #sampled_proposal_index = probsample_noreplace(available_indexes, sample_size, #prob_array=self.weight[available_indexes], #return_index=False) #self.consider_proposal(sampled_proposal_index) #self.weight[sampled_proposal_index] = 0 iteration += 1 self._log_status() # set status of accepted proposals to 'active' self.proposal_set.modify_attribute(name="status_id", data=self.proposal_set.id_active, index=array(self.accepted_proposals, dtype='int32')) # Code added by Jesse Ayers, MAG, 7/20/2009 # Get the active projects: stat_id = self.proposal_set.get_attribute('status_id') actv = where(stat_id == 1)[0] # Where there are active projects, compute the total_land_area_taken # and store it on the development_project_proposals dataset # so it can be used by the building_construction_model for the proper # computation of units_proposed for those projects with velocity curves if actv.size > 0: total_land_area_taken_computed = self.proposal_set.get_attribute( 'urbansim_parcel.development_project_proposal.land_area_taken') self.proposal_set.modify_attribute( 'total_land_area_taken', total_land_area_taken_computed[actv], actv) return (self.proposal_set, self.realestate_dataset.get_id_attribute()[ self.demolished_buildings])