private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, IPersonDayWrapper personDay, DayPattern choice = null) { IHouseholdWrapper household = personDay.Household; IParcelWrapper residenceParcel = household.ResidenceParcel; IPersonWrapper person = personDay.Person; int carsPerDriver = household.GetCarsPerDriver(); double mixedDensity = residenceParcel.MixedUse3Index2(); double intersectionDensity = residenceParcel.IntersectionDensity34Minus1Buffer2(); double[] purposeLogsums = new double[Global.Settings.Purposes.TotalPurposes]; double[] atUsualLogsums = new double[3]; int carOwnership = person.GetCarOwnershipSegment(); int votSegment = person.Household.GetVotALSegment(); int transitAccess = residenceParcel.TransitAccessSegment(); if (person.UsualWorkParcel == null || person.UsualWorkParcelId == household.ResidenceParcelId) { purposeLogsums[Global.Settings.Purposes.Work] = 0; } else { int destinationArrivalTime = ChoiceModelUtility.GetDestinationArrivalTime(Global.Settings.Models.WorkTourModeModel); int destinationDepartureTime = ChoiceModelUtility.GetDestinationDepartureTime(Global.Settings.Models.WorkTourModeModel); ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <WorkTourModeModel>().RunNested(personDay, residenceParcel, person.UsualWorkParcel, destinationArrivalTime, destinationDepartureTime, household.VehiclesAvailable); purposeLogsums[Global.Settings.Purposes.Work] = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum(); atUsualLogsums[Global.Settings.Purposes.Work] = Global.AggregateLogsums[person.UsualWorkParcel.ZoneId][Global.Settings.Purposes.HomeBasedComposite][carOwnership][votSegment][person.UsualWorkParcel.TransitAccessSegment()]; } if (person.UsualSchoolParcel == null || person.UsualSchoolParcelId == household.ResidenceParcelId) { purposeLogsums[Global.Settings.Purposes.School] = 0; } else { int destinationArrivalTime = ChoiceModelUtility.GetDestinationArrivalTime(Global.Settings.Models.SchoolTourModeModel); int destinationDepartureTime = ChoiceModelUtility.GetDestinationDepartureTime(Global.Settings.Models.SchoolTourModeModel); ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <SchoolTourModeModel>().RunNested(personDay, residenceParcel, person.UsualSchoolParcel, destinationArrivalTime, destinationDepartureTime, household.VehiclesAvailable); purposeLogsums[Global.Settings.Purposes.School] = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum(); atUsualLogsums[Global.Settings.Purposes.School] = Global.AggregateLogsums[person.UsualSchoolParcel.ZoneId][Global.Settings.Purposes.HomeBasedComposite][carOwnership][votSegment][person.UsualSchoolParcel.TransitAccessSegment()]; } double compositeLogsum = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.HomeBasedComposite][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.Escort] = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.Escort][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.PersonalBusiness] = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.PersonalBusiness][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.Shopping] = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.Shopping][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.Meal] = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.Meal][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.Social] = Global.AggregateLogsums[household.ResidenceZoneId][Global.Settings.Purposes.Social][carOwnership][votSegment][transitAccess]; purposeLogsums[Global.Settings.Purposes.Recreation] = compositeLogsum; purposeLogsums[Global.Settings.Purposes.Medical] = compositeLogsum; for (int xPurpose = Global.Settings.Purposes.Work; xPurpose <= Global.Settings.Purposes.Social + 10; xPurpose++) { // extra components 1-5 are for 2,3,4,5,6 tour purposes // extra components 6-10 are for 2,3,4,5,6 stop puroposes // recode purpose to match coefficients int purpose = xPurpose <= Global.Settings.Purposes.Social ? xPurpose : xPurpose <= Global.Settings.Purposes.Social + 5 ? Global.Settings.Purposes.Social + 1 : Global.Settings.Purposes.Social + 2; // get correct multiplier on coefficients. double xMultiplier = xPurpose <= Global.Settings.Purposes.Social ? 1.0 : xPurpose <= Global.Settings.Purposes.Social + 5 ? Math.Log(xPurpose - Global.Settings.Purposes.Social + 1) : Math.Log(xPurpose - Global.Settings.Purposes.Social - 5 + 1); choiceProbabilityCalculator.CreateUtilityComponent(xPurpose); ChoiceProbabilityCalculator.Component component = choiceProbabilityCalculator.GetUtilityComponent(xPurpose); component.AddUtilityTerm(100 * purpose + 51, xMultiplier * person.IsFulltimeWorker.ToFlag()); component.AddUtilityTerm(100 * purpose + 2, xMultiplier * person.IsPartTimeWorker.ToFlag()); component.AddUtilityTerm(100 * purpose + 3, xMultiplier * person.IsRetiredAdult.ToFlag()); component.AddUtilityTerm(100 * purpose + 4, xMultiplier * person.IsNonworkingAdult.ToFlag()); component.AddUtilityTerm(100 * purpose + 5, xMultiplier * person.IsUniversityStudent.ToFlag()); component.AddUtilityTerm(100 * purpose + 6, xMultiplier * person.IsDrivingAgeStudent.ToFlag()); component.AddUtilityTerm(100 * purpose + 7, xMultiplier * person.IsChildAge5Through15.ToFlag()); component.AddUtilityTerm(100 * purpose + 8, xMultiplier * person.IsChildUnder5.ToFlag()); component.AddUtilityTerm(100 * purpose + 9, xMultiplier * household.Has0To25KIncome.ToFlag()); component.AddUtilityTerm(100 * purpose + 10, xMultiplier * household.Has25To45KIncome.ToFlag()); component.AddUtilityTerm(100 * purpose + 11, xMultiplier * household.Has75KPlusIncome.ToFlag()); component.AddUtilityTerm(100 * purpose + 12, xMultiplier * carsPerDriver); component.AddUtilityTerm(100 * purpose + 13, xMultiplier * person.IsOnlyAdult().ToFlag()); component.AddUtilityTerm(100 * purpose + 14, xMultiplier * person.IsOnlyFullOrPartTimeWorker().ToFlag()); component.AddUtilityTerm(100 * purpose + 15, xMultiplier * 0); component.AddUtilityTerm(100 * purpose + 16, xMultiplier * person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * (!household.HasChildrenUnder16).ToFlag()); component.AddUtilityTerm(100 * purpose + 17, xMultiplier * person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag()); component.AddUtilityTerm(100 * purpose + 18, xMultiplier * person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag()); component.AddUtilityTerm(100 * purpose + 19, xMultiplier * person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag()); component.AddUtilityTerm(100 * purpose + 20, xMultiplier * person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag()); component.AddUtilityTerm(100 * purpose + 21, xMultiplier * person.AgeIsBetween18And25.ToFlag()); component.AddUtilityTerm(100 * purpose + 22, xMultiplier * person.AgeIsBetween26And35.ToFlag()); component.AddUtilityTerm(100 * purpose + 23, xMultiplier * person.AgeIsBetween51And65.ToFlag()); component.AddUtilityTerm(100 * purpose + 24, xMultiplier * person.WorksAtHome().ToFlag()); component.AddUtilityTerm(100 * purpose + 25, xMultiplier * mixedDensity); component.AddUtilityTerm(100 * purpose + 26, xMultiplier * intersectionDensity); component.AddUtilityTerm(100 * purpose + 27, xMultiplier * purposeLogsums[purpose]); component.AddUtilityTerm(100 * purpose + 28, xMultiplier * person.TransitPassOwnership); } // tour utility int tourComponentIndex = Global.Settings.Purposes.Social + 11; choiceProbabilityCalculator.CreateUtilityComponent(tourComponentIndex); ChoiceProbabilityCalculator.Component tourComponent = choiceProbabilityCalculator.GetUtilityComponent(tourComponentIndex); tourComponent.AddUtilityTerm(1401, carsPerDriver); tourComponent.AddUtilityTerm(1402, person.WorksAtHome().ToFlag()); tourComponent.AddUtilityTerm(1403, mixedDensity); tourComponent.AddUtilityTerm(1404, mixedDensity * person.IsChildAge5Through15.ToFlag()); tourComponent.AddUtilityTerm(1405, compositeLogsum); tourComponent.AddUtilityTerm(1406, person.TransitPassOwnership); // stop utility int stopComponentIndex = Global.Settings.Purposes.Social + 12; choiceProbabilityCalculator.CreateUtilityComponent(stopComponentIndex); ChoiceProbabilityCalculator.Component stopComponent = choiceProbabilityCalculator.GetUtilityComponent(stopComponentIndex); stopComponent.AddUtilityTerm(1411, carsPerDriver); stopComponent.AddUtilityTerm(1412, person.WorksAtHome().ToFlag()); stopComponent.AddUtilityTerm(1413, mixedDensity); stopComponent.AddUtilityTerm(1414, mixedDensity * person.IsChildAge5Through15.ToFlag()); stopComponent.AddUtilityTerm(1415, compositeLogsum); stopComponent.AddUtilityTerm(1416, person.TransitPassOwnership); for (int alternativeIndex = 0; alternativeIndex < TOTAL_ALTERNATIVES; alternativeIndex++) { DayPattern dayPattern = _dayPatterns[alternativeIndex]; bool available = // work tours and stops only available for workers (person.IsWorker || (dayPattern.WorkTours <= 0 && dayPattern.WorkStops <= 0)) && // school tours and stops only available for students with usual school parcel not at home ((person.IsStudent && person.UsualSchoolParcel != null && person.UsualSchoolParcel != person.Household.ResidenceParcel) || (dayPattern.SchoolTours <= 0 && dayPattern.SchoolStops <= 0)) && // school stops not available if usual school parcel is same as usual work parcel ((person.IsStudent && person.UsualSchoolParcel != null && person.UsualSchoolParcel != person.UsualWorkParcel) || (dayPattern.SchoolStops <= 0)); ChoiceProbabilityCalculator.Alternative alternative = choiceProbabilityCalculator.GetAlternative(alternativeIndex, available, choice != null && choice.Equals(dayPattern)); if (!Global.Configuration.IsInEstimationMode && !alternative.Available) { continue; } alternative.Choice = dayPattern; // components for the purposes for (int purpose = Global.Settings.Purposes.Work; purpose <= Global.Settings.Purposes.Social; purpose++) { if (dayPattern.Tours[purpose] > 0 || dayPattern.Stops[purpose] > 0) { alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(purpose)); if (dayPattern.Tours[purpose] > 0) { alternative.AddUtilityTerm(100 * purpose, 1); // tour purpose ASC alternative.AddUtilityTerm(100 * purpose + 29, purposeLogsums[purpose]); // tour purpose logsum alternative.AddUtilityTerm(100 * purpose + 30, person.PaidParkingAtWorkplace); // only use for work purpose } if (dayPattern.Stops[purpose] > 0) { alternative.AddUtilityTerm(100 * purpose + 1, 1); // stop purpose ASC alternative.AddUtilityTerm(100 * purpose + 31, purposeLogsums[purpose]); // stop purpose logsum } if (Global.Configuration.IsInEstimationMode) { alternative.AddUtilityTerm(100 * purpose + 32, 1 - person.PaperDiary); alternative.AddUtilityTerm(100 * purpose + 33, person.ProxyResponse); } } } // multiple tour purposes component if (dayPattern.TotalTours > 1) { alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(Global.Settings.Purposes.Social + (dayPattern.TotalTours - 1))); } // multiple stop purposes component if (dayPattern.TotalStops > 1) { alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(Global.Settings.Purposes.Social + 5 + (dayPattern.TotalStops - 1))); } for (int tourPurpose = Global.Settings.Purposes.Work; tourPurpose <= Global.Settings.Purposes.Social; tourPurpose++) { for (int stopPurpose = Global.Settings.Purposes.Work; stopPurpose <= Global.Settings.Purposes.Social - 1; stopPurpose++) { if (tourPurpose > Global.Settings.Purposes.School && stopPurpose <= Global.Settings.Purposes.School) { continue; } if (dayPattern.Tours[tourPurpose] > 0 && dayPattern.Stops[stopPurpose] > 0) { alternative.AddUtilityTerm(1000 + 10 * tourPurpose + stopPurpose, 1); // tour-stop comb. utility } } } for (int tourPurpose = Global.Settings.Purposes.Work; tourPurpose <= Global.Settings.Purposes.School; tourPurpose++) { if (dayPattern.Tours[tourPurpose] == 1 && dayPattern.TotalStops >= 1) { alternative.AddUtilityTerm(1000 + 10 * tourPurpose, purposeLogsums[tourPurpose]); // usual location logsum x presence of stops in work or school pattern alternative.AddUtilityTerm(1000 + 10 * tourPurpose + 8, compositeLogsum); // home aggregate logsum x presence of stops in work or school pattern alternative.AddUtilityTerm(1000 + 10 * tourPurpose + 9, atUsualLogsums[tourPurpose]); // at usual location aggregate logsum x presence of stops in work or school pattern } } for (int tourPurpose = Global.Settings.Purposes.Work; tourPurpose <= Global.Settings.Purposes.Social - 2; tourPurpose++) { for (int tourPurpose2 = tourPurpose + 1; tourPurpose2 <= Global.Settings.Purposes.Social; tourPurpose2++) { if (dayPattern.Tours[tourPurpose] > 0 && dayPattern.Tours[tourPurpose2] > 0) { alternative.AddUtilityTerm(1100 + 10 * tourPurpose + tourPurpose2, 1); // tour-tour comb. utility } } } for (int stopPurpose = Global.Settings.Purposes.Work; stopPurpose <= Global.Settings.Purposes.Social - 2; stopPurpose++) { for (int stopPurpose2 = stopPurpose + 1; stopPurpose2 <= Global.Settings.Purposes.Social; stopPurpose2++) { if (dayPattern.Stops[stopPurpose] > 0 && dayPattern.Stops[stopPurpose2] > 0) { alternative.AddUtilityTerm(1200 + 10 * stopPurpose + stopPurpose2, 1); // stop-stop comb. utility } } } if (dayPattern.TotalTours > 0 && dayPattern.TotalStops > 0) { int totalStops = dayPattern.TotalStops; if (totalStops > 3) { totalStops = 3; } alternative.AddUtilityTerm(1300 + 10 * dayPattern.TotalTours + totalStops, 1); // nttour-ntstop utility } if (dayPattern.TotalTours - dayPattern.Tours[Global.Settings.Purposes.Work] - dayPattern.Tours[Global.Settings.Purposes.School] > 0) { // tour utility alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(tourComponentIndex)); } if (dayPattern.TotalStops - dayPattern.Stops[Global.Settings.Purposes.Work] - dayPattern.Stops[Global.Settings.Purposes.School] > 0) { // stop utility alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(stopComponentIndex)); } } }