public GravityModel(SparseTwinIndex<float> friction, Action<float> progressCallback = null, float epsilon = 0.8f, int maxIterations = 100, float maxErrorChangePerIteration = 0.000100f) { Epsilon = epsilon; Friction = friction; MaxIterations = maxIterations; ProgressCallback = progressCallback; MaxErrorChangePerIteration = maxErrorChangePerIteration; }
private static float EmployedMobilityProbability(int mobility, int emp, int occ, SparseTriIndex<float> ncars, int age, SparseTwinIndex<float> dlicRate) { switch ( mobility ) { case 0: return ( 1 - dlicRate[age, emp] ) * ncars[0, occ, 0]; case 1: return ( 1 - dlicRate[age, emp] ) * ncars[0, occ, 1]; case 2: return ( 1 - dlicRate[age, emp] ) * ncars[0, occ, 2]; case 3: return ( dlicRate[age, emp] * ncars[1, occ, 0] ); case 4: return dlicRate[age, emp] * ncars[1, occ, 1]; case 5: return dlicRate[age, emp] * ncars[1, occ, 2]; default: throw new XTMFRuntimeException( "Unknown mobility type '" + mobility.ToString() + "'!" ); } }
private void LoadAgeDist() { List <AgeDist> ageDistributions = new List <AgeDist>(); var ageCategories = AgeCategories.Count; using (CommentedCsvReader reader = new CommentedCsvReader(this.AgeDistributionFile.GetFileName(Root.InputBaseDirectory))) { while (reader.NextLine()) { if (reader.NumberOfCurrentCells >= ageCategories + 1) { int zone; float[] ageD = new float[ageCategories]; reader.Get(out zone, 0); for (int i = 1; i < reader.NumberOfCurrentCells; i++) { reader.Get(out ageD[i - 1], i); } ageDistributions.Add(new AgeDist() { Zone = zone, Percentages = ageD }); } } } int numberOfSetZones = 0; foreach (var ageDist in ageDistributions) { List <int> pd; if (!this.PDZoneMap.TryGetValue(ageDist.Zone, out pd)) { throw new XTMFRuntimeException("In " + this.Name + " we were unable to find a planning district for the zone number '" + ageDist.Zone + "' while loading the age distribution."); } numberOfSetZones += pd.Count; } var elements = ageDistributions.Count; var records = elements * ageCategories; var first = new int[numberOfSetZones * ageCategories]; var second = new int[numberOfSetZones * ageCategories]; var d = new float[numberOfSetZones * ageCategories]; var validAgeCategory = AgeCategories.ValidIndexies().ToArray(); int soFar = 0; for (int i = 0; i < elements; i++) { var zones = this.PDZoneMap[ageDistributions[i].Zone]; foreach (var zone in zones) { for (int j = 0; j < ageCategories; j++) { first[soFar] = zone; second[soFar] = validAgeCategory[j]; d[soFar] = ageDistributions[i].Percentages[j]; soFar++; } } } this.AgeRates = SparseTwinIndex <float> .CreateTwinIndex(first, second, d); }
public void IterationStarting(int iteration) { this.ExpandedStudents = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); this.ToSave = new BlockingCollection<Assignment>(); this.SaveTask = Task.Factory.StartNew( () => { var students = this.ExpandedStudents; foreach ( var assignment in this.ToSave.GetConsumingEnumerable() ) { students[assignment.HouseholdZone, assignment.SchoolZone] += assignment.Expanded; } }, TaskCreationOptions.LongRunning ); }
private static void BuildDistribution(SparseTwinIndex<float> ret, SparseArray<float> O, SparseArray<float> D, int oLength, float[] flows) { var retFlat = ret.GetFlatData(); var ratio = O.GetFlatData().Sum() / flows.Sum(); if ( float.IsNaN( ratio ) | float.IsInfinity( ratio ) ) { Parallel.For( 0, retFlat.Length, delegate(int i) { var iOffset = i * oLength; var ith = retFlat[i]; for ( int j = 0; j < oLength; j++ ) { ith[j] = ( float.IsNaN( ratio ) | float.IsInfinity( ratio ) ) ? 0f : flows[iOffset + j]; } } ); return; } Parallel.For( 0, retFlat.Length, delegate(int i) { var iOffset = i * oLength; var ith = retFlat[i]; for ( int j = 0; j < oLength; j++ ) { ith[j] = flows[iOffset + j] * ratio; } } ); }
private void AverageDiagonals(int districtNumber, IZone[] flatZones, SparseTwinIndex<float> matrix) { var flatData = matrix.GetFlatData(); var length = flatData.Length; var average = GetAverageIntraZonalTravelTime( districtNumber, flatZones, flatData ); if ( average == 0 ) { // if the average is 0 then there were no trips for ( int i = 0; i < length; i++ ) { var otherPD = flatZones[i].PlanningDistrict; if ( otherPD != districtNumber ) { var otherAverage = GetAverageIntraZonalTravelTime( otherPD, flatZones, flatData ); if ( otherAverage != 0 ) { var ratio = this.GetNumberOfZonesRatio( flatZones, otherPD, districtNumber ); var radius = BuildDistrictRadius(); var distanceRatio = radius[districtNumber] / radius[otherPD]; average = otherAverage * distanceRatio * ratio; } } } } // after we have the average apply it to the rest of the district's intra zonal trips for ( int i = 0; i < length; i++ ) { if ( flatZones[i].PlanningDistrict != districtNumber ) continue; if ( flatData[i][i] <= 0 ) { flatData[i][i] = average; } } }
private void InitializeFriction(int length) { Friction = Productions.CreateSquareTwinArray<float>(); var flatFriction = Friction.GetFlatData(); Parallel.For(0, length, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate (int i) { for(int j = 0; j < length; j++) { flatFriction[i][j] = (float)FrictionFunction(Productions.GetSparseIndex(i), Attractions.GetSparseIndex(j)); } }); }
private void AddModeSplit(SparseTwinIndex<float> matrix) { if ( this.Results == null ) { InitializeResults(); } if ( this.InterativeMode ) { ProduceResultsForInteractive( matrix.GetFlatData() ); } else { throw new XTMFRuntimeException( "Only Interactive mode is supported!" ); } }
public void LoadData() { if ( this.Data != null ) { this.Data.Release(); } var cache = GetFullPath( this.ODC ); if ( ( this.Regenerate && AlreadyLoaded ) || !File.Exists( cache ) ) { this.Generate(); } this.Data = new ODCache( cache ); this.StoredData = this.Data.StoreAll(); this.AlreadyLoaded = true; }
public static void SaveMatrix(SparseTwinIndex <float> matrix, string fileName) { var zones = matrix.ValidIndexArray(); var data = matrix.GetFlatData(); StringBuilder header = null; StringBuilder[] zoneLines = new StringBuilder[zones.Length]; Parallel.Invoke( () => { var dir = Path.GetDirectoryName(fileName); if (!String.IsNullOrWhiteSpace(dir)) { if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } }, () => { header = new StringBuilder(); header.Append("Zones O\\D"); for (int i = 0; i < zones.Length; i++) { header.Append(','); header.Append(zones[i]); } }, () => { Parallel.For(0, zones.Length, (int i) => { zoneLines[i] = new StringBuilder(); zoneLines[i].Append(zones[i]); var row = data[i]; if (row == null) { for (int j = 0; j < zones.Length; j++) { zoneLines[i].Append(','); zoneLines[i].Append('0'); } } else { for (int j = 0; j < zones.Length; j++) { zoneLines[i].Append(','); zoneLines[i].Append(row[j]); } } }); }); using (StreamWriter writer = new StreamWriter(fileName)) { writer.WriteLine(header); for (int i = 0; i < zoneLines.Length; i++) { writer.WriteLine(zoneLines[i]); } } }
private float UnemployedMobilityProbability(int mobility, SparseTriIndex <float> ncars, int age, SparseTwinIndex <float> dlicRate) { switch (mobility) { case 0: return((1 - dlicRate[age, 0]) * ncars[0, age, 0]); case 1: return((1 - dlicRate[age, 0]) * ncars[0, age, 1]); case 2: return((1 - dlicRate[age, 0]) * ncars[0, age, 2]); case 3: return(dlicRate[age, 0] * ncars[1, age, 0]); case 4: return(dlicRate[age, 0] * ncars[1, age, 1]); case 5: return(dlicRate[age, 0] * ncars[1, age, 2]); default: throw new XTMFRuntimeException(this, "Unknown mobility type '" + mobility + "'!"); } }
private void CreateIndices(SparseIndexing rootLevel, int i, SparseTwinIndex <float> innerData) { rootLevel.Indexes[GetIndexForFlat(rootLevel, i)].SubIndex = innerData.Indexes; }
private void SaveDistribution(SparseTwinIndex <float> sparseRet, IZone[] zone, int index) { this.SaveDistributionSeries.SaveMatrix(sparseRet.GetFlatData()); }
private void LoadStudentDist() { List <StudentDist> studentData = new List <StudentDist>(); using (CommentedCsvReader reader = new CommentedCsvReader(this.StudentDistributionFile.GetFileName(Root.InputBaseDirectory))) { float[] data = new float[4]; while (reader.NextLine()) { for (int i = 0; i < data.Length && i < reader.NumberOfCurrentCells; i++) { reader.Get(out data[i], i); } studentData.Add(new StudentDist() { Zone = (int)data[0], AgeCat = (int)data[1], EmploymentStatus = (int)data[2], Chance = data[3] }); } } studentData.Sort(new Comparison <StudentDist>(delegate(StudentDist first, StudentDist second) { if (first.Zone > second.Zone) { return(1); } else if (first.Zone == second.Zone) { if (first.AgeCat > second.AgeCat) { return(1); } else if (first.AgeCat == second.AgeCat) { if (first.EmploymentStatus > second.EmploymentStatus) { return(1); } else if (first.EmploymentStatus == second.EmploymentStatus) { return(0); } } } return(-1); })); // Employment is now sorted Zone,Age,EmploymentStatus this.SchoolRates = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray <SparseTwinIndex <float> >(); Range currentRange = new Range(); var studentDataLength = studentData.Count; int[] firstIndex; int[] secondIndex; float[] d; int numberOfElements; for (int i = 1; i < studentDataLength; i++) { if (studentData[i].Zone == studentData[i - 1].Zone) { currentRange.Stop = i; } else { numberOfElements = currentRange.Stop - currentRange.Start + 1; firstIndex = new int[numberOfElements]; secondIndex = new int[numberOfElements]; d = new float[numberOfElements]; for (int j = 0; j < numberOfElements; j++) { var data = studentData[currentRange.Start + j]; firstIndex[j] = data.AgeCat; secondIndex[j] = data.EmploymentStatus; d[j] = data.Chance; } foreach (var z in this.PDZoneMap[studentData[i - 1].Zone]) { this.SchoolRates[z] = SparseTwinIndex <float> .CreateTwinIndex(firstIndex, secondIndex, d); } currentRange.Start = i; } } numberOfElements = currentRange.Stop - currentRange.Start + 1; firstIndex = new int[numberOfElements]; secondIndex = new int[numberOfElements]; d = new float[numberOfElements]; for (int j = 0; j < numberOfElements; j++) { firstIndex[j] = studentData[currentRange.Start + j].AgeCat; secondIndex[j] = studentData[currentRange.Start + j].EmploymentStatus; d[j] = studentData[currentRange.Start + j].Chance; } foreach (var z in this.PDZoneMap[studentData[studentDataLength - 1].Zone]) { this.SchoolRates[z] = SparseTwinIndex <float> .CreateTwinIndex(firstIndex, secondIndex, d); } }
private void LoadEmploymentDist() { List <EmploymentDist> employment = new List <EmploymentDist>(); using (CommentedCsvReader reader = new CommentedCsvReader(this.EmploymentDistributionFile.GetFileName(Root.InputBaseDirectory))) { float[] data = new float[5]; while (reader.NextLine()) { if (reader.NumberOfCurrentCells < 5) { continue; } for (int i = 0; i < data.Length && i < reader.NumberOfCurrentCells; i++) { reader.Get(out data[i], i); } employment.Add(new EmploymentDist() { AgeCat = (int)data[1], Zone = (int)data[0], NonWork = data[2], FullTime = data[3], PartTime = data[4] }); } } employment.Sort(new Comparison <EmploymentDist>( delegate(EmploymentDist first, EmploymentDist second) { if (first.Zone > second.Zone) { return(1); } else if (first.Zone == second.Zone) { if (first.AgeCat > second.AgeCat) { return(1); } else if (first.AgeCat == second.AgeCat) { return(0); } } return(-1); })); this.EmploymentStatusRates = this.Root.ZoneSystem.ZoneArray.CreateSimilarArray <SparseTwinIndex <float> >(); Range currentRange = new Range(); var employmentLength = employment.Count; int[] firstIndex; int[] secondIndex; float[] d; int numberOfElements; for (int i = 1; i < employmentLength; i++) { if (employment[i].Zone == employment[i - 1].Zone) { currentRange.Stop = i; } else { numberOfElements = currentRange.Stop - currentRange.Start + 1; firstIndex = new int[numberOfElements * 3]; secondIndex = new int[numberOfElements * 3]; d = new float[numberOfElements * 3]; for (int j = 0; j < numberOfElements; j++) { var ageCat = employment[currentRange.Start + j].AgeCat; for (int k = 0; k < 3; k++) { firstIndex[j * 3 + k] = ageCat; secondIndex[j * 3 + k] = k; } d[j * 3] = employment[currentRange.Start + j].NonWork; d[j * 3 + 1] = employment[currentRange.Start + j].FullTime; d[j * 3 + 2] = employment[currentRange.Start + j].PartTime; } foreach (var z in this.PDZoneMap[employment[i - 1].Zone]) { this.EmploymentStatusRates[z] = SparseTwinIndex <float> .CreateTwinIndex(firstIndex, secondIndex, d); } currentRange.Start = i; } } numberOfElements = currentRange.Stop - currentRange.Start + 1; firstIndex = new int[numberOfElements * 3]; secondIndex = new int[numberOfElements * 3]; d = new float[numberOfElements * 3]; for (int j = 0; j < numberOfElements; j++) { for (int k = 0; k < 3; k++) { firstIndex[j * 3 + k] = employment[currentRange.Start + j].AgeCat; secondIndex[j * 3 + k] = k; } d[j * 3] = employment[currentRange.Start + j].NonWork; d[j * 3 + 1] = employment[currentRange.Start + j].FullTime; d[j * 3 + 2] = employment[currentRange.Start + j].PartTime; } foreach (var z in this.PDZoneMap[employment[employmentLength - 1].Zone]) { this.EmploymentStatusRates[z] = SparseTwinIndex <float> .CreateTwinIndex(firstIndex, secondIndex, d); } }
public bool GetData(out SparseArray<Node> nodes, out SparseTwinIndex<Link> links) { nodes = GetNodes(); links = GetLinks(); return true; }
public void IterationStarting(int iteration, int totalIterations) { WriteThisIteration = iteration == totalIterations - 1; if(WriteThisIteration) { ZoneDistances = Root.ZoneSystem.Distances; Writer = new StreamWriter(SaveTo); WriteHeader(); } }
private float ApplyMobilityProbability(int mobility, int emp, int occ, SparseTriIndex <float> ncars, int age, SparseTwinIndex <float> dlicRate) { // make sure the age is greater than 0 age = (age == 0 ? 1 : age); // now we have slightly different forms depending if the person is a worker or not if (emp == 0) { return(UnemployedMobilityProbability(mobility, ncars, age, dlicRate)); } else { return(EmployedMobilityProbability(mobility, emp, occ, ncars, age, dlicRate)); } }
private float[] ProcessLoadedData(SparseTwinIndex<float[]> loadedData, int types, int times) { var flatLoadedData = loadedData.GetFlatData(); var dataEntries = this.DataEntries = times * types; var zoneArray = this.Root.ZoneSystem.ZoneArray; var zones = zoneArray.GetFlatData(); this.NumberOfZones = zones.Length; var ret = new float[zones.Length * zones.Length * types * times]; Parallel.For( 0, flatLoadedData.Length, (int i) => { var flatI = zoneArray.GetFlatIndex( loadedData.GetSparseIndex( i ) ); for ( int j = 0; j < flatLoadedData[i].Length; j++ ) { if ( flatLoadedData[i][j] == null ) continue; var flatJ = zoneArray.GetFlatIndex( loadedData.GetSparseIndex( i, j ) ); for ( int k = 0; k < flatLoadedData[i][j].Length; k++ ) { ret[( flatI * zones.Length + flatJ ) * dataEntries + k] = flatLoadedData[i][j][k]; } } } ); return ret; }
private float GenerateForWorkingStudent(IZone[] zones, int zoneIndex, SparseTwinIndex <float> ageRates, SparseTwinIndex <float> empRates, SparseTriIndex <float> occRates, SparseTwinIndex <float> dlicRate, SparseTriIndex <float> ncars, int age, float ppGenerationRate, int emp, float studentFactor) { float temp = 0; var ageEmpRate = ageRates[zones[zoneIndex].ZoneNumber, age] * empRates[age, emp] * studentFactor; foreach (var occSet in this.OccupationCategory) { for (int occ = occSet.Start; occ <= occSet.Stop; occ++) { var nonMobilityRate = ageEmpRate * occRates[age, emp, occ]; foreach (var mobilitySet in this.Mobility) { for (int mob = mobilitySet.Start; mob <= mobilitySet.Stop; mob++) { // calculate the probability of a person of this type for this zone var catFactor = nonMobilityRate * ApplyMobilityProbability(mob, emp, occ, ncars, age, dlicRate); // now apply that to temp += zones[zoneIndex].Population * catFactor * ppGenerationRate; } } } } return(temp); }
public static void SaveMatrixThirdNormalized(SparseTwinIndex<float> matrix, FileLocation saveLocation) { using (StreamWriter writer = new StreamWriter(saveLocation)) { writer.WriteLine("Origin,Destination,Data"); foreach (var o in matrix.ValidIndexes()) { foreach (var d in matrix.ValidIndexes(o)) { writer.Write(o); writer.Write(','); writer.Write(d); writer.Write(','); writer.WriteLine(matrix[o, d]); } } } }
private static float EmployedMobilityProbability(int mobility, int emp, int occ, SparseTriIndex <float> ncars, int age, SparseTwinIndex <float> dlicRate) { switch (mobility) { case 0: return((1 - dlicRate[age, emp]) * ncars[0, occ, 0]); case 1: return((1 - dlicRate[age, emp]) * ncars[0, occ, 1]); case 2: return((1 - dlicRate[age, emp]) * ncars[0, occ, 2]); case 3: return(dlicRate[age, emp] * ncars[1, occ, 0]); case 4: return(dlicRate[age, emp] * ncars[1, occ, 1]); case 5: return(dlicRate[age, emp] * ncars[1, occ, 2]); default: throw new XTMFRuntimeException("Unknown mobility type '" + mobility.ToString() + "'!"); } }
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; }
public void UnloadData() { this.Data = null; }
private void FillRatioIntraZonalTravelTime(int districtNumber, IZone[] flatZones, SparseTwinIndex<float> matrix, SparseArray<float> radius) { var validDistricts = radius.ValidIndexArray(); var flatRadius = radius.GetFlatData(); for ( int otherDistrict = 0; otherDistrict < validDistricts.Length; otherDistrict++ ) { var sparseOther = radius.GetSparseIndex( otherDistrict ); if ( sparseOther == districtNumber ) continue; if ( this.AnyTripIntraDistrict( otherDistrict, flatZones, matrix ) ) { var distanceRatio = radius[districtNumber] / flatRadius[otherDistrict]; var data = matrix.GetFlatData(); var averageTT = GetAverageIntraDistrictNonIntraZonalTravelTime( sparseOther, flatZones, data ); var averageIntraZonealTT = GetAverageIntraZonalTravelTime( sparseOther, flatZones, data ); var zoneRatio = GetNumberOfZonesRatio( flatZones, districtNumber, sparseOther ); averageTT *= distanceRatio * zoneRatio; averageIntraZonealTT *= distanceRatio * zoneRatio; for ( int i = 0; i < flatZones.Length; i++ ) { if ( flatZones[i].PlanningDistrict != districtNumber ) continue; for ( int j = 0; j < flatZones.Length; j++ ) { if ( flatZones[j].PlanningDistrict != districtNumber ) continue; if ( i == j ) { data[i][j] = averageIntraZonealTT; } else { data[i][j] = averageTT; } } } break; } } }
public static void SaveFlows(SparseTwinIndex <float> data, string fileName) { //TODO: Save the flows!!! }
public void IterationStarting(int iteration) { Fitness = 0.0f; if(ConfusionMatrix != null) { Choices = (Root.MainClient as ITravelDemandModel).ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); } // reload all of the probabilities LocationChoice.LoadLocationChoiceCache(); }
private static float Sum(SparseTwinIndex <float> data) { return(data.GetFlatData().AsParallel().Sum(row => row.Sum())); }
private static void TransposeMatrix(SparseTwinIndex<float> ret) { var flatData = ret.GetFlatData(); var length = flatData.Length; for ( int i = 0; i < length; i++ ) { for ( int j = 0; j < i; j++ ) { var temp = flatData[i][j]; flatData[i][j] = flatData[j][i]; flatData[j][i] = temp; } } }
private SparseTwinIndex <float> CreateRelativeDifference <T>(SparseTwinIndex <float> runData, SparseTwinIndex <float> baseData, SparseArray <T> refernceArray, Func <IZone, int> getAgg) { var ret = refernceArray.CreateSquareTwinArray <float>(); var truth = refernceArray.CreateSquareTwinArray <float>(); var zones = this.Root.ZoneSystem.ZoneArray.GetFlatData(); var flatRun = runData.GetFlatData(); var flatBaseData = baseData.GetFlatData(); for (int i = 0; i < flatRun.Length; i++) { var oAgg = getAgg(zones[i]); for (int j = 0; j < flatRun[i].Length; j++) { var jAgg = getAgg(zones[j]); ret[oAgg, jAgg] += flatRun[i][j]; truth[oAgg, jAgg] += flatBaseData[i][j]; } } var factor = Sum(truth) / Sum(ret); var flatRetData = ret.GetFlatData(); var flatTruthData = truth.GetFlatData(); for (int i = 0; i < flatRetData.Length; i++) { for (int j = 0; j < flatRetData[i].Length; j++) { flatRetData[i][j] = (flatRetData[i][j] * factor) / flatTruthData[i][j]; } } return(ret); }
protected virtual void Dispose(bool all) { this.Links = null; this.Nodes = null; }
private void ProduceRegionData(float[][] diff, SparseTwinIndex <float> runData, SparseTwinIndex <float> baseData) { var regionMap = this.CreateRegionArray(); var zones = this.Root.ZoneSystem.ZoneArray.GetFlatData(); var regionData = regionMap.CreateSquareTwinArray <float>().GetFlatData(); var regionDataEntries = regionMap.CreateSquareTwinArray <int>().GetFlatData(); // take the zoneal differences and aggregate them to the region level for (int i = 0; i < diff.Length; i++) { var o = regionMap.GetFlatIndex(zones[i].RegionNumber); for (int j = 0; j < diff[i].Length; j++) { var d = regionMap.GetFlatIndex(zones[j].RegionNumber); regionData[o][d] += diff[i][j]; regionDataEntries[o][d]++; } } if (this.AverageSums) { for (int i = 0; i < regionData.Length; i++) { var row = regionData[i]; var numberOfEntries = regionDataEntries[i]; for (int j = 0; j < row.Length; j++) { row[j] = row[j] / numberOfEntries[j]; } } } if (this.RegionValidationFile.ContainsFileName()) { WriteOut(regionMap, regionData, this.RegionValidationFile.GetFileName(), (i => i)); } SparseTwinIndex <float> relativeDiff = CreateRelativeDifference(runData, baseData, regionMap, (zone => zone.RegionNumber)); if (this.RegionRelativeValidationFile.ContainsFileName()) { WriteOut(regionMap, relativeDiff.GetFlatData(), this.RegionRelativeValidationFile.GetFileName(), (i => i)); } }
/// <summary> /// Load the network from a 211 file /// </summary> /// <param name="fileName211"></param> public void LoadNetwork(string fileName211) { Dictionary<int, Node> nodes = new Dictionary<int, Node>(); Dictionary<Pair<int, int>, Link> links = new Dictionary<Pair<int, int>, Link>(); using ( StreamReader reader = new StreamReader( fileName211 ) ) { string line = null; // run until we get to the link information while ( ( line = reader.ReadLine() ) != null ) { string[] parts = line.Split( SplitCharacters, StringSplitOptions.RemoveEmptyEntries ); try { var numberOfParts = parts.Length; if ( numberOfParts >= 3 && parts[0].Length > 0 ) { int offset = -1; if ( parts[0][0] == 'a' ) { offset = 0; } else if ( parts[0][0] == 'c' ) { continue; } Node node = new Node(); if ( offset == -1 ) { node.IsCentroid = false; } else { node.IsCentroid = ( parts[0].Length >= 2 && parts[0] == "a*" ); } node.Number = int.Parse( parts[1 + offset] ); node.X = float.Parse( parts[2 + offset] ); node.Y = float.Parse( parts[3 + offset] ); if ( numberOfParts > 4 + offset ) { node.USER1 = int.Parse( parts[4 + offset] ); if ( numberOfParts > 5 + offset ) { node.USER2 = int.Parse( parts[5 + offset] ); if ( numberOfParts > 6 + offset ) { node.NodeType = int.Parse( parts[6 + offset] ); node.Modified = false; if ( parts.Length > 7 + offset ) { node.NodeLabel = parts[7 + offset]; } else { node.NodeLabel = node.Number.ToString(); } } } } nodes.Add( node.Number, node ); } } catch { } if ( line != null && line.StartsWith( "t links" ) ) { break; } } while ( ( line = reader.ReadLine() ) != null ) { try { string[] parts = line.Split( SplitCharacters, StringSplitOptions.RemoveEmptyEntries ); if ( parts.Length > 7 ) { Link link; link.I = int.Parse( parts[1] ); link.J = int.Parse( parts[2] ); link.Length = float.Parse( parts[3] ); link.Modes = parts[4].ToLower().ToCharArray(); link.LinkType = int.Parse( parts[5] ); link.Lanes = float.Parse( parts[6] ); link.VDF = float.Parse( parts[7] ); // We don't load [8] link.Speed = float.Parse( parts[9] ); link.Capacity = float.Parse( parts[10] ); link.Modified = false; links.Add( new Pair<int, int>( link.I, link.J ), link ); } } catch { } } } // Now that we have loaded the data it is time to create the sparse structures var numberOfLinks = links.Count; var first = new int[numberOfLinks]; var second = new int[numberOfLinks]; var data = new Link[numberOfLinks]; int i = 0; foreach ( var l in links.Values ) { first[i] = l.I; second[i] = l.J; data[i] = l; i++; } if ( nodes.Values.Count == 0 ) { this.Nodes = null; } else { this.Nodes = SparseArray<Node>.CreateSparseArray( ( n => n.Number ), nodes.Values.ToArray() ); } if ( numberOfLinks == 0 ) { this.Links = null; } else { this.Links = SparseTwinIndex<Link>.CreateTwinIndex( first, second, data ); } }
private void ProduceZoneData(float[][] diff, SparseTwinIndex <float> runData, SparseTwinIndex <float> baseData) { SparseTwinIndex <float> relativeDiff = CreateRelativeDifference(runData, baseData, this.Root.ZoneSystem.ZoneArray, (zone => zone.ZoneNumber)); if (this.ZoneValidationFile.ContainsFileName()) { WriteOut(this.Root.ZoneSystem.ZoneArray, diff, this.ZoneValidationFile.GetFileName(), (zone => zone.ZoneNumber)); } if (this.ZoneRelativeValidationFile.ContainsFileName()) { WriteOut(this.Root.ZoneSystem.ZoneArray, relativeDiff.GetFlatData(), this.ZoneRelativeValidationFile.GetFileName(), (zone => zone.ZoneNumber)); } }
public void Load(int maxIterations) { this._ZoneDistances = Root.ZoneSystem.Distances; this._BinData = new float[1 + this.HistogramBins.Count][]; //Extra bin for outside of the array for (int i = 0; i < this._BinData.Length; i++) { this._BinData[i] = new float[3]; } }
public List <TreeData <float[][]> > ModeSplit(SparseTwinIndex <float> flowMatrix) { AddModeSplit(flowMatrix); return(CreateList()); }
public void UnloadData() { if ( this.Data != null ) { this.Data.Release(); this.Data = null; } this.StoredData = null; }
public void LoadData() { var zoneArray = Root.ZoneSystem.ZoneArray; var zones = zoneArray.GetFlatData(); var data = LocalData; if (data == null) { LocalData = data = new float[zones.Length * zones.Length * NumberOfWorkerCategories]; } var distances = Root.ZoneSystem.Distances.GetFlatData(); var pds = PlanningDistricts; if (pds == null) { PlanningDistricts = pds = zones.Select((zone) => zone.PlanningDistrict).ToArray(); } if (KeepLocalData) { CreateHighPerformanceLookup(zoneArray); } float[] workerSplits = LoadWorkerCategories(zones, zoneArray); SparseTwinIndex <float> kFactors = null; if (KFactors != null) { kFactors = KFactors.AcquireResource <SparseTwinIndex <float> >(); Parallel.For(0, zones.Length, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (int i) => { var distanceRow = distances[i]; var iPD = pds[i]; for (int k = 0; k < NumberOfWorkerCategories; k++) { int offset = k * zones.Length * zones.Length + i * zones.Length; for (int j = 0; j < zones.Length; j++) { // use distance in km data[offset + j] = kFactors[iPD, pds[j]] * CalculateUtilityToE(iPD, pds[j], i, j, k, distanceRow[j] * 0.001f); } } }); KFactors.ReleaseResource(); } else { Parallel.For(0, zones.Length, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, (int i) => { var distanceRow = distances[i]; var iPD = pds[i]; for (int k = 0; k < NumberOfWorkerCategories; k++) { int offset = k * zones.Length * zones.Length + i * zones.Length; for (int j = 0; j < zones.Length; j++) { // use distance in km data[offset + j] = CalculateUtilityToE(iPD, pds[j], i, j, k, distanceRow[j] * 0.001f); } } }); } SparseArray <float> employmentSeekers = EmployedPopulationResidenceByZone.AcquireResource <SparseArray <float> >(); var jobs = CreateNormalizedJobs(employmentSeekers, JobsByZone.AcquireResource <SparseArray <float> >().GetFlatData()); var results = TMG.Functions.GravityModel3D.ProduceFlows(MaxIterations, Epsilon, CreateWorkersByCategory(employmentSeekers, workerSplits), jobs, data, NumberOfWorkerCategories, zones.Length); var itModel = Root as IIterativeModel; if (itModel != null && itModel.CurrentIteration > 0) { AverageResults(results, PreviousResults); } Data = ConvertResults(results, zoneArray); PreviousResults = results; if (!KeepLocalData) { LocalData = null; PlanningDistricts = null; WorkerCategories = null; } Loaded = true; }
public List<TreeData<float[][]>> ModeSplit(SparseTwinIndex<float> flowMatrix) { AddModeSplit( flowMatrix ); return CreateList(); }
public void LoadData() { if (Data == null | LastIteration != Root.CurrentIteration) { LastIteration = Root.CurrentIteration; var zoneArray = Root.ZoneSystem.ZoneArray; var zones = zoneArray.GetFlatData(); int[] accessZones = null; float[] trains = null; SparseTwinIndex <Tuple <IZone[], IZone[], float[]> > data = null; // these will be flagged to true if we needed to load a network bool loadedGo = false, loadedTransit = false, loadedPremiumTransit = false; Parallel.Invoke(() => { accessZones = GetAccessZones(zoneArray); data = zoneArray.CreateSquareTwinArray <Tuple <IZone[], IZone[], float[]> >(); }, () => { LoadStationData(zoneArray, out float[] parking, out trains); }, () => { if (!GoTransitNetwork.Loaded) { GoTransitNetwork.LoadData(); loadedGo = true; } }, () => { if (!TransitNetwork.Loaded) { TransitNetwork.LoadData(); loadedTransit = true; } }, () => { if (!PremiumTransitNetwork.Loaded) { PremiumTransitNetwork.LoadData(); loadedPremiumTransit = true; } }); var flatData = data.GetFlatData(); Console.WriteLine("Computing TAG Access station utilities."); Stopwatch watch = Stopwatch.StartNew(); float[][] egressUtility = new float[accessZones.Length][]; int[][] egressZones = new int[accessZones.Length][]; float[][] egressTime = new float[accessZones.Length][]; for (int i = 0; i < egressUtility.Length; i++) { egressUtility[i] = new float[zones.Length]; egressTime[i] = new float[zones.Length]; egressZones[i] = new int[zones.Length]; } // compute the egress data Parallel.For(0, accessZones.Length, i => { var interchange = accessZones[i]; for (int j = 0; j < zones.Length; j++) { // you also don't need to compute the access station choices for destinations that are access stations if (zones[j].RegionNumber <= 0) { egressTime[i][j] = float.NaN; egressUtility[i][j] = float.NaN; egressZones[i][j] = -1; } ComputeEgressStation(interchange, j, accessZones, trains, out egressUtility[i][j], out egressTime[i][j], out egressZones[i][j]); } }); // using the egress data compute access stations Parallel.For(0, zones.Length, o => { // There is no need to compute drive access subway when you are starting at an access station int regionO = zones[o].RegionNumber; if (regionO == 0 | accessZones.Contains(o)) { return; } // for the rest of the zones though, compute it to all destinations for (int d = 0; d < zones.Length; d++) { // you also don't need to compute the access station choices for destinations that are access stations var regionD = zones[d].RegionNumber; if (regionD == 0 | accessZones.Contains(d)) { continue; } if ((regionO == 1) | (regionO != regionD)) { ComputeUtility(o, d, zones, accessZones, egressUtility, egressTime, egressZones, flatData); } } }); watch.Stop(); Console.WriteLine("It took " + watch.ElapsedMilliseconds + "ms to compute the TAG access stations."); // if we loaded the data make sure to unload it if (loadedGo) { GoTransitNetwork.UnloadData(); } if (loadedTransit) { TransitNetwork.UnloadData(); } if (loadedPremiumTransit) { PremiumTransitNetwork.UnloadData(); } Data = data; } }
public List<TreeData<float[][]>> ModeSplit(SparseTwinIndex<float> flowMatrix) { // no need to optimize this case since it is very rare. return this.ModeSplit( new SparseTwinIndex<float>[] { flowMatrix }, 1 ); }
public void UnloadData() { Data = null; }
public static void SaveMatrix(SparseTwinIndex<float> matrix, string fileName) { var zones = matrix.ValidIndexArray(); var data = matrix.GetFlatData(); StringBuilder header = null; StringBuilder[] zoneLines = new StringBuilder[zones.Length]; Parallel.Invoke( () => { var dir = Path.GetDirectoryName(fileName); if (!String.IsNullOrWhiteSpace(dir)) { if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } }, () => { header = new StringBuilder(); header.Append("Zones O\\D"); for (int i = 0; i < zones.Length; i++) { header.Append(','); header.Append(zones[i]); } }, () => { Parallel.For(0, zones.Length, (int i) => { zoneLines[i] = new StringBuilder(); zoneLines[i].Append(zones[i]); var row = data[i]; if (row == null) { for (int j = 0; j < zones.Length; j++) { zoneLines[i].Append(','); zoneLines[i].Append('0'); } } else { for (int j = 0; j < zones.Length; j++) { zoneLines[i].Append(','); zoneLines[i].Append(row[j]); } } }); }); using (StreamWriter writer = new StreamWriter(fileName)) { writer.WriteLine(header); for (int i = 0; i < zoneLines.Length; i++) { writer.WriteLine(zoneLines[i]); } } }
private void InitializeFlows() { this.Progress = 0; // we are going to need to split based on this information this.ZoneArray = this.Root.ZoneSystem.ZoneArray; var occupations = this.Root.Demographics.OccupationCategories; var validZones = this.ZoneArray.ValidIndexies().ToArray(); var numberOfZones = validZones.Length; //[Occupation][O , D] var distribution = occupations.CreateSimilarArray <SparseTwinIndex <float> >(); //Generate the place of work place of residence OD's SparseArray <float> O = this.ZoneArray.CreateSimilarArray <float>(); SparseArray <float> D = this.ZoneArray.CreateSimilarArray <float>(); var occupationIndexes = occupations.ValidIndexies().ToArray(); var numCat = Categories.Count; // Start burning that CPU Thread.CurrentThread.Priority = ThreadPriority.Highest; SparseTwinIndex <float> workplaceDistribution = null; SparseTwinIndex <float> prevWorkplaceDistribution = null; float[] friction = null; float[] nextFriction = null; MultiRunGPUGravityModel multiRunGPU = null; for (int i = 0; i < numCat; i++) { this.CurrentOccupationIndex = i; Task assignToPopulation = null; if (i > 0) { assignToPopulation = new Task(delegate() { if (prevWorkplaceDistribution != null) { // We actually are assigning to the previous category with this data so we need i - 1 AssignToWorkers(prevWorkplaceDistribution, this.Categories[i - 1]); prevWorkplaceDistribution = null; } }); assignToPopulation.Start(); } Task computeNextFriction = null; if (i + 1 < numCat) { computeNextFriction = new Task(delegate() { nextFriction = this.ComputeFriction(ZoneArray.GetFlatData(), this.Categories[i + 1], nextFriction); }); computeNextFriction.Start(); } this.Categories[i].Generate(O, D); if (this.UseGPU) { if (i == 0) { try { Parallel.Invoke(() => friction = this.ComputeFriction(ZoneArray.GetFlatData(), this.Categories[i], friction), () => multiRunGPU = new MultiRunGPUGravityModel(O.GetFlatData().Length, (progress => this.Progress = (progress / numCat) + ((float)i / numCat)), this.Epsilon, this.MaxIterations)); } catch (AggregateException e) { throw new XTMFRuntimeException(e.InnerException.Message + "\r\n" + e.InnerException.StackTrace); } } workplaceDistribution = multiRunGPU.ProcessFlow(friction, O, D); } else { GravityModel gravityModel = new GravityModel(ImpedenceFunction, (progress => this.Progress = (progress / numCat) + ((float)i / numCat)), this.Epsilon, this.MaxIterations); workplaceDistribution = gravityModel.ProcessFlow(O, D, validZones); } this.Progress = ((float)(i + 1) / numCat); if (assignToPopulation != null) { try { assignToPopulation.Wait(); assignToPopulation.Dispose(); assignToPopulation = null; } catch (AggregateException e) { throw new XTMFRuntimeException(e.InnerException.Message + "\r\n" + e.InnerException.StackTrace); } } if (computeNextFriction != null) { try { computeNextFriction.Wait(); computeNextFriction.Dispose(); computeNextFriction = null; } catch (AggregateException e) { throw new XTMFRuntimeException(e.InnerException.Message + "\r\n" + e.InnerException.StackTrace); } } prevWorkplaceDistribution = workplaceDistribution; var frictionTemp = friction; friction = nextFriction; nextFriction = friction; } friction = null; nextFriction = null; prevWorkplaceDistribution = null; if (multiRunGPU != null) { multiRunGPU.Dispose(); multiRunGPU = null; } AssignToWorkers(workplaceDistribution, this.Categories[numCat - 1]); workplaceDistribution = null; // ok now we can relax Thread.CurrentThread.Priority = ThreadPriority.Normal; GC.Collect(); }
protected virtual void Dispose(bool all) { Links = null; Nodes = null; }
public bool GetData(out SparseArray <Node> nodes, out SparseTwinIndex <Link> links) { nodes = GetNodes(); links = GetLinks(); return(true); }
private bool AnyTripIntraDistrict(int districtNumber, IZone[] flatZones, SparseTwinIndex<float> matrix) { var flatData = matrix.GetFlatData(); var length = flatData.Length; for ( int i = 0; i < length; i++ ) { if ( flatZones[i].PlanningDistrict != districtNumber ) continue; for ( int j = 0; j < length; j++ ) { if ( i == j ) continue; if ( flatZones[j].PlanningDistrict != districtNumber ) continue; if ( flatData[i][j] > 0 ) { return true; } } } return false; }
/// <summary> /// Load the network from a 211 file /// </summary> /// <param name="fileName211"></param> public void LoadNetwork(string fileName211) { Dictionary <int, Node> nodes = new Dictionary <int, Node>(); Dictionary <Pair <int, int>, Link> links = new Dictionary <Pair <int, int>, Link>(); using (StreamReader reader = new StreamReader(fileName211)) { string line; // run until we get to the link information while ((line = reader.ReadLine()) != null) { string[] parts = line.Split(SplitCharacters, StringSplitOptions.RemoveEmptyEntries); var numberOfParts = parts.Length; if (numberOfParts >= 3 && parts[0].Length > 0) { int offset = -1; if (parts[0][0] == 'a') { offset = 0; } else if (parts[0][0] == 'c') { continue; } Node node = new Node(); if (offset == -1) { node.IsCentroid = false; } else { node.IsCentroid = (parts[0].Length >= 2 && parts[0] == "a*"); } node.Number = int.Parse(parts[1 + offset]); node.X = float.Parse(parts[2 + offset]); node.Y = float.Parse(parts[3 + offset]); if (numberOfParts > 4 + offset) { node.User1 = int.Parse(parts[4 + offset]); if (numberOfParts > 5 + offset) { node.User2 = int.Parse(parts[5 + offset]); if (numberOfParts > 6 + offset) { node.NodeType = int.Parse(parts[6 + offset]); node.Modified = false; if (parts.Length > 7 + offset) { node.NodeLabel = parts[7 + offset]; } else { node.NodeLabel = node.Number.ToString(); } } } } nodes.Add(node.Number, node); } if (line.StartsWith("t links")) { break; } } while ((line = reader.ReadLine()) != null) { string[] parts = line.Split(SplitCharacters, StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 7) { var link = new Link(int.Parse(parts[1]), int.Parse(parts[2])) { Length = float.Parse(parts[3]), Modes = parts[4].ToLower().ToCharArray(), LinkType = int.Parse(parts[5]), Lanes = float.Parse(parts[6]), Vdf = float.Parse(parts[7]), Speed = float.Parse(parts[9]), Capacity = float.Parse(parts[10]), Modified = false }; // We don't load [8] links.Add(new Pair <int, int>(link.I, link.J), link); } } } // Now that we have loaded the data it is time to create the sparse structures var numberOfLinks = links.Count; var first = new int[numberOfLinks]; var second = new int[numberOfLinks]; var data = new Link[numberOfLinks]; int i = 0; foreach (var l in links.Values) { first[i] = l.I; second[i] = l.J; data[i] = l; i++; } if (nodes.Values.Count == 0) { Nodes = null; } else { Nodes = SparseArray <Node> .CreateSparseArray((n => n.Number), nodes.Values.ToArray()); } if (numberOfLinks == 0) { Links = null; } else { Links = SparseTwinIndex <Link> .CreateTwinIndex(first, second, data); } }
private void AverageIntraDistrictTravelTimes(int districtNumber, IZone[] flatZones, SparseTwinIndex<float> matrix) { var flatData = matrix.GetFlatData(); var length = flatData.Length; var average = GetAverageIntraDistrictNonIntraZonalTravelTime( districtNumber, flatZones, flatData ); // after we have the average apply it to the rest of the district's intra zonal trips for ( int i = 0; i < length; i++ ) { if ( flatZones[i].PlanningDistrict != districtNumber ) continue; for ( int j = 0; j < length; j++ ) { if ( i == j ) continue; if ( flatZones[j].PlanningDistrict != districtNumber ) continue; if ( flatData[i][j] <= 0 ) { flatData[i][j] = average; } } } }
public void UnloadData() { Loaded = false; Data = null; }
private void InitializeData() { var numberOfModes = this.AllModes.Count; this.TripCountMatrixes = new SparseTwinIndex<float>[numberOfModes][]; this.TripAvgTimeMatrixes = new SparseTwinIndex<float>[numberOfModes][]; for ( int i = 0; i < numberOfModes; i++ ) { this.TripCountMatrixes[i] = new SparseTwinIndex<float>[3]; this.TripAvgTimeMatrixes[i] = new SparseTwinIndex<float>[3]; } for ( int i = 0; i < numberOfModes; i++ ) { for ( int j = 0; j < 3; j++ ) { this.TripCountMatrixes[i][j] = this.ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); this.TripAvgTimeMatrixes[i][j] = this.ZoneSystem.ZoneArray.CreateSquareTwinArray<float>(); } } }
public void UnloadData() { Data = null; Loaded = false; }
private void RebuildCache(Time time) { lock ( this ) { System.Threading.Thread.MemoryBarrier(); if ( lastIteration == this.Root.CurrentIteration ) return; this.Cache = this.Root.ZoneSystem.ZoneArray.CreateSquareTwinArray<CacheData>(); foreach ( var child in this.Children ) { child.DumpCaches(); } lastIteration = this.Root.CurrentIteration; CacheTime = time; System.Threading.Thread.MemoryBarrier(); } }
public void SaveMatrix(SparseTwinIndex <float> matrix, string fileName) { TMG.Functions.SaveData.SaveMatrix(matrix, fileName); }
public void IterationStarting(int iterationNumber, int maxIterations) { if ( iterationNumber > 0 ) { this.AccessStationUtilities.ReleaseResource(); } // each iteration reload the utilities if ( ( this.AccessUtilities = this.AccessStationUtilities.AquireResource<SparseTwinIndex<Tuple<IZone[], IZone[], float[]>>>() ) == null ) { throw new XTMFRuntimeException( "In '" + this.Name + "' we were unable to gather our Access Station Utilities!" ); } }
/// <summary> /// Assign workers to zones /// </summary> /// <param name="workplaceDistribution"></param> /// <param name="category"></param> private void AssignToWorkers(SparseTwinIndex <float> workplaceDistribution, IDemographicCategoryGeneration category) { /* * -> For each zone * 1) Load the population * 2) Count the number of people * 3) Count the number of jobs for the zone * 4) Compute the ratio of people to jobs and Balance it by normalizing @ population level * 5) Shuffle the people to avoid bias * 6) Apply the random split algorithm from the Population Synthesis to finish it off */ var zoneIndexes = ZoneArray.ValidIndexies().ToArray(); var flatZones = ZoneArray.GetFlatData(); var numberOfZones = zoneIndexes.Length; var flatWorkplaceDistribution = workplaceDistribution.GetFlatData(); var flatPopulation = Root.Population.Population.GetFlatData(); Parallel.For(0, numberOfZones, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate { return(new Assignment { Dist = ZoneArray.CreateSimilarArray <float>(), Indexes = null }); }, delegate(int z, ParallelLoopState unused, Assignment assign) { var dist = assign.Dist; var indexes = assign.Indexes; var flatDist = dist.GetFlatData(); var distributionForZone = flatWorkplaceDistribution[z]; Random rand = new Random((RandomSeed * z) * (CurrentOccupationIndex * numberOfZones)); var zonePop = flatPopulation[z]; int popLength = zonePop.Length; if (indexes == null || indexes.Length < popLength) { indexes = new int[(int)(popLength * 1.5)]; assign.Indexes = indexes; } int totalPeopleInCat = 0; // 1+2) learn who is qualified for this distribution for (int i = 0; i < popLength; i++) { var person = zonePop[i]; if (category.IsContained(person)) { indexes[totalPeopleInCat] = i; totalPeopleInCat++; } } // 3) Count how many jobs are expected to come from this zone double totalJobsFromThisOrigin = 0; for (int i = 0; i < numberOfZones; i++) { totalJobsFromThisOrigin += (flatDist[i] = distributionForZone[i]); } if (totalJobsFromThisOrigin == 0) { return(assign); } // 4) Calculate the ratio of people who work to the number of jobs so we can balance it again float normalizationFactor = 1 / (float)totalJobsFromThisOrigin; for (int i = 0; i < numberOfZones; i++) { flatDist[i] = flatDist[i] * normalizationFactor; } // 5) card sort algo for (int i = totalPeopleInCat - 1; i > 0; i--) { var swapIndex = rand.Next(i); var temp = indexes[i]; indexes[i] = indexes[swapIndex]; indexes[swapIndex] = temp; } // 6) Apply the random split algorithm from the Population Synthesis to finish it off var flatResult = SplitAndClear(totalPeopleInCat, dist, rand); int offset = 0; for (int i = 0; i < numberOfZones; i++) { var ammount = flatResult[i]; for (int j = 0; j < ammount; j++) { if (offset + j >= indexes.Length || indexes[offset + j] > zonePop.Length) { throw new XTMFRuntimeException(this, "We tried to assign to a person that does not exist!"); } zonePop[indexes[offset + j]].WorkZone = flatZones[i]; } offset += ammount; } return(assign); }, delegate { }); }
private bool AreWeClosest(IZone origin, SparseArray<IZone> zoneArray, SparseTwinIndex<float> distances) { var ourDistance = distances[origin.ZoneNumber, this.InterchangeZone.ZoneNumber]; foreach ( var range in this.StationRanges ) { for ( int i = range.Start; i <= range.Stop; i++ ) { if ( i == this.StationZone ) continue; var otherZone = zoneArray[i]; if ( otherZone != null ) { if ( distances[origin.ZoneNumber, otherZone.ZoneNumber] < ourDistance ) return false; } } } return true; }
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 LoadInBaseData(SparseTwinIndex<float> ret, IReadODData<float> data) { foreach ( var point in data.Read() ) { ret[point.O, point.D] = point.Data; } }
private void TraditionalModeSplit(int numberOfCategories, List <TreeData <float[][]> > ret, IZone[] zones, int flows, SparseTwinIndex <float> flow) { try { int soFar = 0; Parallel.For(0, zones.Length, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, delegate { return(MirrorModeTree.CreateMirroredTree <float>(Root.Modes)); }, delegate(int o, ParallelLoopState unused, List <TreeData <float> > utility) { var flatFlows = flow.GetFlatData(); for (int d = 0; d < zones.Length; d++) { var odFlow = flatFlows[o][d]; if (odFlow > 0) { GatherUtility(utility, o, d, zones); ConvertToFlow(utility, odFlow); SaveResults(utility, ret, o, d, zones.Length); } } Progress = ((Interlocked.Increment(ref soFar) / (float)zones.Length) / numberOfCategories) + (flows / (float)numberOfCategories); return(utility); }, delegate { // do nothing }); } catch (AggregateException e) { throw new XTMFRuntimeException(this, e.InnerException?.Message + "\r\n" + e.InnerException?.StackTrace); } }