public void TestSimpleGravityModelSolution() { var data = CreateData(); var gm = new GravityModel( data, null, 0.0f, 300 ); var o = SparseArray<float>.CreateSparseArray( new int[] { 1, 2 }, new float[] { 2, 2 } ); var d = SparseArray<float>.CreateSparseArray( new int[] { 1, 2 }, new float[] { 1.5f, 2.5f } ); var ret = gm.ProcessFlow( o, d, new int[] { 1, 2 } ); var result = ret.GetFlatData(); Assert.AreEqual( 0.5f, result[0][0], 0.0001f ); Assert.AreEqual( 1.5f, result[0][1], 0.0001f); Assert.AreEqual( 1f, result[1][0], 0.0001f); Assert.AreEqual( 1f, result[1][1], 0.0001f); }
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 InitializeFlows() { this.Progress = 0; // we are going to need to split based on this information this.ZoneArray = this.Root.ZoneSystem.ZoneArray; var occupations = this.Root.Demographics.OccupationCategories; var validZones = this.ZoneArray.ValidIndexies().ToArray(); var numberOfZones = validZones.Length; //[Occupation][O , D] var distribution = occupations.CreateSimilarArray<SparseTwinIndex<float>>(); //Generate the place of work place of residence OD's SparseArray<float> O = this.ZoneArray.CreateSimilarArray<float>(); SparseArray<float> D = this.ZoneArray.CreateSimilarArray<float>(); var occupationIndexes = occupations.ValidIndexies().ToArray(); var numCat = Categories.Count; // Start burning that CPU Thread.CurrentThread.Priority = ThreadPriority.Highest; SparseTwinIndex<float> workplaceDistribution = null; SparseTwinIndex<float> prevWorkplaceDistribution = null; float[] friction = null; float[] nextFriction = null; MultiRunGPUGravityModel multiRunGPU = null; for ( int i = 0; i < numCat; i++ ) { this.CurrentOccupationIndex = i; Task assignToPopulation = null; if ( i > 0 ) { assignToPopulation = new Task( delegate() { if ( prevWorkplaceDistribution != null ) { // We actually are assigning to the previous category with this data so we need i - 1 AssignToWorkers( prevWorkplaceDistribution, this.Categories[i - 1] ); prevWorkplaceDistribution = null; } } ); assignToPopulation.Start(); } Task computeNextFriction = null; if ( i + 1 < numCat ) { computeNextFriction = new Task( delegate() { nextFriction = this.ComputeFriction( ZoneArray.GetFlatData(), this.Categories[i + 1], nextFriction ); } ); computeNextFriction.Start(); } this.Categories[i].Generate( O, D ); if ( this.UseGPU ) { if ( i == 0 ) { try { Parallel.Invoke( () => friction = this.ComputeFriction( ZoneArray.GetFlatData(), this.Categories[i], friction ), () => multiRunGPU = new MultiRunGPUGravityModel( O.GetFlatData().Length, ( progress => this.Progress = ( progress / numCat ) + ( (float)i / numCat ) ), this.Epsilon, this.MaxIterations ) ); } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } workplaceDistribution = multiRunGPU.ProcessFlow( friction, O, D ); } else { GravityModel gravityModel = new GravityModel( ImpedenceFunction, ( progress => this.Progress = ( progress / numCat ) + ( (float)i / numCat ) ), this.Epsilon, this.MaxIterations ); workplaceDistribution = gravityModel.ProcessFlow( O, D, validZones ); } this.Progress = ( (float)( i + 1 ) / numCat ); if ( assignToPopulation != null ) { try { assignToPopulation.Wait(); assignToPopulation.Dispose(); assignToPopulation = null; } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } if ( computeNextFriction != null ) { try { computeNextFriction.Wait(); computeNextFriction.Dispose(); computeNextFriction = null; } catch ( AggregateException e ) { throw new XTMFRuntimeException( e.InnerException.Message + "\r\n" + e.InnerException.StackTrace ); } } prevWorkplaceDistribution = workplaceDistribution; var frictionTemp = friction; friction = nextFriction; nextFriction = friction; } friction = null; nextFriction = null; prevWorkplaceDistribution = null; if ( multiRunGPU != null ) { multiRunGPU.Dispose(); multiRunGPU = null; } AssignToWorkers( workplaceDistribution, this.Categories[numCat - 1] ); workplaceDistribution = null; // ok now we can relax Thread.CurrentThread.Priority = ThreadPriority.Normal; GC.Collect(); }
public SparseTwinIndex<float> Distribute(SparseArray<float> productions, SparseArray<float> attractions) { var zoneSystem = this.Parent.ZoneSystem; var zoneArray = zoneSystem.ZoneArray; var flatZones = zoneArray.GetFlatData(); ZoneX = zoneArray.CreateSimilarArray<float>(); var flatX = ZoneX.GetFlatData(); ZoneY = zoneArray.CreateSimilarArray<float>(); var flatY = ZoneY.GetFlatData(); var numberOfZones = flatZones.Length; for (int i = 0; i < numberOfZones; i++) { var zone = flatZones[i]; flatX[i] = zone.X; flatY[i] = zone.Y; } SparseTwinIndex<float> data; if (this.UseGPU) { float[] friction = this.ComputeFriction(flatX, flatY, flatZones); data = new GPUGravityModel( friction, UpdateProgress, this.Epsilon, this.MaxBalanceIterations ).ProcessFlow( productions, attractions ); } else { var validZones = zoneArray.ValidIndexies().ToArray(); data = new GravityModel(FrictionFunction, UpdateProgress, this.Epsilon, this.MaxBalanceIterations).ProcessFlow(productions, attractions, validZones); } this.Progress = 1; return data; }