private float[] ComputeFriction(IZone[] zones, IDemographicCategory[][] cats, float[][][] productionSet, float[] friction, float[] production, int subsetIndex) { var numberOfZones = zones.Length; float[] ret = friction ?? (new float[numberOfZones * numberOfZones]); if (!String.IsNullOrWhiteSpace(LoadFrictionFileName)) { LoadFriction(ret); } else { ComputeFriction(zones, numberOfZones, ret); } InteractiveModeSplit.StartNewInteractiveModeSplit(TotalBlendSets); SumProduction(production, productionSet, subsetIndex); try { float[] ratio = new float[cats[subsetIndex].Length]; var mpd = Root.ModeParameterDatabase; for (int i = 0; i < numberOfZones; i++) { // let it setup the modes so we can compute friction ProcessRatio(i, ratio, production, productionSet[subsetIndex]); SetupModeChoiceParameters(cats[subsetIndex], ratio, mpd); SaveModeChoice(zones, numberOfZones, i); } } catch (AggregateException e) { if (e.InnerException != null) { throw e.InnerException; } } // Use the Log-Sum from the V's as the impedance function if (!String.IsNullOrWhiteSpace(SaveFrictionFileName)) { SaveFriction(ret); } return(ret); }
private void ComputeFriction(IZone[] zones, IDemographicCategory[][] cats, float[][][] productions, float[][][] attractions, float[][] friction, float[] production, float[] attraction) { var numberOfZones = zones.Length; bool loadedFriction = false; if (!String.IsNullOrWhiteSpace(LoadFrictionFileName)) { LoadFriction(friction, -1); loadedFriction = true; } else { ClearFriction(friction, numberOfZones); } var mpd = Root.ModeParameterDatabase; float[] subsetRatios = new float[productions.Length]; SumProductionAndAttraction(production, attraction, productions, attractions); for (int subset = 0; subset < cats.Length; subset++) { InteractiveModeSplit.StartNewInteractiveModeSplit(MultiBlendSets.Count); float[] ratio = new float[cats[subset].Length]; for (int i = 0; i < numberOfZones; i++) { ComputeSubsetRatios(i, subsetRatios, productions); ProcessBlendsetRatio(i, ratio, productions[subset]); // if there is no production for this origin we can just skip ahead for the next zone if (production[i] == 0) { continue; } // if there is something here to process SetupModeChoice(cats, ratio, mpd, subset); GatherUtilities(zones, friction, attraction, numberOfZones, loadedFriction, subsetRatios, subset, i); } InteractiveModeSplit.EndInterativeModeSplit(); } ConvertToFriction(friction, zones); CheckSaveFriction(friction); }
private void UpdateData(float[][] flatRet, float[] flatProd, IDemographicCategory[][] cats, float[][][] productions, float[][][] attractions, IZone[] zones, int subset, bool loadedFriction) { var numberOfZones = flatProd.Length; InteractiveModeSplit.StartNewInteractiveModeSplit(TotalBlendSets); var mpd = Root.ModeParameterDatabase; float[] subsetRatios = new float[productions.Length]; float[] ratio = new float[cats[subset].Length]; for (int i = 0; i < numberOfZones; i++) { var p = flatProd[i]; float factor; if (p == 0) { // if there is no production, clear out everything for (int j = 0; j < numberOfZones; j++) { flatRet[i][j] = 0f; } continue; } if (UseProductionPercentages) { var totalProduction = 0f; factor = 0f; for (int j = 0; j < attractions[subset].Length; j++) { totalProduction += productions[subset][j][i]; } if (totalProduction <= 0) { for (int j = 0; j < numberOfZones; j++) { flatRet[i][j] = 0f; } continue; } // compute how much each one contributes to the total // then sum it all up into our final factor for (int j = 0; j < productions[subset].Length; j++) { ratio[j] = productions[subset][j][i] / totalProduction; factor += productions[subset][j][i]; } float retTotal = 0; for (int j = 0; j < flatRet[i].Length; j++) { retTotal += flatRet[i][j]; } factor = factor / retTotal; // in this case we use the attraction since that is where the people // are actually stored in this case ComputeSubsetRatios(i, subsetRatios, attractions); if (factor <= 0f) { for (int j = 0; j < numberOfZones; j++) { flatRet[i][j] = 0f; } continue; } // we actually still need to operate on the friction since it will be in totals loadedFriction = false; } else { var sum = 0f; var retRow = flatRet[i]; // Gather the sum of all of the destinations from this origin for (int j = 0; j < numberOfZones; j++) { sum += retRow[j]; } // The rows should already be seeded however, if they are not // just return since all of the values are zero anyway if (sum <= 0) { throw new XTMFRuntimeException(this, "In '" + Name + "' there was no attraction for zone " + zones[i].ZoneNumber); } ProcessRatio(i, ratio, flatProd, productions[subset]); ComputeSubsetRatios(i, subsetRatios, productions); // p is already the production of this subset factor = p / sum; } SetupModeSplit(cats, subset, mpd, ratio); // make sure to only include the total factor of people that belong to this subset // now that we have the new factor we update the demand UpdateDemand(flatRet, zones, numberOfZones, loadedFriction, i, factor); } if (Transpose) { TransposeMatrix(flatRet); } if (!String.IsNullOrWhiteSpace(SaveFrictionFileName)) { SaveFriction(flatRet); } }
private void DistributePopulation(DemographicCategoryGeneration cat, float[] ageProbability, float[][] assignedPersons, int catIndex, float[][] ret) { var timeOfDayRate = CurrentTimeOfDayRates.GiveData(); var dailyRates = CurrentDailyRates.GiveData(); var zones = Root.ZoneSystem.ZoneArray.GetFlatData(); var numberOfMobilityTypes = GetMobilityTypeTotal(); var currentMobilityType = catIndex % numberOfMobilityTypes; ModeSplit.StartNewInteractiveModeSplit(NumberOfGenerations); // Setup the mode choice function, since each zone is the same, we only need to do this once cat.InitializeDemographicCategory(); var age = cat.AgeCategoryRange[0].Start; //ageOfffset = foreach each OD Pair, for each mobility category multiplied by the age - 2 (workrs start at 2). var ageOffset = (5 * zones.Length * zones.Length) * (age - 2); // for each origin zone Parallel.For(0, zones.Length, i => { var pdI = zones[i].PlanningDistrict; // Offset of the origin var iOffset = i * zones.Length * numberOfMobilityTypes; // offset by the age category plus the mobility category offset iOffset += ageOffset + currentMobilityType * zones.Length; // for each destination var row = ret[i]; var assignedPersonRow = assignedPersons[i]; if (ageProbability[i] == 0) { for (int j = 0; j < zones.Length; j++) { row[j] = 0; } } else { int currentJIndex = 0; for (int j = 0; j < zones.Length; j++) { if (assignedPersonRow[j] <= 0) { row[j] = 0; } else if (j == i) { throw new XTMFRuntimeException(this, "We found assigned persons for an intra-zonal work trip!"); } else { var pdJ = zones[j].PlanningDistrict; // compute the mode choice var util = ModeSplit.ComputeUtility(zones[i], zones[j]); if (float.IsNaN(util) | float.IsInfinity(util)) { throw new XTMFRuntimeException(this, "We came across an invalid utility! Age = " + age + " origin = " + zones[i].ZoneNumber + " destination = " + zones[j].ZoneNumber + " demographic category = '" + cat.ToString() + "'"); } // Process how many persons go here // probabilities contains the probability of being in that age category already var rate = timeOfDayRate[pdI, pdJ, age] * dailyRates[pdI, pdJ, age]; var persons = ageProbability[i] * assignedPersonRow[j]; if ((rate == 0) & (persons > 0)) { throw new XTMFRuntimeException(this, "We lost generation for " + zones[i].ZoneNumber + " to " + zones[j].ZoneNumber + ". " + persons + " persons in category " + catIndex + "."); } row[j] = persons * rate * MobilityCache[iOffset + currentJIndex]; } currentJIndex++; } } }); }