private SparseArray <float> GetWarmBalancingFactors(SparseArray <float> attraction, out string balanceFileName)
        {
            SparseArray <float> balanceFactors = null;

            if (BalanceFactors.ContainsFileName())
            {
                balanceFileName = BalanceFactors.GetFileName() + CurrentMultiSetIndex + ".bin";
                if (File.Exists(balanceFileName))
                {
                    balanceFactors = LoadBalanceFactors(balanceFileName);
                }
                else
                {
                    balanceFactors = attraction.CreateSimilarArray <float>();
                    var flatFactors = balanceFactors.GetFlatData();
                    // initialize the factors to 1
                    for (int i = 0; i < flatFactors.Length; i++)
                    {
                        flatFactors[i] = 1.0f;
                    }
                }
            }
            else
            {
                balanceFileName = null;
            }
            return(balanceFactors);
        }
Esempio n. 2
0
        public SparseTwinIndex <float> ProcessFlow(SparseArray <float> O, SparseArray <float> D, int[] validIndexes, SparseArray <float> attractionStar = null)
        {
            int length = validIndexes.Length;

            Productions = O;
            Attractions = D;
            if (attractionStar == null)
            {
                AttractionsStar = D.CreateSimilarArray <float>();
            }
            else
            {
                AttractionsStar = attractionStar;
            }
            FlowMatrix = Productions.CreateSquareTwinArray <float>();
            if (Friction == null)
            {
                InitializeFriction(length);
            }
            var flatAttractionStar = AttractionsStar.GetFlatData();

            float[] oldTotal        = new float[flatAttractionStar.Length];
            var     flatAttractions = Attractions.GetFlatData();

            for (int i = 0; i < length; i++)
            {
                flatAttractionStar[i] = 1f;
                oldTotal[i]           = flatAttractions[i];
            }
            int iteration = 0;

            float[] columnTotals = new float[length];
            var     balanced     = false;

            do
            {
                if (ProgressCallback != null)
                {
                    // this doesn't go to 100%, but that is alright since when we end, the progress
                    // of the calling model should assume we hit 100%
                    ProgressCallback(iteration / (float)MaxIterations);
                }
                Array.Clear(columnTotals, 0, columnTotals.Length);
                if (Vector.IsHardwareAccelerated)
                {
                    VectorProcessFlow(columnTotals, FlowMatrix.GetFlatData());
                }
                else
                {
                    ProcessFlow(columnTotals);
                }
                balanced = Balance(columnTotals, oldTotal);
            } while((++iteration) < MaxIterations && !balanced);

            if (ProgressCallback != null)
            {
                ProgressCallback(1f);
            }
            return(FlowMatrix);
        }
Esempio n. 3
0
        private void AverageAttractionAndProduction(ref SparseArray <float> production, ref SparseArray <float> attraction)
        {
            var newAttraction     = attraction.CreateSimilarArray <float>();
            var newProduction     = production.CreateSimilarArray <float>();
            var flatAttraction    = attraction.GetFlatData();
            var flatProduction    = production.GetFlatData();
            var newFlatProduction = newProduction.GetFlatData();
            var newFlatAttraction = newAttraction.GetFlatData();
            var productionTotal   = VectorHelper.Sum(flatProduction, 0, flatProduction.Length);
            var attractionTotal   = VectorHelper.Sum(flatAttraction, 0, flatAttraction.Length);
            var totalAverage      = productionTotal + attractionTotal / 2.0f;
            var ratio             = totalAverage / attractionTotal;

            if (float.IsNaN(ratio) || float.IsInfinity(ratio))
            {
                ratio = 0.0f;
            }
            VectorHelper.Multiply(newFlatAttraction, flatAttraction, ratio);
            ratio = totalAverage / productionTotal;
            if (float.IsNaN(ratio) || float.IsInfinity(ratio))
            {
                ratio = 0.0f;
            }
            VectorHelper.Multiply(newFlatProduction, flatProduction, 1.0f / ratio);
            attraction = newAttraction;
            production = newProduction;
        }
Esempio n. 4
0
        private void WriteParallel(int[] validZones, SparseArray <IPerson[]> population, StreamWriter writer, int length)
        {
            var output     = population.CreateSimilarArray <StringBuilder>();
            var flatOutput = output.GetFlatData();
            var flatPop    = population.GetFlatData();
            int current    = 0;

            Parallel.For(0, length,
                         delegate(int i)
            {
                var popInZone = flatPop[i];
                if (popInZone == null)
                {
                    return;
                }
                StringBuilder builder = new StringBuilder();
                foreach (var person in popInZone)
                {
                    builder.Append(validZones[i]);
                    if (person == null)
                    {
                        builder.AppendLine(", PERSON MISSING!");
                        continue;
                    }
                    builder.Append(',');
                    builder.Append(person.Age);
                    builder.Append(',');
                    builder.Append(person.Household != null ? person.Household.Cars : 0);
                    builder.Append(',');
                    builder.Append(person.SchoolZone != null ? person.SchoolZone.ZoneNumber : -1);
                    builder.Append(',');
                    builder.Append(person.WorkZone != null ? person.WorkZone.ZoneNumber : -1);
                    builder.Append(',');
                    builder.Append(person.EmploymentStatus);
                    builder.Append(',');
                    builder.Append(person.StudentStatus);
                    builder.Append(',');
                    builder.Append(person.Occupation);
                    builder.Append(',');
                    builder.Append(person.DriversLicense ? 1 : 0);
                    builder.Append(',');
                    builder.Append(person.ExpansionFactor);
                    builder.AppendLine();
                }
                flatOutput[i] = builder;
                Interlocked.Increment(ref current);
                Progress = (float)current / length;
            });

            for (int i = 0; i < length; i++)
            {
                var sbuilder = flatOutput[i];
                if (sbuilder != null)
                {
                    writer.Write(sbuilder.ToString());
                }
            }
            Progress = 1;
        }
Esempio n. 5
0
        public SparseTwinIndex<float> ProcessFlow(SparseArray<float> O, SparseArray<float> D, int[] validIndexes, SparseArray<float> attractionStar = null)
        {
            int length = validIndexes.Length;
            Productions = O;
            Attractions = D;
            if(attractionStar == null)
            {
                AttractionsStar = D.CreateSimilarArray<float>();
            }
            else
            {
                AttractionsStar = attractionStar;
            }
            FlowMatrix = Productions.CreateSquareTwinArray<float>();
            if(Friction == null)
            {
                InitializeFriction(length);
            }
            var flatAttractionStar = AttractionsStar.GetFlatData();
            float[] oldTotal = new float[flatAttractionStar.Length];
            var flatAttractions = Attractions.GetFlatData();
            for(int i = 0; i < length; i++)
            {
                flatAttractionStar[i] = 1f;
                oldTotal[i] = flatAttractions[i];
            }
            int iteration = 0;
            float[] columnTotals = new float[length];
            var balanced = false;
            do
            {
                if(ProgressCallback != null)
                {
                    // this doesn't go to 100%, but that is alright since when we end, the progress
                    // of the calling model should assume we hit 100%
                    ProgressCallback(iteration / (float)MaxIterations);
                }
                Array.Clear(columnTotals, 0, columnTotals.Length);
                if(Vector.IsHardwareAccelerated)
                {
                    VectorProcessFlow(columnTotals, FlowMatrix.GetFlatData());
                }
                else
                {
                    ProcessFlow(columnTotals);
                }
                balanced = Balance(columnTotals, oldTotal);
            } while((++iteration) < MaxIterations && !balanced);

            if(ProgressCallback != null)
            {
                ProgressCallback(1f);
            }
            return FlowMatrix;
        }
Esempio n. 6
0
        private SparseArray <int> SplitAndClear(int pop, SparseArray <float> splitPercentages, Random rand)
        {
            var   flatSplitPercentages = splitPercentages.GetFlatData();
            var   length         = flatSplitPercentages.Length;
            var   ret            = splitPercentages.CreateSimilarArray <int>();
            var   flatRet        = ret.GetFlatData();
            var   flatRemainder  = new float[length];
            float remainderTotal = 0;
            int   total          = 0;

            for (int i = 0; i < length; i++)
            {
                float element = (flatSplitPercentages[i] * pop);
                total           += (flatRet[i] = (int)Math.Floor(element));
                flatRemainder[i] = element - flatRet[i];
            }
            int notAssigned = pop - total;

            // Make sure that we do not over assign
            remainderTotal = notAssigned;
            for (int i = 0; i < notAssigned; i++)
            {
                var   randPop         = rand.NextDouble() * remainderTotal;
                float ammountToReduce = 0;
                int   j = 0;
                for ( ; j < length; j++)
                {
                    randPop -= (ammountToReduce = flatRemainder[j]);
                    if (randPop <= 0)
                    {
                        remainderTotal  -= ammountToReduce;
                        flatRemainder[j] = 0;
                        flatRet[j]      += 1;
                        break;
                    }
                }
                if (j == length)
                {
                    for (j = 0; j < length; j++)
                    {
                        if (flatRemainder[j] >= 0)
                        {
                            remainderTotal  -= flatRemainder[j];
                            flatRemainder[j] = 0;
                            flatRet[j]      += 1;
                            break;
                        }
                    }
                }
            }
            return(ret);
        }
Esempio n. 7
0
        private void MatchAttractionToProduction(ref SparseArray <float> production, ref SparseArray <float> attraction)
        {
            var newAttraction     = attraction.CreateSimilarArray <float>();
            var flatAttraction    = attraction.GetFlatData();
            var flatProduction    = production.GetFlatData();
            var newFlatAttraction = newAttraction.GetFlatData();
            var ratio             = VectorHelper.Sum(flatProduction, 0, flatProduction.Length) / VectorHelper.Sum(flatAttraction, 0, flatAttraction.Length);

            if (float.IsNaN(ratio) || float.IsInfinity(ratio))
            {
                ratio = 0.0f;
            }
            VectorHelper.Multiply(newFlatAttraction, flatAttraction, ratio);
            attraction = newAttraction;
        }
Esempio n. 8
0
        private void InitializeFlows()
        {
            Progress = 0;
            // we are going to need to split based on this information
            ZoneArray = Root.ZoneSystem.ZoneArray;
            var validZones = ZoneArray.ValidIndexies().ToArray();
            //Generate the place of work place of residence OD's
            SparseArray <float> o = ZoneArray.CreateSimilarArray <float>();
            SparseArray <float> d = ZoneArray.CreateSimilarArray <float>();
            var numCat            = Categories.Count;

            // Start burning that CPU
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            SparseTwinIndex <float> workplaceDistribution     = null;
            SparseTwinIndex <float> prevWorkplaceDistribution = null;

            float[] friction;
            float[] nextFriction = null;
            for (int i = 0; i < numCat; i++)
            {
                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, Categories[i - 1]);
                            prevWorkplaceDistribution = null;
                        }
                    });
                    assignToPopulation.Start();
                }
                Task computeNextFriction = null;
                if (i + 1 < numCat)
                {
                    computeNextFriction = new Task(delegate
                    {
                        nextFriction = ComputeFriction(ZoneArray.GetFlatData(), Categories[i + 1], nextFriction);
                    });
                    computeNextFriction.Start();
                }

                Categories[i].Generate(o, d);
                GravityModel gravityModel = new GravityModel(ImpedenceFunction, (progress => Progress = (progress / numCat) + ((float)i / numCat)), Epsilon, MaxIterations);
                workplaceDistribution = gravityModel.ProcessFlow(o, d, validZones);
                Progress = ((float)(i + 1) / numCat);
                if (assignToPopulation != null)
                {
                    assignToPopulation.Wait();
                    assignToPopulation.Dispose();
                }
                if (computeNextFriction != null)
                {
                    computeNextFriction.Wait();
                    computeNextFriction.Dispose();
                }
                prevWorkplaceDistribution = workplaceDistribution;
                friction     = nextFriction;
                nextFriction = friction;
            }
            nextFriction = null;
            prevWorkplaceDistribution = null;
            AssignToWorkers(workplaceDistribution, Categories[numCat - 1]);
            // ok now we can relax
            Thread.CurrentThread.Priority = ThreadPriority.Normal;
            GC.Collect();
        }
        private void Pass1(SparseArray <IZone> zoneArray, IZone[] zones, int[] basePopulation, int[] zonalDifferences, List <KeyValuePair <int, int> >[] results,
                           List <ITashaHousehold>[] remainingHouseholds, List <int>[] lookupsForRegion)
        {
            SparseArray <List <int> > householdsByZoneIndexToRegion = zoneArray.CreateSimilarArray <List <int> >();

            SetupSpatialListByElement(householdsByZoneIndexToRegion.GetFlatData());
            Console.WriteLine("Preparing household Index");
            Parallel.For(0, HouseholdsByZone.Count, (int i) =>
            {
                var list  = householdsByZoneIndexToRegion.GetFlatData()[i];
                var total = HouseholdsByZone.GetFlatData()[i].Count;
                for (int j = 0; j < total; j++)
                {
                    list.Add(-1);
                }
            });
            Console.WriteLine("Building household index");
            Parallel.For(0, HouseholdsByRegion.Count, (int flatRegionIndex) =>
            {
                if (flatRegionIndex == 0)
                {
                    return;
                }
                var region = HouseholdsByRegion.GetFlatData()[flatRegionIndex];
                var householdIndexArray = householdsByZoneIndexToRegion.GetFlatData();
                var householdArray      = HouseholdsByZone.GetFlatData();
                for (int i = 0; i < region.Count; i++)
                {
                    var currentHousehold  = region[i];
                    var flatZone          = zoneArray.GetFlatIndex(currentHousehold.HomeZone.ZoneNumber);
                    var household         = householdArray[flatZone];
                    var householdIndex    = householdIndexArray[flatZone];
                    int index             = household.IndexOf(currentHousehold);
                    householdIndex[index] = i;
                }
            });
            Console.WriteLine("Starting Pass 1");
            Parallel.For(0, HouseholdsByRegion.Count, (int flatRegionIndex) =>
            {
                if (flatRegionIndex == 0)
                {
                    return;
                }
                var regionNumber     = HouseholdsByRegion.GetSparseIndex(flatRegionIndex);
                var zonesToProcess   = zones.Where(z => z.RegionNumber == regionNumber).ToArray();
                var regionLookup     = HouseholdsByRegion.GetFlatData()[flatRegionIndex];
                var remaining        = remainingHouseholds[flatRegionIndex];
                var resultsForRegion = results[flatRegionIndex];
                for (int z = 0; z < zonesToProcess.Length; z++)
                {
                    int attempts       = 0;
                    int flatZone       = zoneArray.GetFlatIndex(zonesToProcess[z].ZoneNumber);
                    var householdIndex = householdsByZoneIndexToRegion.GetFlatData()[flatZone];
                    // the difference is negative so we need to add not subtract
                    int populationToAdd = zonalDifferences[flatZone] >= 0 ? basePopulation[flatZone] : basePopulation[flatZone] + zonalDifferences[flatZone];
                    var zonalHouseholds = HouseholdsByZone.GetFlatData()[flatZone];
                    int i = 0;
                    List <int> tossedHouseholds = new List <int>();
                    for (int pop = 0; pop < populationToAdd;)
                    {
                        if (attempts > 2)
                        {
                            throw new XTMFRuntimeException("In '" + Name + "' we were unable to assign a base population for zone '" + zonesToProcess[z].ZoneNumber + "'!");
                        }
                        for (i = 0; i < zonalHouseholds.Count; i++)
                        {
                            var hhld   = zonalHouseholds[i];
                            var newPop = pop + hhld.Persons.Length;
                            if (newPop <= populationToAdd)
                            {
                                pop = newPop;
                                resultsForRegion.Add(new KeyValuePair <int, int>(flatZone, householdIndex[i]));
                                if (pop >= populationToAdd)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                tossedHouseholds.Add(i);
                            }
                        }
                        attempts++;
                    }
                    // if we didn't use everything add the rest of the households to the remaining list
                    var lookupIndex = lookupsForRegion[flatRegionIndex];
                    // first add all the households we excluded to finish the zone
                    foreach (var tossed in tossedHouseholds)
                    {
                        remaining.Add(zonalHouseholds[tossed]);
                        lookupIndex.Add(householdIndex[tossed]);
                    }
                    // then add the rest of the households we haven't looked at
                    if (attempts <= 1)
                    {
                        for (; i < zonalHouseholds.Count; i++)
                        {
                            remaining.Add(zonalHouseholds[i]);
                            lookupIndex.Add(householdIndex[i]);
                        }
                    }
                }
            });
        }
 private SparseArray<float> GetWarmBalancingFactors(SparseArray<float> attraction, out string balanceFileName)
 {
     SparseArray<float> balanceFactors = null;
     if ( this.BalanceFactors.ContainsFileName() )
     {
         balanceFileName = this.BalanceFactors.GetFileName() + this.CurrentMultiSetIndex + ".bin";
         if ( File.Exists( balanceFileName ) )
         {
             balanceFactors = LoadBalanceFactors( balanceFileName );
         }
         else
         {
             balanceFactors = attraction.CreateSimilarArray<float>();
             var flatFactors = balanceFactors.GetFlatData();
             // initialize the factors to 1
             for ( int i = 0; i < flatFactors.Length; i++ )
             {
                 flatFactors[i] = 1.0f;
             }
         }
     }
     else
     {
         balanceFileName = null;
     }
     return balanceFactors;
 }
Esempio n. 11
0
        private void WriteParallel(int[] validZones, SparseArray<IPerson[]> population, StreamWriter writer, int length)
        {
            var output = population.CreateSimilarArray<StringBuilder>();
            var flatOutput = output.GetFlatData();
            var flatPop = population.GetFlatData();
            int current = 0;
            Parallel.For( 0, length,
                delegate(int i)
                {
                    var popInZone = flatPop[i];
                    if ( popInZone == null ) return;
                    StringBuilder builder = new StringBuilder();
                    foreach ( var person in popInZone )
                    {
                        builder.Append( validZones[i] );
                        if ( person == null )
                        {
                            builder.AppendLine( ", PERSON MISSING!" );
                            continue;
                        }
                        builder.Append( ',' );
                        builder.Append( person.Age );
                        builder.Append( ',' );
                        builder.Append( person.Household != null ? person.Household.Cars : 0 );
                        builder.Append( ',' );
                        builder.Append( person.SchoolZone != null ? person.SchoolZone.ZoneNumber : -1 );
                        builder.Append( ',' );
                        builder.Append( person.WorkZone != null ? person.WorkZone.ZoneNumber : -1 );
                        builder.Append( ',' );
                        builder.Append( (int)person.EmploymentStatus );
                        builder.Append( ',' );
                        builder.Append( (int)person.StudentStatus );
                        builder.Append( ',' );
                        builder.Append( (int)person.Occupation );
                        builder.Append( ',' );
                        builder.Append( person.DriversLicense ? 1 : 0 );
                        builder.Append( ',' );
                        builder.Append( person.ExpansionFactor );
                        builder.AppendLine();
                    }
                    flatOutput[i] = builder;
                    System.Threading.Interlocked.Increment( ref current );
                    this.Progress = (float)current / length;
                } );

            for ( int i = 0; i < length; i++ )
            {
                var sbuilder = flatOutput[i];
                if ( sbuilder != null )
                {
                    writer.Write( sbuilder.ToString() );
                }
            }
            this.Progress = 1;
        }
Esempio n. 12
0
 private SparseArray<int> SplitAndClear(int pop, SparseArray<float> splitPercentages, Random rand)
 {
     var flatSplitPercentages = splitPercentages.GetFlatData();
     var length = flatSplitPercentages.Length;
     var ret = splitPercentages.CreateSimilarArray<int>();
     var flatRet = ret.GetFlatData();
     var flatRemainder = new float[length];
     float remainderTotal = 0;
     int total = 0;
     for ( int i = 0; i < length; i++ )
     {
         float element = ( flatSplitPercentages[i] * pop );
         total += ( flatRet[i] = (int)Math.Floor( element ) );
         flatRemainder[i] = element - flatRet[i];
     }
     int notAssigned = pop - total;
     // Make sure that we do not over assign
     remainderTotal = notAssigned;
     for ( int i = 0; i < notAssigned; i++ )
     {
         var randPop = rand.NextDouble() * remainderTotal;
         float ammountToReduce = 0;
         int j = 0;
         for ( ; j < length; j++ )
         {
             randPop -= ( ammountToReduce = flatRemainder[j] );
             if ( randPop <= 0 )
             {
                 remainderTotal -= ammountToReduce;
                 flatRemainder[j] = 0;
                 flatRet[j] += 1;
                 break;
             }
         }
         if ( j == length )
         {
             for ( j = 0; j < length; j++ )
             {
                 if ( flatRemainder[j] >= 0 )
                 {
                     remainderTotal -= flatRemainder[j];
                     flatRemainder[j] = 0;
                     flatRet[j] += 1;
                     break;
                 }
             }
         }
     }
     return ret;
 }