private void calculateVacancyRate() { // calculate and log vacancy rate int[] ddCount = new int[DwellingType.values().length]; int[] occCount = new int[DwellingType.values().length]; for (Dwelling dd : Dwelling.getDwellingArray()) { int id = dd.getResidentId(); DwellingType tp = dd.getType(); ddCount[tp.ordinal()]++; if (id > 0) occCount[tp.ordinal()]++; } for (DwellingType tp : DwellingType.values()) { float rate = SiloUtil.rounder( ((float) ddCount[tp.ordinal()] - occCount[tp.ordinal()]) * 100 / ((float) ddCount[tp.ordinal()]), 2); logger.info(" Vacancy rate for " + tp + ": " + rate + "%"); } }
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); } } } } }