private void addVacantDwellings() { // PUMS generates too few vacant dwellings, add vacant dwellings to match vacancy rate logger.info(" Adding empty dwellings to match vacancy rate"); HashMap<String, ArrayList<Integer>> ddPointer = new HashMap<>(); // summarize vacancy int[][][] ddCount = new int[geoData.getHighestZonalId() + 1][DwellingType.values().length][2]; for (Dwelling dd : Dwelling.getDwellingArray()) { int taz = dd.getZone(); int occ = dd.getResidentId(); ddCount[taz][dd.getType().ordinal()][0]++; if (occ > 0) ddCount[taz][dd.getType().ordinal()][1]++; // set pointer to this dwelling String code = taz + "_" + dd.getType(); if (ddPointer.containsKey(code)) { ArrayList<Integer> dList = ddPointer.get(code); dList.add(dd.getId()); ddPointer.put(code, dList); } else { ArrayList<Integer> dList = new ArrayList<>(); dList.add(dd.getId()); ddPointer.put(code, dList); } } TableDataSet countyLevelVacancies = SiloUtil.readCSVfile(rb.getString(PROPERTIES_COUNTY_VACANCY_RATES)); countyLevelVacancies.buildIndex(countyLevelVacancies.getColumnPosition("Fips")); double[] expectedVacancies = ResourceUtil.getDoubleArray(rb, PROPERTIES_VACANCY_RATES); for (int taz : geoData.getZones()) { float vacRateCountyTarget; try { vacRateCountyTarget = countyLevelVacancies.getIndexedValueAt(geoData.getCountyOfZone(taz), "VacancyRate"); } catch (Exception e) { vacRateCountyTarget = countyLevelVacancies.getIndexedValueAt(99999, "VacancyRate"); // use average value } int ddInThisTaz = 0; for (DwellingType dt : DwellingType.values()) { String code = taz + "_" + dt; if (!ddPointer.containsKey(code)) continue; ddInThisTaz += ddPointer.get(code).size(); } int targetVacantDdThisZone = (int) (ddInThisTaz * vacRateCountyTarget + 0.5); for (DwellingType dt : DwellingType.values()) { String code = taz + "_" + dt; if (!ddPointer.containsKey(code)) continue; ArrayList<Integer> dList = ddPointer.get(code); if (ddCount[taz][dt.ordinal()][0] == 0) continue; // no values for this zone and dwelling type in modeled data float vacRateTargetThisDwellingType = (float) expectedVacancies[dt.ordinal()]; float targetThisTypeThisZoneAbs = (float) (vacRateTargetThisDwellingType / SiloUtil.getSum(expectedVacancies) * targetVacantDdThisZone); float vacDwellingsModel = ((float) (ddCount[taz][dt.ordinal()][0] - ddCount[taz][dt.ordinal()][1])); Integer[] ids = dList.toArray(new Integer[dList.size()]); while (vacDwellingsModel < SiloUtil.rounder(targetThisTypeThisZoneAbs, 0)) { int selected = SiloUtil.select(ids.length) - 1; Dwelling dd = Dwelling.getDwellingFromId(ids[selected]); int newDdId = RealEstateDataManager.getNextDwellingId(); new Dwelling( newDdId, dd.getZone(), -1, dd.getType(), dd.getBedrooms(), dd.getQuality(), dd.getPrice(), 0f, dd.getYearBuilt()); ddCount[taz][dt.ordinal()][0]++; vacDwellingsModel++; if (newDdId == SiloUtil.trackDd) { SiloUtil.trackWriter.println("Generated vacant dwelling with following attributes:"); Dwelling.getDwellingFromId(newDdId).logAttributes(SiloUtil.trackWriter); } } } } }
private void savePumsRecord( int pumaZone, int weight, int hhSize, int pumsDdType, int bedRooms, int autos, int rent, int mortgage, int quality, int yearBuilt, int[] gender, int[] age, Race[] race, int[] relShp, int[] occupation, int[] workPumaZone, int[] workState, int[] income) { // add record to PUMS record storage if (pumsDdType == 10 || pumsDdType == -999) return; // skip this record if PUMS dwelling type is 10 (Boat, RV, Van) or -999 (unknown) DwellingType ddType = translateDwellingType(pumsDdType); for (int count = 0; count < weight; count++) { int newDdId = RealEstateDataManager.getNextDwellingId(); int newHhId; if (gender[0] == 0) newHhId = -1; else newHhId = HouseholdDataManager.getNextHouseholdId(); int taz = locateDwelling(pumaZone); int price = getDwellingPrice(rent, mortgage); int selectedYear = selectYear(yearBuilt); new Dwelling(newDdId, taz, newHhId, ddType, bedRooms, quality, price, 0, selectedYear); if (gender[0] == 0) return; // this dwelling is empty, do not create household Household hh = new Household(newHhId, newDdId, taz, hhSize, autos); for (int s = 0; s < hhSize; s++) { int newPpId = HouseholdDataManager.getNextPersonId(); int occ = translateOccupation(occupation[s]); int workplace = -1; if (occ == 1) { if (workPumaZone[s] == 0 || workState[s] == 0) { // no workplace PUMA provided by PUMS (person did not go to work during week interviewed // because of vacation, leave, etc.) workplace = selectWorkplaceByTripLengthFrequencyDistribution( workPumaZone[s], workState[s], taz); } else { // workplace PUMA provided by PUMS // workplace = selectWorkplace(workPumaZone[s], workState[s]); // update: As the distribution of requested workplaces according to PUMS is very // different from the available MSTM employment data all jobs are chosen based on trip // length frequency distributions workplace = selectWorkplaceByTripLengthFrequencyDistribution( workPumaZone[s], workState[s], taz); } if (workplace != -2) { Job.getJobFromId(workplace) .setWorkerID(newPpId); // -2 for jobs outside of the study area } } Person pp = new Person(newPpId, newHhId, age[s], gender[s], race[s], occ, workplace, income[s]); hh.addPersonForInitialSetup(pp); } hh.setType(); hh.setHouseholdRace(); definePersonRolesInHousehold(hh, relShp); // trace persons, households and dwellings for (Person pp : hh.getPersons()) if (pp.getId() == SiloUtil.trackPp) { SiloUtil.trackWriter.println("Generated person with following attributes:"); Person.getPersonFromId(pp.getId()).logAttributes(SiloUtil.trackWriter); } if (newHhId == SiloUtil.trackHh) { SiloUtil.trackWriter.println("Generated household with following attributes:"); Household.getHouseholdFromId(newHhId).logAttributes(SiloUtil.trackWriter); } if (newDdId == SiloUtil.trackDd) { SiloUtil.trackWriter.println("Generated dwelling with following attributes:"); Dwelling.getDwellingFromId(newDdId).logAttributes(SiloUtil.trackWriter); } } }