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; }
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"); }
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); } }
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); }
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)); }
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; }
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); }
/// <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); } } }
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; }
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); } } }
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)); } }
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)); } } }
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)); } } }
/// <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); } } }
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); } } }