Пример #1
0
 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;
     }
 }
Пример #3
0
        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();
        }
Пример #4
0
 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;
 }