private static void SetupFrictionData(List <SparseArray <float> > productions, List <SparseArray <float> > attractions, List <IDemographicCategory> cats, MultiBlendSet multiset, float[][][] productionSet, float[][][] attractionSet, IDemographicCategory[][] multiCatSet) { int subsetIndex = -1; foreach (var blendSet in multiset.Subsets) { subsetIndex++; var set = blendSet.Set; var length = set.Count; int place = 0; int blendSetCount = 0; for (int i = 0; i < length; i++) { for (int pos = set[i].Start; pos <= set[i].Stop; pos++) { blendSetCount++; } } productionSet[subsetIndex] = new float[blendSetCount][]; attractionSet[subsetIndex] = new float[blendSetCount][]; multiCatSet[subsetIndex] = new IDemographicCategory[blendSetCount]; for (int i = 0; i < length; i++) { for (int pos = set[i].Start; pos <= set[i].Stop; pos++) { productionSet[subsetIndex][place] = productions[pos].GetFlatData(); attractionSet[subsetIndex][place] = attractions[pos].GetFlatData(); multiCatSet[subsetIndex][place] = cats[pos]; place++; } } } }
public IEnumerable <SparseTwinIndex <float> > Distribute(IEnumerable <SparseArray <float> > production, IEnumerable <SparseArray <float> > attraction, IEnumerable <IDemographicCategory> category) { Progress = 0f; using (var ep = production.GetEnumerator()) using (var ea = attraction.GetEnumerator()) using (var eCat = category.GetEnumerator()) { var zones = Root.ZoneSystem.ZoneArray; if (String.IsNullOrWhiteSpace(LoadFrictionFileName)) { if (BaseData.Count != MultiBlendSets.Count) { throw new XTMFRuntimeException(this, "In " + Name + " the number of BaseData entries is not the same as the number of Blend Sets!"); } } var productions = new List <SparseArray <float> >(); var attractions = new List <SparseArray <float> >(); var cats = new List <IDemographicCategory>(); // We need to pre-load all of our generations in order to handle blending properly while (ep.MoveNext() && ea.MoveNext() && eCat.MoveNext()) { productions.Add(ep.Current); attractions.Add(ea.Current); cats.Add(eCat.Current); } int setNumber = -1; var ret = zones.CreateSquareTwinArray <float>(); float[] p = new float[zones.GetFlatData().Length]; CountTotalBlendSets(); foreach (var multiset in MultiBlendSets) { setNumber++; var numberOfBlendSets = multiset.Subsets.Count; var productionSet = new float[numberOfBlendSets][][]; var attractionSet = new float[numberOfBlendSets][][]; var catSet = new IDemographicCategory[numberOfBlendSets][]; SetupFrictionData(productions, attractions, cats, multiset, productionSet, attractionSet, catSet); for (int subsetIndex = 0; subsetIndex < multiset.Subsets.Count; subsetIndex++) { SumProductionAndAttraction(p, productionSet[subsetIndex]); bool loadedFriction = false; // use the base data if we don't load in the friction base data if (String.IsNullOrWhiteSpace(LoadFrictionFileName)) { LoadInBaseData(ret, BaseData[setNumber]); } else { LoadFriction(ret.GetFlatData(), setNumber); loadedFriction = true; } UpdateData(ret.GetFlatData(), p, catSet, productionSet, attractionSet, zones.GetFlatData(), subsetIndex, loadedFriction); yield return(ret); } } } }
private float[][] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[][] friction) { var numberOfZones = zones.Length; var rootModes = Root.Modes; var numberOfModes = rootModes.Count; // initialize the category so we can compute the friction cat.InitializeDemographicCategory(); Parallel.For(0, numberOfZones, delegate(int i) { var origin = zones[i]; for (int j = 0; j < numberOfZones; j++) { double logsum = 0f; for (int mIndex = 0; mIndex < numberOfModes; mIndex++) { var mode = rootModes[mIndex]; if (!mode.Feasible(origin, zones[j], SimulationTime)) { continue; } var inc = mode.CalculateV(origin, zones[j], SimulationTime); if (float.IsNaN(inc)) { continue; } logsum += Math.Exp(inc); } friction[i][j] = (float)Math.Pow(logsum, Beta); } }); // Use the Log-Sum from the V's as the impedance function return(friction); }
private void ComputeFriction(IZone[] zones, IDemographicCategory cat, float[][] friction) { var numberOfZones = zones.Length; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For(0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { for (int j = 0; j < numberOfZones; j++) { var destination = zones[j]; float utility; if (!this.GatherAllUtility(zones[i], zones[j], out utility)) { throw new XTMFRuntimeException("There was no valid mode to travel between " + zones[i].ZoneNumber + " and " + zones[j].ZoneNumber); } else { friction[i][j] = (float)Math.Pow(utility, this.ImpedianceParameter) * (this.KFactor != null ? (float)Math.Exp(this.KFactor[i * this.NumberOfZones + j]) : 1f); } } }); } catch (AggregateException e) { throw e.InnerException; } }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; var minFrictionInc = (float)Math.Exp(-10); // initialize the category so we can compute the friction cat.InitializeDemographicCategory(); try { Parallel.For(0, numberOfZones, delegate(int i) { int index = i * numberOfZones; var origin = zones[i]; int vIndex = i * numberOfZones * numberOfModes; for (int j = 0; j < numberOfZones; j++) { double logsum = 0f; var destination = zones[j]; int feasibleModes = 0; for (int mIndex = 0; mIndex < numberOfModes; mIndex++) { var mode = rootModes[mIndex]; if (!mode.Feasible(origin, zones[j], this.SimulationTime)) { vIndex++; continue; } feasibleModes++; var inc = mode.CalculateV(origin, zones[j], this.SimulationTime); if (float.IsNaN(inc)) { continue; } logsum += Math.Exp(inc); } ret[index++] = (float)Math.Pow(logsum, this.Beta); } }); } catch (AggregateException e) { if (e.InnerException is XTMFRuntimeException) { throw e.InnerException; } else { throw new XTMFRuntimeException(e.InnerException.Message + "\r\n" + e.InnerException.StackTrace); } } // Use the Log-Sum from the V's as the impedence function return(ret); }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction ?? (new float[numberOfZones * numberOfZones]); // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For(0, numberOfZones, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int j) { var destination = zones[j]; if (!InverseLookup(destination.RegionNumber, out int regionIndex)) { // make sure to reset the friction to zero for (int i = 0; i < numberOfZones; i++) { ret[i * numberOfZones + j] = float.NegativeInfinity; } return; } // store the log of the population and the employment since we will be using this for each origin var employmentLog = (float)Math.Log((destination.Employment - destination.ManufacturingEmployment) + 1); var populationLog = (float)Math.Log(destination.Population + 1); for (int i = 0; i < numberOfZones; i++) { var origin = zones[i]; if (origin.RegionNumber <= 0) { ret[i * numberOfZones + j] = float.NegativeInfinity; } else { var autoTime = RegionEmploymentGeneralParameter[regionIndex] * NetworkData.TravelTime(origin, destination, SimulationTime).ToMinutes(); var destinationUtility = RegionEmploymentParameter[regionIndex] * employmentLog + RegionPopulationParameter[regionIndex] * populationLog; // this isn't friction, it is V where friction will be e^V ret[i * numberOfZones + j] = destinationUtility + autoTime; } } }); } catch (AggregateException e) { if (e.InnerException is XTMFRuntimeException) { throw new XTMFRuntimeException(this, e.InnerException.Message); } throw new XTMFRuntimeException(this, e.InnerException?.Message + "\r\n" + e.InnerException?.StackTrace); } // Use the Log-Sum from the V's as the impedence function return(ret); }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] production, float[] attraction, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction ?? (new float[numberOfZones * numberOfZones]); // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For(0, numberOfZones, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { int index = i * numberOfZones; if (production[i] == 0) { for (int j = 0; j < numberOfZones; j++) { ret[index++] = 0; } return; } for (int j = 0; j < numberOfZones; j++) { if (attraction != null && attraction[j] == 0) { ret[index++] = 0; } else { if (!GatherAllUtility(zones[i], zones[j], out float utility)) { ret[index++] = 0; //throw new XTMFRuntimeException( "There was no valid mode to travel between " + zones[i].ZoneNumber + " and " + zones[j].ZoneNumber ); } else { ret[index++] = (float)Math.Pow(utility, ImpedianceParameter) * (KFactor != null ? (float)Math.Exp(KFactor[i * NumberOfZones + j]) : 1f); } } } }); } catch (AggregateException e) { if (e.InnerException is XTMFRuntimeException) { throw new XTMFRuntimeException(this, e.InnerException.Message); } throw new XTMFRuntimeException(this, e.InnerException?.Message + "\r\n" + e.InnerException?.StackTrace); } // Use the Log-Sum from the V's as the impedence function return(ret); }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For(0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { int index = i * numberOfZones; var origin = zones[i]; int vIndex = i * numberOfZones * numberOfModes; int regionIndex; if (!InverseLookup(zones[i].RegionNumber, out regionIndex)) { for (int j = 0; j < numberOfZones; j++) { ret[index++] = 0; } return; } for (int j = 0; j < numberOfZones; j++) { var destination = zones[j]; var autoTime = this.NetworkData.TravelTime(origin, destination, this.SimulationTime); var population = destination.Population; ret[index++] = (float)(this.RegionAutoParameter[regionIndex] * autoTime.ToMinutes() // population + this.RegionPopulationParameter[regionIndex] * Math.Log(population + 1) // employment + this.RegionEmploymentProfessionalParameter[regionIndex] * Math.Log(destination.ProfessionalEmployment + 1) + this.RegionEmploymentGeneralParameter[regionIndex] * Math.Log(destination.GeneralEmployment + 1) + this.RegionEmploymentSalesParameter[regionIndex] * Math.Log(destination.RetailEmployment + 1) + this.RegionEmploymentManufacturingParameter[regionIndex] * Math.Log(destination.ManufacturingEmployment + 1)); } }); } catch (AggregateException e) { throw e.InnerException; } // Use the Log-Sum from the V's as the impedence function return(ret); }
private IEnumerable <SparseTwinIndex <float> > CPUDoublyConstrained(IZone[] zones, IEnumerator <SparseArray <float> > ep, IEnumerator <SparseArray <float> > ea, IEnumerator <IDemographicCategory> ec) { float completed = 0f; var frictionSparse = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray <float>(); var productions = new List <SparseArray <float> >(); var attractions = new List <SparseArray <float> >(); var cats = new List <IDemographicCategory>(); // We need to pre load all of our generations in order to handle blending properly while (ep.MoveNext() & ea.MoveNext() & ec.MoveNext()) { productions.Add(ep.Current); attractions.Add(ea.Current); cats.Add(ec.Current); } var ret = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray <float>(); SparseArray <float> production = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray <float>(); SparseArray <float> attraction = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray <float>(); this.CurrentMultiSetIndex = -1; foreach (var multiset in this.MultiBlendSets) { this.CurrentMultiSetIndex++; var numberOfSubsets = multiset.Subsets.Count; var productionSet = new float[numberOfSubsets][][]; var attractionSet = new float[numberOfSubsets][][]; var multiCatSet = new IDemographicCategory[numberOfSubsets][]; SetupFrictionData(productions, attractions, cats, multiset, productionSet, attractionSet, multiCatSet); this.ComputeFriction(zones, multiCatSet, productionSet, attractionSet, frictionSparse.GetFlatData(), production.GetFlatData(), attraction.GetFlatData()); string balanceFileName; SparseArray <float> balanceFactors = GetWarmBalancingFactors(attraction, out balanceFileName); if (this.CullSmallValues) { var tempValues = new GravityModel(frictionSparse, null, this.Epsilon, this.MaxIterations) .ProcessFlow(production, attraction, production.ValidIndexArray(), balanceFactors); this.Cull(tempValues, frictionSparse.GetFlatData(), production.GetFlatData(), attraction.GetFlatData()); if (!String.IsNullOrWhiteSpace(this.SaveFrictionFileName)) { this.SaveFriction(frictionSparse.GetFlatData()); } } yield return(new GravityModel(frictionSparse, (p => this.Progress = (p * (1f / (this.MultiBlendSets.Count)) + (completed / (this.MultiBlendSets.Count)))), this.Epsilon, this.MaxIterations) .ProcessFlow(production, attraction, production.ValidIndexArray(), balanceFactors)); if (balanceFileName != null) { SaveBalanceFactors(balanceFileName, balanceFactors); } completed += 1f; } }
private void ComputeFriction(IZone[] zones, IDemographicCategory cat, float[][] friction) { var numberOfZones = zones.Length; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); Parallel.For(0, numberOfZones, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { for (int j = 0; j < numberOfZones; j++) { if (!GatherAllUtility(zones[i], zones[j], out float utility)) { throw new XTMFRuntimeException(this, "There was no valid mode to travel between " + zones[i].ZoneNumber + " and " + zones[j].ZoneNumber); } friction[i][j] = (float)Math.Pow(utility, ImpedianceParameter) * (KFactor != null ? (float)Math.Exp(KFactor[i * NumberOfZones + j]) : 1f); } }); }
public IEnumerable <SparseTwinIndex <float> > Distribute(IEnumerable <SparseArray <float> > eps, IEnumerable <SparseArray <float> > eas, IEnumerable <IDemographicCategory> ecs) { float[] friction = null; var zones = Root.ZoneSystem.ZoneArray.GetFlatData(); var productions = new List <SparseArray <float> >(); var cats = new List <IDemographicCategory>(); using (var ep = eps.GetEnumerator()) using (var ec = ecs.GetEnumerator()) { while (ep.MoveNext() && ec.MoveNext()) { productions.Add(ep.Current); cats.Add(ec.Current); } } SparseArray <float> production = Root.ZoneSystem.ZoneArray.CreateSimilarArray <float>(); TotalBlendSets = 0; for (int i = 0; i < BlendSets.Count; i++) { TotalBlendSets += BlendSets[i].Subsets.Count; } foreach (var multiset in BlendSets) { var setLength = multiset.Subsets.Count; var productionSet = new float[setLength][][]; var catSet = new IDemographicCategory[setLength][]; SetupFrictionData(productions, cats, multiset, productionSet, catSet); for (int subIndex = 0; subIndex < multiset.Subsets.Count; subIndex++) { friction = ComputeFriction(zones, catSet, productionSet, friction, production.GetFlatData(), subIndex); var ret = SinglyConstrainedGravityModel.Process(production, friction); if (Transpose) { TransposeMatrix(ret); } yield return(ret); } } }
public IEnumerable<SparseTwinIndex<float>> Distribute(IEnumerable<SparseArray<float>> production, IEnumerable<SparseArray<float>> attraction, IEnumerable<IDemographicCategory> category) { this.Progress = 0f; var ep = production.GetEnumerator(); var ea = attraction.GetEnumerator(); var eBaseData = this.BaseData.GetEnumerator(); var eCat = category.GetEnumerator(); var zones = this.Root.ZoneSystem.ZoneArray; if ( String.IsNullOrWhiteSpace( this.LoadFrictionFileName ) ) { if ( BaseData.Count != this.MultiBlendSets.Count ) { throw new XTMFRuntimeException( "In " + this.Name + " the number of BaseData entries is not the same as the number of Blend Sets!" ); } } var productions = new List<SparseArray<float>>(); var attractions = new List<SparseArray<float>>(); var cats = new List<IDemographicCategory>(); // We need to pre-load all of our generations in order to handle blending properly while ( ep.MoveNext() && ea.MoveNext() && eCat.MoveNext() ) { productions.Add( ep.Current ); attractions.Add( ea.Current ); cats.Add( eCat.Current ); } int setNumber = -1; var ret = zones.CreateSquareTwinArray<float>(); float[] p = new float[zones.GetFlatData().Length]; CountTotalBlendSets(); foreach ( var multiset in this.MultiBlendSets ) { setNumber++; var numberOfBlendSets = multiset.Subsets.Count; var productionSet = new float[numberOfBlendSets][][]; var attractionSet = new float[numberOfBlendSets][][]; var catSet = new IDemographicCategory[numberOfBlendSets][]; SetupFrictionData( productions, attractions, cats, multiset, productionSet, attractionSet, catSet ); for ( int subsetIndex = 0; subsetIndex < multiset.Subsets.Count; subsetIndex++ ) { SumProductionAndAttraction( p, productionSet[subsetIndex] ); bool loadedFriction = false; // use the base data if we don't load in the friction base data if ( String.IsNullOrWhiteSpace( this.LoadFrictionFileName ) ) { LoadInBaseData( ret, this.BaseData[setNumber] ); } else { LoadFriction( ret.GetFlatData(), setNumber ); loadedFriction = true; } UpdateData( ret.GetFlatData(), p, catSet, productionSet, attractionSet, zones.GetFlatData(), subsetIndex, loadedFriction ); if ( this.Transpose ) { TransposeMatrix( ret ); if ( !String.IsNullOrWhiteSpace( this.SaveFrictionFileName ) ) { this.SaveFriction( ret.GetFlatData() ); } } yield return ret; } } }
private void UpdateData(float[][] flatRet, float[] flatProd, IDemographicCategory[][] cats, float[][][] productions, float[][][] attractions, IZone[] zones, int subset, bool loadedFriction) { var numberOfZones = flatProd.Length; this.InteractiveModeSplit.StartNewInteractiveModeSplit( this.TotalBlendSets ); var mpd = this.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]; var factor = 0f; if ( p == 0 ) { // if there is no production, clear out everything for ( int j = 0; j < numberOfZones; j++ ) { flatRet[i][j] = 0f; } continue; } if ( this.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( "In '" + this.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 ); } this.CheckSaveFriction( flatRet ); }
private static void SetupModeSplit(IDemographicCategory[][] cats, int subset, IModeParameterDatabase mpd, float[] ratio) { mpd.InitializeBlend(); for ( int j = 0; j < cats[subset].Length; j++ ) { mpd.SetBlendWeight( ratio[j] ); cats[subset][j].InitializeDemographicCategory(); } mpd.CompleteBlend(); }
private static void SetupFrictionData(List<SparseArray<float>> productions, List<SparseArray<float>> attractions, List<IDemographicCategory> cats, MultiBlendSet multiset, float[][][] productionSet, float[][][] attractionSet, IDemographicCategory[][] multiCatSet) { int subsetIndex = -1; foreach ( var blendSet in multiset.Subsets ) { subsetIndex++; var set = blendSet.Set; var length = set.Count; int place = 0; int blendSetCount = 0; for ( int i = 0; i < length; i++ ) { for ( int pos = set[i].Start; pos <= set[i].Stop; pos++ ) { blendSetCount++; } } productionSet[subsetIndex] = new float[blendSetCount][]; attractionSet[subsetIndex] = new float[blendSetCount][]; multiCatSet[subsetIndex] = new IDemographicCategory[blendSetCount]; for ( int i = 0; i < length; i++ ) { for ( int pos = set[i].Start; pos <= set[i].Stop; pos++ ) { productionSet[subsetIndex][place] = productions[pos].GetFlatData(); attractionSet[subsetIndex][place] = attractions[pos].GetFlatData(); multiCatSet[subsetIndex][place] = cats[pos]; place++; } } } }
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( this.LoadFrictionFileName ) ) { LoadFriction( friction, -1 ); loadedFriction = true; } else { ClearFriction( friction, numberOfZones ); } var mpd = this.Root.ModeParameterDatabase; float[] subsetRatios = new float[productions.Length]; SumProductionAndAttraction( production, attraction, productions, attractions ); for ( int subset = 0; subset < cats.Length; subset++ ) { this.InteractiveModeSplit.StartNewInteractiveModeSplit( this.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 ); } this.InteractiveModeSplit.EndInterativeModeSplit(); } ConvertToFriction( friction, zones ); CheckSaveFriction( friction ); }
private IEnumerable<SparseTwinIndex<float>> CPUDoublyConstrained(IZone[] zones, IEnumerator<SparseArray<float>> ep, IEnumerator<SparseArray<float>> ea, IEnumerator<IDemographicCategory> ec) { float completed = 0f; var frictionSparse = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); var productions = new List<SparseArray<float>>(); var attractions = new List<SparseArray<float>>(); var cats = new List<IDemographicCategory>(); // We need to pre load all of our generations in order to handle blending properly while ( ep.MoveNext() & ea.MoveNext() & ec.MoveNext() ) { productions.Add( ep.Current ); attractions.Add( ea.Current ); cats.Add( ec.Current ); } var ret = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); SparseArray<float> production = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray<float>(); SparseArray<float> attraction = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray<float>(); this.CurrentMultiSetIndex = -1; foreach ( var multiset in this.MultiBlendSets ) { this.CurrentMultiSetIndex++; var numberOfSubsets = multiset.Subsets.Count; var productionSet = new float[numberOfSubsets][][]; var attractionSet = new float[numberOfSubsets][][]; var multiCatSet = new IDemographicCategory[numberOfSubsets][]; SetupFrictionData( productions, attractions, cats, multiset, productionSet, attractionSet, multiCatSet ); this.ComputeFriction( zones, multiCatSet, productionSet, attractionSet, frictionSparse.GetFlatData(), production.GetFlatData(), attraction.GetFlatData() ); string balanceFileName; SparseArray<float> balanceFactors = GetWarmBalancingFactors( attraction, out balanceFileName ); if ( this.CullSmallValues ) { var tempValues = new GravityModel( frictionSparse, null, this.Epsilon, this.MaxIterations ) .ProcessFlow( production, attraction, production.ValidIndexArray(), balanceFactors ); this.Cull( tempValues, frictionSparse.GetFlatData(), production.GetFlatData(), attraction.GetFlatData() ); if ( !String.IsNullOrWhiteSpace( this.SaveFrictionFileName ) ) { this.SaveFriction( frictionSparse.GetFlatData() ); } } yield return new GravityModel( frictionSparse, ( p => this.Progress = ( p * ( 1f / ( this.MultiBlendSets.Count ) ) + ( completed / ( this.MultiBlendSets.Count ) ) ) ), this.Epsilon, this.MaxIterations ) .ProcessFlow( production, attraction, production.ValidIndexArray(), balanceFactors ); if ( balanceFileName != null ) { SaveBalanceFactors( balanceFileName, balanceFactors ); } completed += 1f; } }
private static void SetupModeChoiceParameters(IDemographicCategory[] cats, float[] ratio, IModeParameterDatabase mpd) { mpd.InitializeBlend(); for ( int c = 0; c < cats.Length; c++ ) { mpd.SetBlendWeight( ratio[c] ); cats[c].InitializeDemographicCategory(); } mpd.CompleteBlend(); }
private void ComputeFriction(IZone[] zones, IDemographicCategory cat, float[][] friction) { var numberOfZones = zones.Length; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For( 0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { for ( int j = 0; j < numberOfZones; j++ ) { var destination = zones[j]; float utility; if ( !this.GatherAllUtility( zones[i], zones[j], out utility ) ) { throw new XTMFRuntimeException( "There was no valid mode to travel between " + zones[i].ZoneNumber + " and " + zones[j].ZoneNumber ); } else { friction[i][j] = (float)Math.Pow( utility, this.ImpedianceParameter ) * ( this.KFactor != null ? (float)Math.Exp( this.KFactor[i * this.NumberOfZones + j] ) : 1f ); } } } ); } catch ( AggregateException e ) { throw e.InnerException; } }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] production, float[] attraction, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For( 0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { int index = i * numberOfZones; if ( production[i] == 0 ) { for ( int j = 0; j < numberOfZones; j++ ) { ret[index++] = 0; } return; } for ( int j = 0; j < numberOfZones; j++ ) { if ( attraction != null && attraction[j] == 0 ) { ret[index++] = 0; } else { var utility = 0f; if ( !this.GatherAllUtility( zones[i], zones[j], out utility ) ) { ret[index++] = 0; //throw new XTMFRuntimeException( "There was no valid mode to travel between " + zones[i].ZoneNumber + " and " + zones[j].ZoneNumber ); } else { ret[index++] = (float)Math.Pow( utility, this.ImpedianceParameter ) * ( this.KFactor != null ? (float)Math.Exp( this.KFactor[i * this.NumberOfZones + j] ) : 1f ); } } } } ); } catch ( AggregateException e ) { if ( e.InnerException is XTMFRuntimeException ) { throw new XTMFRuntimeException( e.InnerException.Message ); } else { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } // Use the Log-Sum from the V's as the impedence function return ret; }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; var minFrictionInc = (float)Math.Exp( -10 ); // initialize the category so we can compute the friction cat.InitializeDemographicCategory(); try { Parallel.For( 0, numberOfZones, delegate(int i) { int index = i * numberOfZones; var origin = zones[i]; int vIndex = i * numberOfZones * numberOfModes; for ( int j = 0; j < numberOfZones; j++ ) { double logsum = 0f; var destination = zones[j]; int feasibleModes = 0; for ( int mIndex = 0; mIndex < numberOfModes; mIndex++ ) { var mode = rootModes[mIndex]; if ( !mode.Feasible( origin, zones[j], this.SimulationTime ) ) { vIndex++; continue; } feasibleModes++; var inc = mode.CalculateV( origin, zones[j], this.SimulationTime ); if ( float.IsNaN( inc ) ) { continue; } logsum += Math.Exp( inc ); } ret[index++] = (float)Math.Pow( logsum, this.Beta ); } } ); } catch ( AggregateException e ) { if ( e.InnerException is XTMFRuntimeException ) { throw e.InnerException; } else { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } // Use the Log-Sum from the V's as the impedence function return ret; }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For( 0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int j) { var destination = zones[j]; int regionIndex; if ( !InverseLookup( destination.RegionNumber, out regionIndex ) ) { // make sure to reset the friction to zero for ( int i = 0; i < numberOfZones; i++ ) { ret[i * numberOfZones + j] = float.NegativeInfinity; } return; } // store the log of the population and the employment since we will be using this for each origin var employmentLog = (float)Math.Log( ( destination.Employment - destination.ManufacturingEmployment ) + 1 ); var populationLog = (float)Math.Log( destination.Population + 1 ); for ( int i = 0; i < numberOfZones; i++ ) { var origin = zones[i]; if ( origin.RegionNumber <= 0 ) { ret[i * numberOfZones + j] = float.NegativeInfinity; } else { var autoTime = this.RegionEmploymentGeneralParameter[regionIndex] * this.NetworkData.TravelTime( origin, destination, this.SimulationTime ).ToMinutes(); var destinationUtility = this.RegionEmploymentParameter[regionIndex] * employmentLog + this.RegionPopulationParameter[regionIndex] * populationLog; // this isn't friction, it is V where friction will be e^V ret[i * numberOfZones + j] = destinationUtility + autoTime; } } } ); } catch ( AggregateException e ) { if ( e.InnerException is XTMFRuntimeException ) { throw new XTMFRuntimeException( e.InnerException.Message ); } else { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } // Use the Log-Sum from the V's as the impedence function return ret; }
public IEnumerable <SparseTwinIndex <float> > Distribute(IEnumerable <SparseArray <float> > productions, IEnumerable <SparseArray <float> > attractions, IEnumerable <IDemographicCategory> category) { if (this.SaveDistributionSeries != null) { this.SaveDistributionSeries.Reset(); } IDemographicCategory cat = null; var ret = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray <float>(); var linkages = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray <float>(); var catEnum = category.GetEnumerator(); var productionEnum = productions.GetEnumerator(); int catIndex = 0; var rangeSet = new RangeSet(new int[] { 0 }); // just multiply by the number of occupations in v2 since this is a throw away module this.NumberOfGenerations = NumberOfCategoriesPerOccupation * 4; while (catEnum.MoveNext() & productionEnum.MoveNext()) { cat = catEnum.Current; var ageRate = productionEnum.Current; Parallel.Invoke( () => SetupMobilityInformation(catIndex), () => LoadLinkages(catIndex, linkages.GetFlatData()) ); foreach (var mobilitySet in this.MobilityRanges) { for (int mobility = mobilitySet.Start; mobility <= mobilitySet.Stop; mobility++) { var realCat = cat as DemographicCategoryGeneration; if (realCat == null) { throw new XTMFRuntimeException("In '" + this.Name + "' it is required that all generates be of the type DemographicCategoryGeneration!"); } rangeSet[0] = new Range() { Start = mobility, Stop = mobility }; realCat.Mobility = rangeSet; DistributePopulation(realCat, ageRate.GetFlatData(), linkages.GetFlatData(), catIndex, ret.GetFlatData()); Task save = null; if (this.SaveDistributionSeries != null) { save = Task.Factory.StartNew(() => { SaveDistribution(ret, this.Root.ZoneSystem.ZoneArray.GetFlatData(), catIndex); }); } yield return(ret); if (save != null) { save.Wait(); } catIndex++; } } } // Free up our memory this.MobilityCache = null; this.UnloadRates(); }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory[][] cats, float[][][] productionSet, float[] friction, float[] production, int subsetIndex) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; if ( !String.IsNullOrWhiteSpace( this.LoadFrictionFileName ) ) { LoadFriction( ret ); } else { ComputeFriction( zones, numberOfZones, ret ); } this.InteractiveModeSplit.StartNewInteractiveModeSplit( this.TotalBlendSets ); SumProduction( production, productionSet, subsetIndex ); try { float[] ratio = new float[cats[subsetIndex].Length]; var mpd = this.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 ) { throw e.InnerException; } // Use the Log-Sum from the V's as the impedence function if ( !String.IsNullOrWhiteSpace( this.SaveFrictionFileName ) ) { SaveFriction( ret ); } return ret; }
private float[] ComputeFriction(IZone[] zones, IDemographicCategory cat, float[] friction) { var numberOfZones = zones.Length; float[] ret = friction == null ? new float[numberOfZones * numberOfZones] : friction; var rootModes = this.Root.Modes; var numberOfModes = rootModes.Count; // let it setup the modes so we can compute friction cat.InitializeDemographicCategory(); try { Parallel.For( 0, numberOfZones, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate(int i) { int index = i * numberOfZones; var origin = zones[i]; int vIndex = i * numberOfZones * numberOfModes; int regionIndex; if ( !InverseLookup( zones[i].RegionNumber, out regionIndex ) ) { for ( int j = 0; j < numberOfZones; j++ ) { ret[index++] = 0; } return; } for ( int j = 0; j < numberOfZones; j++ ) { var destination = zones[j]; var autoTime = this.NetworkData.TravelTime( origin, destination, this.SimulationTime ); var population = destination.Population; ret[index++] = (float)( this.RegionAutoParameter[regionIndex] * autoTime.ToMinutes() // population + this.RegionPopulationParameter[regionIndex] * Math.Log( population + 1 ) // employment + this.RegionEmploymentProfessionalParameter[regionIndex] * Math.Log( destination.ProfessionalEmployment + 1 ) + this.RegionEmploymentGeneralParameter[regionIndex] * Math.Log( destination.GeneralEmployment + 1 ) + this.RegionEmploymentSalesParameter[regionIndex] * Math.Log( destination.RetailEmployment + 1 ) + this.RegionEmploymentManufacturingParameter[regionIndex] * Math.Log( destination.ManufacturingEmployment + 1 ) ); } } ); } catch ( AggregateException e ) { throw e.InnerException; } // Use the Log-Sum from the V's as the impedence function return ret; }
public IEnumerable<SparseTwinIndex<float>> Distribute(IEnumerable<SparseArray<float>> eps, IEnumerable<SparseArray<float>> eas, IEnumerable<IDemographicCategory> ecs) { float[] friction = null; var zones = this.Root.ZoneSystem.ZoneArray.GetFlatData(); var productions = new List<SparseArray<float>>(); var cats = new List<IDemographicCategory>(); var ep = eps.GetEnumerator(); var ec = ecs.GetEnumerator(); while ( ep.MoveNext() && ec.MoveNext() ) { productions.Add( ep.Current ); cats.Add( ec.Current ); } SparseArray<float> production = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray<float>(); this.TotalBlendSets = 0; for ( int i = 0; i < this.BlendSets.Count; i++ ) { this.TotalBlendSets += this.BlendSets[i].Subsets.Count; } foreach ( var multiset in this.BlendSets ) { var setLength = multiset.Subsets.Count; var productionSet = new float[setLength][][]; var catSet = new IDemographicCategory[setLength][]; SetupFrictionData( productions, cats, multiset, productionSet, catSet ); for ( int subIndex = 0; subIndex < multiset.Subsets.Count; subIndex++ ) { friction = this.ComputeFriction( zones, catSet, productionSet, friction, production.GetFlatData(), subIndex ); var ret = SinglyConstrainedGravityModel.Process( production, friction ); if ( this.Transpose ) { TransposeMatrix( ret ); } yield return ret; } } }