예제 #1
0
파일: AddRates.cs 프로젝트: dianatle/XTMF
        public void LoadData()
        {
            var zoneArray = Root.ZoneSystem.ZoneArray;
            var zones     = zoneArray.GetFlatData();
            var resources = ResourcesToAdd.Select(resource => resource.AquireResource <SparseArray <float> >().GetFlatData()).ToArray();
            SparseArray <float> data;

            data = SaveRatesBasedOnPD ? ZoneSystemHelper.CreatePDArray <float>(zoneArray) : zoneArray.CreateSimilarArray <float>();
            var flatData = data.GetFlatData();

            if (VectorHelper.IsHardwareAccelerated)
            {
                for (int j = 0; j < resources.Length; j++)
                {
                    VectorHelper.Add(flatData, 0, flatData, 0, resources[j], 0, flatData.Length);
                }
            }
            else
            {
                for (int j = 0; j < resources.Length; j++)
                {
                    var currentResource = resources[j];
                    for (int i = 0; i < currentResource.Length; i++)
                    {
                        flatData[i] += currentResource[i];
                    }
                }
            }
            Data = data;
        }
예제 #2
0
        public void LoadData()
        {
            var first      = ModuleHelper.GetDataFromDatasourceOrResource(FirstRateToApplyRaw, FirstRateToApply, FirstRateToApplyRaw != null);
            var firstRate  = first.GetFlatData();
            var secondRate = ModuleHelper.GetDataFromDatasourceOrResource(SecondRateToApplyRaw, SecondRateToApply, SecondRateToApplyRaw != null).GetFlatData();
            SparseTwinIndex <float> data;

            data = first.CreateSimilarArray <float>();
            var flatData     = data.GetFlatData();
            var dereferenced = AdditionalRates.Select(a => a.AcquireResource <SparseTwinIndex <float> >().GetFlatData()).Union
                               (
                AdditionalRatesRaw.Select(source =>
            {
                source.LoadData();
                var ret = source.GiveData();
                source.UnloadData();
                return(ret.GetFlatData());
            })
                               ).ToArray();

            for (int i = 0; i < flatData.Length; i++)
            {
                VectorHelper.Add(flatData[i], 0, firstRate[i], 0, secondRate[i], 0, flatData[i].Length);
                for (int j = 0; j < dereferenced.Length; j++)
                {
                    VectorHelper.Add(flatData[i], 0, flatData[i], 0, dereferenced[j][i], 0, flatData[i].Length);
                }
            }
            Data = data;
        }
        private void Vectors_SumWithAnother()
        {
            Console.Clear();

            ConsoleHelper.WriteSeparator("Read the other vector");

            int[] other = VectorHelper.ReadFromConsole();

            Console.Clear();

            ConsoleHelper.WriteSeparator("First vector is ");

            VectorHelper.PrintToConsole(this.vector);

            ConsoleHelper.WriteSeparator("Second vector is ");

            VectorHelper.PrintToConsole(other);

            int[] sum = VectorHelper.Add(this.vector, other);

            ConsoleHelper.WriteSeparator("The sum (vector1 + vector2) is ");

            VectorHelper.PrintToConsole(sum);

            this.ExerciseEnd_PromptGoBackToMenu("vectors");
        }
예제 #4
0
파일: TestVector.cs 프로젝트: lunaxi7/XTMF
 public void TestVectorAdd()
 {
     float[] first  = Enumerable.Range(1, 100).Select(p => 2.0f).ToArray();
     float[] second = Enumerable.Range(1, 100).Select(p => 3.0f).ToArray();
     VectorHelper.Add(first, 0, first, 0, second, 0, first.Length);
     for (int i = 0; i < first.Length; i++)
     {
         Assert.AreEqual(5.0f, first[i], 0.00001f);
     }
 }
예제 #5
0
        private float[][] AggregateResults(float[][][] model, IZone[] zones)
        {
            var ret = AggArray;

            if (ret == null)
            {
                ret = new float[zones.Length][];
                for (int i = 0; i < ret.Length; i++)
                {
                    ret[i] = new float[zones.Length];
                }
                AggArray = ret;
            }
            Parallel.For(0, zones.Length, (int i) =>
            {
                var retRow = ret[i];
                if (model.Length > 0)
                {
                    var row = model[0][i];
                    for (int j = 0; j < row.Length; j++)
                    {
                        retRow[j] = row[j];
                    }
                    for (int k = 1; k < model.Length; k++)
                    {
                        row = model[k][i];
                        // accelerated
                        VectorHelper.Add(retRow, 0, retRow, 0, row, 0, row.Length);
                    }
                }
            });
            if (AggregateToPlanningDistricts)
            {
                var data = PDError.GetFlatData();
                for (int i = 0; i < data.Length; i++)
                {
                    var row = data[i];
                    for (int j = 0; j < row.Length; j++)
                    {
                        row[j] = 0;
                    }
                }
                for (int i = 0; i < ret.Length; i++)
                {
                    var row = ret[i];
                    for (int j = 0; j < row.Length; j++)
                    {
                        data[ZoneToPDIndexMap[i]][ZoneToPDIndexMap[j]] += row[j];
                    }
                }
                return(data);
            }
            return(ret);
        }
예제 #6
0
        private ComputationResult SumColumns(ComputationResult computationResult)
        {
            var data     = computationResult.OdData;
            var ret      = new SparseArray <float>(data.Indexes);
            var flatRet  = ret.GetFlatData();
            var flatData = data.GetFlatData();

            System.Threading.Tasks.Parallel.For(0, flatData.Length, (int i) =>
            {
                VectorHelper.Add(flatRet, 0, flatRet, 0, flatData[i], 0, flatData[i].Length);
            });
            return(new ComputationResult(ret, true, ComputationResult.VectorDirection.Horizontal));
        }
예제 #7
0
        public void LoadData()
        {
            var zoneArray  = Root.ZoneSystem.ZoneArray;
            var zones      = zoneArray.GetFlatData();
            var firstRate  = FirstRateToApply.AquireResource <SparseTwinIndex <float> >().GetFlatData();
            var secondRate = SecondRateToApply.AquireResource <SparseTwinIndex <float> >().GetFlatData();
            SparseTwinIndex <float> data;

            data = zoneArray.CreateSquareTwinArray <float>();
            var flatData     = data.GetFlatData();
            var dereferenced = AdditionalRates.Select(a => a.AquireResource <SparseTwinIndex <float> >().GetFlatData()).ToArray();

            if (VectorHelper.IsHardwareAccelerated)
            {
                for (int i = 0; i < flatData.Length; i++)
                {
                    VectorHelper.Add(flatData[i], 0, firstRate[i], 0, secondRate[i], 0, flatData[i].Length);
                    for (int j = 0; j < dereferenced.Length; j++)
                    {
                        VectorHelper.Add(flatData[i], 0, flatData[i], 0, dereferenced[j][i], 0, flatData[i].Length);
                    }
                }
            }
            else
            {
                for (int i = 0; i < flatData.Length; i++)
                {
                    for (int k = 0; k < flatData[i].Length; k++)
                    {
                        flatData[i][k] = firstRate[i][k] + secondRate[i][k];
                    }
                    for (int j = 0; j < dereferenced.Length; j++)
                    {
                        for (int k = 0; k < flatData[i].Length; k++)
                        {
                            flatData[i][k] = flatData[i][k] + dereferenced[j][i][k];
                        }
                    }
                }
            }
            Data = data;
        }
예제 #8
0
 public void IterationFinished(int iteration)
 {
     if (SpecialGenerators.Length > 0)
     {
         var specialGenerationResults = Root.ZoneSystem.ZoneArray.CreateSquareTwinArray <float>().GetFlatData();
         // Apply the special generators
         for (int i = 0; i < SpecialGenerators.Length; i++)
         {
             SpecialGenerators[i].IncludeTally(specialGenerationResults);
         }
         // Now scale the by household iterations and integrate it back into the result matrix
         Parallel.For(0, specialGenerationResults.Length, (int i) =>
         {
             VectorHelper.Multiply(specialGenerationResults[i], 0, specialGenerationResults[i], 0, HouseholdIterations, specialGenerationResults[i].Length);
             VectorHelper.Add(Matrix[i], 0, Matrix[i], 0, specialGenerationResults[i], 0, specialGenerationResults.Length);
         });
     }
     // write to disk
     new EmmeMatrix(ZoneSystem, Matrix).Save(MatrixSaveLocation, true);
 }
예제 #9
0
                /// <summary>
                /// Copy the linkages in case they need to be reset.
                /// </summary>
                /// <param name="linkages"></param>
                private void CopyLinkages(SparseTriIndex <float> linkages)
                {
                    _originalLinkages = linkages.CreateSimilarArray <float>();
                    var flatLinkages = linkages.GetFlatData();
                    var flatOriginal = _originalLinkages.GetFlatData();
                    var numberofPDs  = _planningDistricts.Count;
                    var zones        = _zoneSystem.GetFlatData();

                    _totalEmployment = new float[numberofPDs][][];
                    _assigned        = new float[numberofPDs][][];
                    for (int pd = 0; pd < numberofPDs; pd++)
                    {
                        _totalEmployment[pd] = new float[3][];
                        _assigned[pd]        = new float[3][];
                    }
                    for (int i = 0; i < flatLinkages.Length; i++)
                    {
                        for (int pd = 0; pd < numberofPDs; pd++)
                        {
                            _totalEmployment[pd][i] = new float[flatLinkages[i].Length];
                            _assigned[pd][i]        = new float[flatLinkages[i].Length];
                        }
                        for (int j = 0; j < flatLinkages[i].Length; j++)
                        {
                            Array.Copy(flatLinkages[i][j], flatOriginal[i][j], flatLinkages[i][j].Length);
                        }
                    }
                    for (int type = 0; type < flatLinkages.Length; type++)
                    {
                        for (int i = 0; i < zones.Length; i++)
                        {
                            var iPD     = _planningDistricts.GetFlatIndex(zones[i].PlanningDistrict);
                            var empRow  = _totalEmployment[iPD][type];
                            var linkRow = flatLinkages[type][i];
                            VectorHelper.Add(empRow, 0, empRow, 0, linkRow, 0, empRow.Length);
                        }
                    }
                }
예제 #10
0
        public void LoadData()
        {
            var zoneArray = Root.ZoneSystem.ZoneArray;
            var resources = ResourcesToAdd.Select(resource => resource.AcquireResource <SparseArray <float> >().GetFlatData()).Union(
                ResourcesToAddRaw.Select(source =>
            {
                source.LoadData();
                var ret = source.GiveData();
                source.UnloadData();
                return(ret.GetFlatData());
            })
                ).ToArray();
            SparseArray <float> data;

            data = SaveRatesBasedOnPD ? ZoneSystemHelper.CreatePdArray <float>(zoneArray) : zoneArray.CreateSimilarArray <float>();
            var flatData = data.GetFlatData();

            for (int j = 0; j < resources.Length; j++)
            {
                VectorHelper.Add(flatData, 0, flatData, 0, resources[j], 0, flatData.Length);
            }
            Data = data;
        }
예제 #11
0
        public void IncludeTally(float[][] currentTally)
        {
            var zoneSystem = Root.ZoneSystem.ZoneArray;
            var zones      = zoneSystem.GetFlatData();

            BuildData(zones);
            var tripChains     = BaseYearTrips.AcquireResource <List <ITripChain> >();
            var basePopulation = BaseYearPopulation.AcquireResource <SparseArray <float> >().GetFlatData();
            var ratio          = new float[zones.Length];

            for (int i = 0; i < ratio.Length; i++)
            {
                ratio[i] = zones[i].Population / basePopulation[i];
                if (float.IsInfinity(ratio[i]) | float.IsNaN(ratio[i]))
                {
                    ratio[i] = 1;
                }
            }
            // Use the current tally if we don't care to save the results.
            // Otherwise we should create a replica so we can save those results then
            // recombine them at the end
            var tallyToUse = currentTally;

            if (SaveResults != null)
            {
                tallyToUse = new float[currentTally.Length][];
                for (int i = 0; i < tallyToUse.Length; i++)
                {
                    tallyToUse[i] = new float[currentTally[i].Length];
                }
            }
            for (int i = 0; i < tripChains.Count; i++)
            {
                var chain = tripChains[i];
                if ((chain.StartTime >= StartTime) | (chain.EndTime < EndTime))
                {
                    var person          = chain.Person;
                    var homeZone        = zoneSystem.GetFlatIndex(person.Household.HomeZone.ZoneNumber);
                    var expansionFactor = person.ExpansionFactor * ratio[homeZone];
                    foreach (var trip in chain.Trips)
                    {
                        var tripStart = trip.TripStartTime;
                        if ((tripStart >= StartTime) & (tripStart < EndTime))
                        {
                            var originZone           = trip.OriginalZone.ZoneNumber;
                            var destinationZone      = trip.DestinationZone.ZoneNumber;
                            var originZoneIndex      = zoneSystem.GetFlatIndex(originZone);
                            var destinationZoneIndex = zoneSystem.GetFlatIndex(destinationZone);
                            if (ImplementExternalTransit && ExternalTransit.Contains(trip.Mode))
                            {
                                var originExternal      = ExternalZones.Contains(originZone);
                                var destinationExternal = ExternalZones.Contains(destinationZone);
                                if (originExternal && destinationExternal)
                                {
                                    // if the transit trip is external ignore it since we don't model the service
                                    continue;
                                }
                                else
                                {
                                    if (RecordAccess)
                                    {
                                        // if we are recording the auto side of the trip
                                        if (originExternal)
                                        {
                                            tallyToUse[originZoneIndex][ClosestStationIndex[destinationZoneIndex]] += expansionFactor;
                                        }
                                        else if (destinationExternal)
                                        {
                                            tallyToUse[ClosestStationIndex[originZoneIndex]][destinationZoneIndex] += expansionFactor;
                                        }
                                        else
                                        {
                                            tallyToUse[originZoneIndex][destinationZoneIndex] += expansionFactor;
                                        }
                                    }
                                    else
                                    {
                                        // if we are recording the transit side of the trip
                                        if (originExternal)
                                        {
                                            tallyToUse[ClosestStationIndex[originZoneIndex]][destinationZoneIndex] += expansionFactor;
                                        }
                                        else if (destinationExternal)
                                        {
                                            tallyToUse[originZoneIndex][ClosestStationIndex[destinationZoneIndex]] += expansionFactor;
                                        }
                                        else
                                        {
                                            tallyToUse[originZoneIndex][destinationZoneIndex] += expansionFactor;
                                        }
                                    }
                                }
                            }
                            else if (trip.Mode == PrimaryMode)
                            {
                                tallyToUse[originZoneIndex][destinationZoneIndex] += expansionFactor;
                            }
                        }
                    }
                }
            }
            if (SaveResults != null)
            {
                // save the results then combine them into the current tally
                SaveData.SaveMatrix(zoneSystem.GetFlatData(), tallyToUse, SaveResults);
                // now that the data is saved we need to recombine the data
                for (int i = 0; i < tallyToUse.Length; i++)
                {
                    VectorHelper.Add(currentTally[i], 0, currentTally[i], 0, tallyToUse[i], 0, tallyToUse[i].Length);
                }
            }
        }
예제 #12
0
 private ComputationResult EvaluateAddIsMatrix(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
 {
     if (lhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
     {
         return(new ComputationResult("Unable to multiply vector without directionality starting at position " + MulLhs.Start + "!"));
     }
     if (rhs.IsVectorResult && rhs.Direction == ComputationResult.VectorDirection.Unassigned)
     {
         return(new ComputationResult("Unable to multiply vector without directionality starting at position " + MulRhs.Start + "!"));
     }
     // Ensure that the LHS is a higher or equal order to the RHS (Matrix > Vector > Scalar)
     if (!lhs.IsOdResult)
     {
         Swap(ref lhs, ref rhs);
     }
     if (lhs.IsValue)
     {
         Swap(ref lhs, ref rhs);
     }
     // LHS is now a higher or equal to the order of RHS
     if (lhs.IsOdResult)
     {
         if (rhs.IsOdResult)
         {
             var retMatrix = add.Accumulator ? add.OdData :
                             (lhs.Accumulator ? lhs.OdData :
                              (rhs.Accumulator ? rhs.OdData : add.OdData.CreateSimilarArray <float>()));
             VectorHelper.FusedMultiplyAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.OdData.GetFlatData(), add.OdData.GetFlatData());
             return(new ComputationResult(retMatrix, true));
         }
         else if (rhs.IsVectorResult)
         {
             var retMatrix = add.Accumulator ? add.OdData :
                             (lhs.Accumulator ? lhs.OdData : add.OdData.CreateSimilarArray <float>());
             if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
             {
                 VectorHelper.FusedMultiplyAddVerticalRhs(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.OdData.GetFlatData());
             }
             else
             {
                 VectorHelper.FusedMultiplyAddHorizontalRhs(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.OdData.GetFlatData());
             }
             return(new ComputationResult(retMatrix, true));
         }
         else
         {
             //RHS is scalar
             var retMatrix = add.Accumulator ? add.OdData :
                             (lhs.Accumulator ? lhs.OdData : add.OdData.CreateSimilarArray <float>());
             VectorHelper.FusedMultiplyAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.LiteralValue, add.OdData.GetFlatData());
             return(new ComputationResult(retMatrix, true));
         }
     }
     else if (lhs.IsVectorResult)
     {
         var retMatrix  = add.Accumulator ? add.OdData : add.OdData.CreateSimilarArray <float>();
         var tempVector = lhs.Accumulator ? lhs.VectorData : (rhs.IsVectorResult && rhs.Accumulator ? rhs.VectorData : lhs.VectorData.CreateSimilarArray <float>());
         // compute the multiplication separately in this case for better performance (n multiplies instead of n^2)
         if (rhs.IsVectorResult)
         {
             if (lhs.Direction != rhs.Direction)
             {
                 // if the directions don't add up then the sum operation would be undefined!
                 return(new ComputationResult("Unable to add vector without directionality starting at position " + MulLhs.Start + "!"));
             }
             VectorHelper.Multiply(tempVector.GetFlatData(), 0, lhs.VectorData.GetFlatData(), 0, rhs.VectorData.GetFlatData(), 0, tempVector.GetFlatData().Length);
         }
         else
         {
             VectorHelper.Multiply(tempVector.GetFlatData(), lhs.VectorData.GetFlatData(), rhs.LiteralValue);
         }
         if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
         {
             VectorHelper.AddVertical(retMatrix.GetFlatData(), add.OdData.GetFlatData(), tempVector.GetFlatData());
         }
         else
         {
             VectorHelper.AddHorizontal(retMatrix.GetFlatData(), add.OdData.GetFlatData(), tempVector.GetFlatData());
         }
         return(new ComputationResult(retMatrix, true));
     }
     else
     {
         // in this case LHS is a scalar, and therefore RHS is also a scalar
         var retMatrix = add.Accumulator ? add.OdData : add.OdData.CreateSimilarArray <float>();
         VectorHelper.Add(retMatrix.GetFlatData(), add.OdData.GetFlatData(), lhs.LiteralValue * rhs.LiteralValue);
         return(new ComputationResult(retMatrix, true));
     }
 }
예제 #13
0
 private ComputationResult EvaluateAddIsVector(ComputationResult lhs, ComputationResult rhs, ComputationResult add)
 {
     // Test the simple case of this really just being an add with a constant multiply
     if (lhs.IsValue && rhs.IsValue)
     {
         var retVector = add.Accumulator ? add.VectorData : add.VectorData.CreateSimilarArray <float>();
         VectorHelper.Add(retVector.GetFlatData(), add.VectorData.GetFlatData(), lhs.LiteralValue * rhs.LiteralValue);
         return(new ComputationResult(retVector, true, add.Direction));
     }
     if (lhs.IsOdResult || rhs.IsOdResult)
     {
         if (lhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
         {
             return(new ComputationResult("Unable to multiply vector without directionality starting at position " + MulLhs.Start + "!"));
         }
         if (rhs.IsVectorResult && lhs.Direction == ComputationResult.VectorDirection.Unassigned)
         {
             return(new ComputationResult("Unable to multiply vector without directionality starting at position " + MulRhs.Start + "!"));
         }
         if (add.Direction == ComputationResult.VectorDirection.Unassigned)
         {
             return(new ComputationResult("Unable to add vector without directionality starting at position " + Add.Start + "!"));
         }
         // if the lhs is a value just swap the two around
         if (!lhs.IsOdResult)
         {
             Swap(ref lhs, ref rhs);
         }
         //LHS is a matrix
         if (rhs.IsOdResult)
         {
             var retMatrix = rhs.Accumulator ? rhs.OdData :
                             (lhs.Accumulator ? lhs.OdData : lhs.OdData.CreateSimilarArray <float>());
             if (add.Direction == ComputationResult.VectorDirection.Vertical)
             {
                 VectorHelper.FusedMultiplyAddVerticalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.OdData.GetFlatData(), add.VectorData.GetFlatData());
             }
             else
             {
                 VectorHelper.FusedMultiplyAddHorizontalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.OdData.GetFlatData(), add.VectorData.GetFlatData());
             }
             return(new ComputationResult(retMatrix, true));
         }
         else if (rhs.IsVectorResult)
         {
             var retMatrix = lhs.Accumulator ? lhs.OdData : lhs.OdData.CreateSimilarArray <float>();
             if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
             {
                 if (add.Direction == ComputationResult.VectorDirection.Vertical)
                 {
                     VectorHelper.FusedMultiplyAddVerticalRhsVerticalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.VectorData.GetFlatData());
                 }
                 else
                 {
                     VectorHelper.FusedMultiplyAddVerticalRhsHorizontalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.VectorData.GetFlatData());
                 }
             }
             else
             {
                 if (add.Direction == ComputationResult.VectorDirection.Vertical)
                 {
                     VectorHelper.FusedMultiplyAddHorizontalRhsVerticalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.VectorData.GetFlatData());
                 }
                 else
                 {
                     VectorHelper.FusedMultiplyAddHorizontalRhsHorizontalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.VectorData.GetFlatData(), add.VectorData.GetFlatData());
                 }
             }
             return(new ComputationResult(retMatrix, true));
         }
         else
         {
             //RHS is a scalar
             var retMatrix = lhs.Accumulator ? lhs.OdData : lhs.OdData.CreateSimilarArray <float>();
             if (add.Direction == ComputationResult.VectorDirection.Vertical)
             {
                 VectorHelper.FusedMultiplyAddVerticalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.LiteralValue, add.VectorData.GetFlatData());
             }
             else
             {
                 VectorHelper.FusedMultiplyAddHorizontalAdd(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.LiteralValue, add.VectorData.GetFlatData());
             }
             return(new ComputationResult(retMatrix, true));
         }
     }
     // vector cases
     else
     {
         // if the lhs is a value just swap the two around
         if (lhs.IsValue)
         {
             Swap(ref lhs, ref rhs);
         }
         // vector * vector + vector
         if (rhs.IsVectorResult)
         {
             var retVector = add.Accumulator ? add.VectorData :
                             (rhs.Accumulator ? rhs.VectorData :
                              (lhs.Accumulator ? lhs.VectorData : lhs.VectorData.CreateSimilarArray <float>()));
             VectorHelper.FusedMultiplyAdd(retVector.GetFlatData(), lhs.VectorData.GetFlatData(), rhs.VectorData.GetFlatData(), add.VectorData.GetFlatData());
             return(new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned));
         }
         // vector * lit + vector
         else
         {
             var retVector = add.Accumulator ? add.VectorData :
                             (lhs.Accumulator ? lhs.VectorData : lhs.VectorData.CreateSimilarArray <float>());
             VectorHelper.FusedMultiplyAdd(retVector.GetFlatData(), lhs.VectorData.GetFlatData(), rhs.LiteralValue, add.VectorData.GetFlatData());
             return(new ComputationResult(retVector, true, add.Direction == lhs.Direction && add.Direction == rhs.Direction ? add.Direction : ComputationResult.VectorDirection.Unassigned));
         }
     }
 }
예제 #14
0
 public override ComputationResult Evaluate(ComputationResult lhs, ComputationResult rhs)
 {
     // see if we have two values, in this case we can skip doing the matrix operation
     if (lhs.IsValue && rhs.IsValue)
     {
         return(new ComputationResult(lhs.LiteralValue + rhs.LiteralValue));
     }
     // float / matrix
     if (lhs.IsValue)
     {
         if (rhs.IsVectorResult)
         {
             var retVector = rhs.Accumulator ? rhs.VectorData : rhs.VectorData.CreateSimilarArray <float>();
             var flat      = retVector.GetFlatData();
             VectorHelper.Add(flat, rhs.VectorData.GetFlatData(), lhs.LiteralValue);
             return(new ComputationResult(retVector, true));
         }
         else
         {
             var retMatrix = rhs.Accumulator ? rhs.OdData : rhs.OdData.CreateSimilarArray <float>();
             VectorHelper.Add(retMatrix.GetFlatData(), lhs.LiteralValue, rhs.OdData.GetFlatData());
             return(new ComputationResult(retMatrix, true));
         }
     }
     else if (rhs.IsValue)
     {
         if (lhs.IsVectorResult)
         {
             var retVector = lhs.Accumulator ? lhs.VectorData : lhs.VectorData.CreateSimilarArray <float>();
             var flat      = retVector.GetFlatData();
             VectorHelper.Add(flat, lhs.VectorData.GetFlatData(), rhs.LiteralValue);
             return(new ComputationResult(retVector, true));
         }
         else
         {
             // matrix / float
             var retMatrix = lhs.Accumulator ? lhs.OdData : lhs.OdData.CreateSimilarArray <float>();
             VectorHelper.Add(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.LiteralValue);
             return(new ComputationResult(retMatrix, true));
         }
     }
     else
     {
         if (lhs.IsVectorResult || rhs.IsVectorResult)
         {
             if (lhs.IsVectorResult && rhs.IsVectorResult)
             {
                 var retMatrix = lhs.Accumulator ? lhs.VectorData : (rhs.Accumulator ? rhs.VectorData : lhs.VectorData.CreateSimilarArray <float>());
                 VectorHelper.Add(retMatrix.GetFlatData(), 0, lhs.VectorData.GetFlatData(), 0, rhs.VectorData.GetFlatData(), 0, retMatrix.GetFlatData().Length);
                 return(new ComputationResult(retMatrix, true, lhs.Direction));
             }
             else if (lhs.IsVectorResult)
             {
                 var retMatrix = rhs.Accumulator ? rhs.OdData : rhs.OdData.CreateSimilarArray <float>();
                 var flatRet   = retMatrix.GetFlatData();
                 var flatRhs   = rhs.OdData.GetFlatData();
                 var flatLhs   = lhs.VectorData.GetFlatData();
                 if (lhs.Direction == ComputationResult.VectorDirection.Vertical)
                 {
                     System.Threading.Tasks.Parallel.For(0, flatRet.Length, i =>
                     {
                         VectorHelper.Add(flatRet[i], flatRhs[i], flatLhs[i]);
                     });
                 }
                 else if (lhs.Direction == ComputationResult.VectorDirection.Horizontal)
                 {
                     System.Threading.Tasks.Parallel.For(0, flatRet.Length, i =>
                     {
                         VectorHelper.Add(flatRet[i], 0, flatLhs, 0, flatRhs[i], 0, flatRet[i].Length);
                     });
                 }
                 else
                 {
                     return(new ComputationResult("Unable to add vector without directionality starting at position " + Lhs.Start + "!"));
                 }
                 return(new ComputationResult(retMatrix, true));
             }
             else
             {
                 var retMatrix = lhs.Accumulator ? lhs.OdData : lhs.OdData.CreateSimilarArray <float>();
                 var flatRet   = retMatrix.GetFlatData();
                 var flatLhs   = lhs.OdData.GetFlatData();
                 var flatRhs   = rhs.VectorData.GetFlatData();
                 if (rhs.Direction == ComputationResult.VectorDirection.Vertical)
                 {
                     System.Threading.Tasks.Parallel.For(0, flatRet.Length, i =>
                     {
                         VectorHelper.Add(flatRet[i], flatLhs[i], flatRhs[i]);
                     });
                 }
                 else if (rhs.Direction == ComputationResult.VectorDirection.Horizontal)
                 {
                     System.Threading.Tasks.Parallel.For(0, flatRet.Length, i =>
                     {
                         VectorHelper.Add(flatRet[i], 0, flatRhs, 0, flatLhs[i], 0, flatRet[i].Length);
                     });
                 }
                 else
                 {
                     return(new ComputationResult("Unable to add vector without directionality starting at position " + Lhs.Start + "!"));
                 }
                 return(new ComputationResult(retMatrix, true));
             }
         }
         else
         {
             var retMatrix = lhs.Accumulator ? lhs.OdData : (rhs.Accumulator ? rhs.OdData : lhs.OdData.CreateSimilarArray <float>());
             VectorHelper.Add(retMatrix.GetFlatData(), lhs.OdData.GetFlatData(), rhs.OdData.GetFlatData());
             return(new ComputationResult(retMatrix, true));
         }
     }
 }
예제 #15
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        /// <param name="iterator">The iterator to use to control when to stop iterating.</param>
        /// <param name="preconditioner">The preconditioner to use for approximations.</param>
        public void Solve(Matrix <double> matrix, Vector <double> input, Vector <double> result,
                          Iterator <double> iterator, IPreconditioner <double> preconditioner)
        {
            var A = (SparseMatrix)matrix;
            var M = preconditioner;

            var b = (DenseVector)input;
            var x = (DenseVector)result;

            double atolf  = 0.0;
            double rtol_1 = 0.0;
            int    recompute_residual_p = 0;

            var p = new DenseVector(b.Count);
            var s = new DenseVector(b.Count);
            var r = new DenseVector(b.Count);

            double alpha, beta;
            double gamma, gamma_old;
            double bi_prod;

            double sdotp;
            bool   recompute_true_residual = false;

            int i = 0;

            M.Initialize(A);

            // Start pcg solve

            // bi_prod = <C*b,b>
            //VectorHelper.Clear(p);
            M.Approximate(input, p);
            bi_prod = VectorHelper.DotProduct(p, b);

            if (bi_prod > 0.0)
            {
                if (atolf > 0)  // mixed relative and absolute tolerance
                {
                    bi_prod += atolf;
                }
            }
            else    // bi_prod==0.0: the rhs vector b is zero
            {
                // Set x equal to zero and return
                VectorHelper.Copy(b, x);
                return;
            }

            // r = b - Ax
            VectorHelper.Copy(b, r);
            A.Multiply(-1.0, result, 1.0, r);

            // p = C*r
            //VectorHelper.Clear(p);
            M.Approximate(r, p);

            // gamma = <r,p>
            gamma = VectorHelper.DotProduct(r, p);

            while (iterator.DetermineStatus(i, x, b, r) == IterationStatus.Continue)
            {
                // the core CG calculations...
                i++;

                // At user request, periodically recompute the residual from the formula
                // r = b - A x (instead of using the recursive definition). Note that this
                // is potentially expensive and can lead to degraded convergence (since it
                // essentially a "restarted CG").
                recompute_true_residual = (recompute_residual_p > 0) && !((i % recompute_residual_p) == 0);

                // s = A*p
                A.Multiply(1.0, p, 0.0, s);

                // alpha = gamma / <s,p>
                sdotp = VectorHelper.DotProduct(s, p);
                if (sdotp == 0.0)
                {
                    throw new NumericalBreakdownException();
                }
                alpha = gamma / sdotp;

                gamma_old = gamma;

                // x = x + alpha*p
                VectorHelper.Add(alpha, p, x, x);

                // r = r - alpha*s
                if (recompute_true_residual)
                {
                    //Recomputing the residual...
                    VectorHelper.Copy(b, r);
                    A.Multiply(-1.0, result, 1.0, r);
                }
                else
                {
                    VectorHelper.Add(-alpha, s, r, r);
                }

                // s = C*r
                VectorHelper.Clear(s);
                M.Approximate(r, s);

                // gamma = <r,s>
                gamma = VectorHelper.DotProduct(r, s);

                // residual-based stopping criteria: ||r_new-r_old||_C < rtol ||b||_C
                if (rtol_1 > 0)
                {
                    // use that ||r_new-r_old||_C^2 = (r_new ,C r_new) + (r_old, C r_old)
                    if ((gamma + gamma_old) / bi_prod < rtol_1 * rtol_1)
                    {
                        break;
                    }
                }

                // ... gamma should be >=0.  IEEE subnormal numbers are < 2**(-1022)=2.2e-308
                // (and >= 2**(-1074)=4.9e-324).  So a gamma this small means we're getting
                // dangerously close to subnormal or zero numbers (usually if gamma is small,
                // so will be other variables).  Thus further calculations risk a crash.
                // Such small gamma generally means no hope of progress anyway.
                if (Math.Abs(gamma) < TINY)
                {
                    throw new NumericalBreakdownException();
                }

                // beta = gamma / gamma_old
                beta = gamma / gamma_old;

                // p = s + beta p
                if (recompute_true_residual)
                {
                    VectorHelper.Copy(s, p);
                }
                else
                {
                    p.Scale(beta);
                    VectorHelper.Add(1.0, s, p, p);
                }
            }
        }
예제 #16
0
        public void IncludeTally(float[][] currentTally)
        {
            var zoneSystem     = Root.ZoneSystem.ZoneArray;
            var zones          = zoneSystem.GetFlatData();
            var tripChains     = BaseYearTrips.AquireResource <List <ITripChain> >();
            var basePopulation = BaseYearPopulation.AquireResource <SparseArray <float> >().GetFlatData();
            var ratio          = new float[zones.Length];

            for (int i = 0; i < ratio.Length; i++)
            {
                ratio[i] = zones[i].Population / basePopulation[i];
                if (float.IsInfinity(ratio[i]) | float.IsNaN(ratio[i]))
                {
                    ratio[i] = 1;
                }
            }
            // Use the current tally if we don't care to save the results.
            // Otherwise we should create a replica so we can save those results then
            // recombine them at the end
            var tallyToUse = currentTally;

            if (SaveResults != null)
            {
                tallyToUse = new float[currentTally.Length][];
                for (int i = 0; i < tallyToUse.Length; i++)
                {
                    tallyToUse[i] = new float[currentTally[i].Length];
                }
            }
            for (int i = 0; i < tripChains.Count; i++)
            {
                var chain = tripChains[i];
                if ((chain.StartTime >= StartTime) | (chain.EndTime < EndTime))
                {
                    var person          = chain.Person;
                    var homeZone        = zoneSystem.GetFlatIndex(person.Household.HomeZone.ZoneNumber);
                    var expansionFactor = person.ExpansionFactor * ratio[homeZone];
                    foreach (var trip in chain.Trips)
                    {
                        if (trip.Mode != Mode)
                        {
                            continue;
                        }
                        var tripStart = trip.TripStartTime;
                        if ((tripStart >= StartTime) & (tripStart < EndTime))
                        {
                            tallyToUse[zoneSystem.GetFlatIndex(trip.OriginalZone.ZoneNumber)][zoneSystem.GetFlatIndex(trip.DestinationZone.ZoneNumber)]
                                += expansionFactor;
                        }
                    }
                }
            }
            if (SaveResults != null)
            {
                // save the results then combine them into the current tally
                SaveData.SaveMatrix(zoneSystem.GetFlatData(), tallyToUse, SaveResults);
                // now that the data is saved we need to recombine the data
                for (int i = 0; i < tallyToUse.Length; i++)
                {
                    VectorHelper.Add(currentTally[i], 0, currentTally[i], 0, tallyToUse[i], 0, tallyToUse[i].Length);
                }
            }
        }