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));
                }
            }
        }
Exemple #2
0
        private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, ITourWrapper tour, int nCallsForTour, int choice = Constants.DEFAULT_VALUE)
        {
            IPersonWrapper    person    = tour.Person;
            IPersonDayWrapper personDay = tour.PersonDay;

            //            var foodRetailServiceMedicalQtrMileLog = tour.DestinationParcel.FoodRetailServiceMedicalQtrMileLogBuffer1();
            //            var mixedUseIndex = tour.DestinationParcel.MixedUse4Index1();
            double k8HighSchoolQtrMileLog = tour.DestinationParcel.K8HighSchoolQtrMileLogBuffer1();
            int    carOwnership           = person.GetCarOwnershipSegment();

            int noCarsFlag         = FlagUtility.GetNoCarsFlag(carOwnership);
            int carCompetitionFlag = FlagUtility.GetCarCompetitionFlag(carOwnership);
            //            var notUsualWorkParcelFlag = tour.DestinationParcel.NotUsualWorkParcelFlag(person.UsualWorkParcelId);

            int votALSegment = tour.GetVotALSegment();

            int    workTaSegment       = tour.DestinationParcel.TransitAccessSegment();
            double workAggregateLogsum = Global.AggregateLogsums[tour.DestinationParcel.ZoneId]
                                         [Global.Settings.Purposes.WorkBased][carOwnership][votALSegment][workTaSegment];

            // NONE_OR_HOME

            ChoiceProbabilityCalculator.Alternative alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.NoneOrHome, true, choice == Global.Settings.Purposes.NoneOrHome);

            alternative.Choice = Global.Settings.Purposes.NoneOrHome;

            alternative.AddUtilityTerm(15, (nCallsForTour > 1).ToFlag());
            alternative.AddUtilityTerm(16, Math.Log(personDay.HomeBasedTours));
            alternative.AddUtilityTerm(18, personDay.TwoOrMoreWorkToursExist().ToFlag());
            //            alternative.AddUtility(19, notUsualWorkParcelFlag);
            alternative.AddUtilityTerm(22, noCarsFlag);
            alternative.AddUtilityTerm(23, carCompetitionFlag);
            alternative.AddUtilityTerm(32, workAggregateLogsum);
            //            alternative.AddUtility(32, mixedUseIndex);

            alternative.AddNestedAlternative(11, 0, 50);

            // WORK

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Work, personDay.WorkStops > 0, choice == Global.Settings.Purposes.Work);

            alternative.Choice = Global.Settings.Purposes.Work;

            alternative.AddUtilityTerm(1, 1);

            alternative.AddNestedAlternative(12, 1, 50);

            // SCHOOL

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.School, personDay.SchoolStops > 0, choice == Global.Settings.Purposes.School);

            alternative.Choice = Global.Settings.Purposes.School;

            alternative.AddUtilityTerm(3, 1);

            alternative.AddNestedAlternative(12, 1, 50);

            // ESCORT

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Escort, personDay.EscortStops > 0, choice == Global.Settings.Purposes.Escort);

            alternative.Choice = Global.Settings.Purposes.Escort;

            alternative.AddUtilityTerm(4, 1);
            alternative.AddUtilityTerm(39, k8HighSchoolQtrMileLog);

            alternative.AddNestedAlternative(12, 1, 50);

            // PERSONAL_BUSINESS

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.PersonalBusiness, personDay.PersonalBusinessStops > 0, choice == Global.Settings.Purposes.PersonalBusiness);

            alternative.Choice = Global.Settings.Purposes.PersonalBusiness;

            alternative.AddUtilityTerm(6, 1);

            alternative.AddNestedAlternative(12, 1, 50);

            // SHOPPING

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Shopping, personDay.ShoppingStops > 0, choice == Global.Settings.Purposes.Shopping);

            alternative.Choice = Global.Settings.Purposes.Shopping;

            alternative.AddUtilityTerm(8, 1);

            alternative.AddNestedAlternative(12, 1, 50);

            // MEAL

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Meal, personDay.MealStops > 0, choice == Global.Settings.Purposes.Meal);

            alternative.Choice = Global.Settings.Purposes.Meal;

            alternative.AddUtilityTerm(10, 1);

            alternative.AddNestedAlternative(12, 1, 50);

            // SOCIAL

            alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Social, personDay.SocialStops > 0, choice == Global.Settings.Purposes.Social);

            alternative.Choice = Global.Settings.Purposes.Social;

            alternative.AddUtilityTerm(13, 1);

            alternative.AddNestedAlternative(12, 1, 50);
        }
Exemple #3
0
        private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, IPersonDayWrapper personDay, int purpose, int choice = Constants.DEFAULT_VALUE)
        {
            IHouseholdWrapper household       = personDay.Household;
            IParcelWrapper    residenceParcel = household.ResidenceParcel;
            IPersonWrapper    person          = personDay.Person;

            int    carsPerDriver       = household.GetCarsPerDriver();
            double mixedDensity        = residenceParcel.ParcelHouseholdsPerRetailServiceFoodEmploymentBuffer2();
            double intersectionDensity = residenceParcel.IntersectionDensity34Minus1Buffer2();

            double purposeLogsum;

            if (purpose == Global.Settings.Purposes.Work)
            {
                if (person.UsualWorkParcel == null || person.UsualWorkParcelId == household.ResidenceParcelId)
                {
                    purposeLogsum = 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);

                    purposeLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }
            }
            else if (purpose == Global.Settings.Purposes.School)
            {
                if (person.UsualSchoolParcel == null || person.UsualSchoolParcelId == household.ResidenceParcelId)
                {
                    purposeLogsum = 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);

                    purposeLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }
            }
            else
            {
                int carOwnership  = person.GetCarOwnershipSegment();
                int votSegment    = person.Household.GetVotALSegment();
                int transitAccess = residenceParcel.TransitAccessSegment();

                purposeLogsum = Global.AggregateLogsums[household.ResidenceZoneId][purpose][carOwnership][votSegment][transitAccess];
            }

            // 1 TOUR

            ChoiceProbabilityCalculator.Alternative alternative = choiceProbabilityCalculator.GetAlternative(0, true, choice == 1);

            alternative.Choice = 1;

            alternative.AddUtilityTerm(1, purpose);

            // 2 TOURS

            alternative = choiceProbabilityCalculator.GetAlternative(1, true, choice == 2);

            const int two = 2;

            alternative.Choice = two;

            alternative.AddUtilityTerm(100 * purpose + 1, person.IsFulltimeWorker.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 2, person.IsPartTimeWorker.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 3, person.IsRetiredAdult.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 4, person.IsNonworkingAdult.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 5, person.IsUniversityStudent.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 6, person.IsDrivingAgeStudent.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 7, person.IsChildAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 8, person.IsChildUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 9, household.Has0To25KIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 10, household.Has25To45KIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 11, household.Has75KPlusIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 12, carsPerDriver);
            alternative.AddUtilityTerm(100 * purpose + 13, person.IsOnlyAdult().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 14, person.IsOnlyFullOrPartTimeWorker().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 15, 0);
            alternative.AddUtilityTerm(100 * purpose + 16, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * (!household.HasChildrenUnder16).ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 17, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 18, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 19, person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 20, person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 21, person.AgeIsBetween18And25.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 22, person.AgeIsBetween26And35.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 23, person.AgeIsBetween51And65.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 24, person.WorksAtHome().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 25, mixedDensity);
            alternative.AddUtilityTerm(100 * purpose + 26, intersectionDensity);
            alternative.AddUtilityTerm(100 * purpose + 31, personDay.WorkTours);
            alternative.AddUtilityTerm(100 * purpose + 32, personDay.SchoolTours);
            alternative.AddUtilityTerm(100 * purpose + 33, personDay.EscortTours);
            alternative.AddUtilityTerm(100 * purpose + 34, personDay.PersonalBusinessTours);
            alternative.AddUtilityTerm(100 * purpose + 35, personDay.ShoppingTours);
            alternative.AddUtilityTerm(100 * purpose + 36, personDay.MealTours);
            alternative.AddUtilityTerm(100 * purpose + 37, personDay.SocialTours);
            alternative.AddUtilityTerm(100 * purpose + 41, personDay.WorkStops);

            if (purpose <= Global.Settings.Purposes.Escort)
            {
                alternative.AddUtilityTerm(100 * purpose + 42, personDay.SchoolStops);
            }

            alternative.AddUtilityTerm(100 * purpose + 43, personDay.EscortStops);
            alternative.AddUtilityTerm(100 * purpose + 44, personDay.PersonalBusinessStops);
            alternative.AddUtilityTerm(100 * purpose + 45, personDay.ShoppingStops);
            alternative.AddUtilityTerm(100 * purpose + 46, personDay.MealStops);
            alternative.AddUtilityTerm(100 * purpose + 47, personDay.SocialStops);
            alternative.AddUtilityTerm(100 * purpose + 50 + two, 1);                 // ASC
            alternative.AddUtilityTerm(100 * purpose + 23 + 2 * two, purposeLogsum); // accessibility effect has different coefficient for 2 and 3+

            // 3+ TOURS

            alternative = choiceProbabilityCalculator.GetAlternative(2, true, choice == 3);

            const int three = 3;

            alternative.Choice = three;

            alternative.AddUtilityTerm(100 * purpose + 1, person.IsFulltimeWorker.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 2, person.IsPartTimeWorker.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 3, person.IsRetiredAdult.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 4, person.IsNonworkingAdult.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 5, person.IsUniversityStudent.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 6, person.IsDrivingAgeStudent.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 7, person.IsChildAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 8, person.IsChildUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 9, household.Has0To25KIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 10, household.Has25To45KIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 11, household.Has75KPlusIncome.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 12, carsPerDriver);
            alternative.AddUtilityTerm(100 * purpose + 13, person.IsOnlyAdult().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 14, person.IsOnlyFullOrPartTimeWorker().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 15, 0);
            alternative.AddUtilityTerm(100 * purpose + 16, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * (!household.HasChildrenUnder16).ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 17, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 18, person.IsFemale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 19, person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenUnder5.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 20, person.IsMale.ToFlag() * person.IsAdult.ToFlag() * household.HasChildrenAge5Through15.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 21, person.AgeIsBetween18And25.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 22, person.AgeIsBetween26And35.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 23, person.AgeIsBetween51And65.ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 24, person.WorksAtHome().ToFlag());
            alternative.AddUtilityTerm(100 * purpose + 25, mixedDensity);
            alternative.AddUtilityTerm(100 * purpose + 26, intersectionDensity);
            alternative.AddUtilityTerm(100 * purpose + 31, personDay.WorkTours);
            alternative.AddUtilityTerm(100 * purpose + 32, personDay.SchoolTours);
            alternative.AddUtilityTerm(100 * purpose + 33, personDay.EscortTours);
            alternative.AddUtilityTerm(100 * purpose + 34, personDay.PersonalBusinessTours);
            alternative.AddUtilityTerm(100 * purpose + 35, personDay.ShoppingTours);
            alternative.AddUtilityTerm(100 * purpose + 36, personDay.MealTours);
            alternative.AddUtilityTerm(100 * purpose + 37, personDay.SocialTours);
            alternative.AddUtilityTerm(100 * purpose + 41, personDay.WorkStops);

            if (purpose <= Global.Settings.Purposes.Escort)
            {
                alternative.AddUtilityTerm(100 * purpose + 42, personDay.SchoolStops);
            }

            alternative.AddUtilityTerm(100 * purpose + 43, personDay.EscortStops);
            alternative.AddUtilityTerm(100 * purpose + 44, personDay.PersonalBusinessStops);
            alternative.AddUtilityTerm(100 * purpose + 45, personDay.ShoppingStops);
            alternative.AddUtilityTerm(100 * purpose + 46, personDay.MealStops);
            alternative.AddUtilityTerm(100 * purpose + 47, personDay.SocialStops);
            alternative.AddUtilityTerm(100 * purpose + 50 + three, 1);                 // ASC
            alternative.AddUtilityTerm(100 * purpose + 23 + 2 * three, purposeLogsum); // accessibility effect has different coefficient for 2 and 3+
        }
        private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, ITripWrapper trip, IHouseholdDayWrapper householdDay, int choice = Constants.DEFAULT_VALUE)
        {
            IHouseholdWrapper household = trip.Household;
            IPersonWrapper    person    = trip.Person;
            IPersonDayWrapper personDay = trip.PersonDay;
            ITourWrapper      tour      = trip.Tour;

            Framework.DomainModels.Models.IHalfTour halfTour = trip.HalfTour;
            List <IPersonDayWrapper> personDays = householdDay.PersonDays;

            int            isJointTour       = tour.JointTourSequence > 0 ? 1 : 0;
            IParcelWrapper destinationParcel = tour.DestinationParcel;
            int            fullJointHalfTour = ((trip.Direction == Global.Settings.TourDirections.OriginToDestination && tour.FullHalfTour1Sequence > 0) ||
                                                (trip.Direction == Global.Settings.TourDirections.DestinationToOrigin && tour.FullHalfTour2Sequence > 0)).ToFlag();
            int partialJointHalfTour = ((trip.Direction == Global.Settings.TourDirections.OriginToDestination && tour.PartialHalfTour1Sequence > 0) ||
                                        (trip.Direction == Global.Settings.TourDirections.DestinationToOrigin && tour.PartialHalfTour2Sequence > 0)).ToFlag();
            int isJoint      = (isJointTour + fullJointHalfTour + partialJointHalfTour > 0) ? 1 : 0;
            int isIndividual = 1 - isJoint;

            //destination parcel variables
            double foodBuffer2   = 0.0;
            double totEmpBuffer2 = 0.0;
            double retailBuffer2 = 0.0;

            if (destinationParcel != null)
            {
                foodBuffer2   = Math.Log(1 + destinationParcel.EmploymentFoodBuffer2);
                totEmpBuffer2 = Math.Log(1 + destinationParcel.EmploymentTotalBuffer2);
                retailBuffer2 = Math.Log(1 + destinationParcel.EmploymentRetailBuffer2);
            }

            int carOwnership = person.GetCarOwnershipSegment();

            // household inputs
            int onePersonHouseholdFlag = household.IsOnePersonHousehold.ToFlag();
            //var householdInc75KP = household.Has75KPlusIncome;

            int votALSegment         = tour.GetVotALSegment();
            int transitAccessSegment = household.ResidenceParcel.TransitAccessSegment();

            double totalAggregateLogsum = Global.AggregateLogsums[household.ResidenceParcel.ZoneId]
                                          [Global.Settings.Purposes.HomeBasedComposite][carOwnership][votALSegment][transitAccessSegment];

            double homeFoodBuffer2   = Math.Log(1 + household.ResidenceParcel.EmploymentFoodBuffer2);
            double homeTotEmpBuffer2 = Math.Log(1 + household.ResidenceParcel.EmploymentTotalBuffer2);
            double homeRetailBuffer2 = Math.Log(1 + household.ResidenceParcel.EmploymentRetailBuffer2);

            // person-day inputs
            int homeBasedTours                 = personDay.HomeBasedTours;
            int simulatedToursFlag             = personDay.SimulatedToursExist().ToFlag();
            int simulatedWorkStops             = personDay.SimulatedWorkStops;
            int simulatedWorkStopsFlag         = personDay.SimulatedWorkStopsExist().ToFlag();
            int simulatedSchoolStops           = personDay.SimulatedSchoolStops;
            int simulatedEscortStops           = personDay.SimulatedEscortStops;
            int simulatedPersonalBusinessStops = personDay.SimulatedPersonalBusinessStops;
            int simulatedShoppingStops         = personDay.SimulatedShoppingStops;
            int simulatedMealStops             = personDay.SimulatedMealStops;
            int simulatedSocialStops           = personDay.SimulatedSocialStops;
            int simulatedRecreationStops       = personDay.SimulatedRecreationStops;
            int simulatedMedicalStops          = personDay.SimulatedMedicalStops;

            // tour inputs
            int hov2TourFlag         = tour.IsHov2Mode().ToFlag();
            int hov3TourFlag         = tour.IsHov3Mode().ToFlag();
            int transitTourFlag      = tour.IsTransitMode().ToFlag();
            int notHomeBasedTourFlag = (!tour.IsHomeBasedTour).ToFlag();
            int workTourFlag         = tour.IsWorkPurpose().ToFlag();
            int personalBusinessOrMedicalTourFlag = tour.IsPersonalBusinessOrMedicalPurpose().ToFlag();
            int socialTourFlag             = tour.IsSocialPurpose().ToFlag();
            int socialOrRecreationTourFlag = tour.IsSocialOrRecreationPurpose().ToFlag();
            int schoolTourFlag             = tour.IsSchoolPurpose().ToFlag();
            int escortTourFlag             = tour.IsEscortPurpose().ToFlag();
            int shoppingTourFlag           = tour.IsShoppingPurpose().ToFlag();
            int mealTourFlag = tour.IsMealPurpose().ToFlag();

            // trip inputs
            int oneSimulatedTripFlag           = halfTour.OneSimulatedTripFlag;
            int twoSimulatedTripsFlag          = halfTour.TwoSimulatedTripsFlag;
            int threeSimulatedTripsFlag        = halfTour.ThreeSimulatedTripsFlag;
            int fourSimulatedTripsFlag         = halfTour.FourSimulatedTripsFlag;
            int fivePlusSimulatedTripsFlag     = halfTour.FivePlusSimulatedTripsFlag; //JLB changed 5 to 5Plus
            int halfTourFromOriginFlag         = trip.IsHalfTourFromOrigin.ToFlag();
            int halfTourFromDestinationFlag    = (!trip.IsHalfTourFromOrigin).ToFlag();
            int beforeMandatoryDestinationFlag = trip.IsBeforeMandatoryDestination().ToFlag();

            // remaining inputs, including joint tour variables
            int time = trip.IsHalfTourFromOrigin ? tour.DestinationArrivalTime : tour.DestinationDepartureTime;

            int from7AMto9AMFlag  = (time >= Global.Settings.Times.SevenAM && time < Global.Settings.Times.NineAM).ToFlag();
            int from9AMto11AMFlag = (time >= Global.Settings.Times.NineAM && time < Global.Settings.Times.ElevenAM).ToFlag();
            int from11AMto1PMFlag = (time >= Global.Settings.Times.ElevenAM && time < Global.Settings.Times.OnePM).ToFlag();
            int from1PMto3PMFlag  = (time >= Global.Settings.Times.OnePM && time < Global.Settings.Times.ThreePM).ToFlag();
            int from3PMto5PMFlag  = (time >= Global.Settings.Times.ThreePM && time < Global.Settings.Times.FivePM).ToFlag();
            int from7PMto9PMFlag  = (time >= Global.Settings.Times.SevenPM && time < Global.Settings.Times.NinePM).ToFlag();
            int from9PMto11PMFlag = (time >= Global.Settings.Times.NinePM && time < Global.Settings.Times.ElevenPM).ToFlag();
            int from11PMto7AMFlag = (time >= Global.Settings.Times.ElevenPM).ToFlag();

            int remainingToursCount = personDay.HomeBasedTours - personDay.GetTotalSimulatedTours();

            // connectivity attributes
            double c34Ratio = trip.OriginParcel.C34RatioBuffer1();

            double adis    = 0.0;
            double logDist = 0.0;
            int    minute  = DayPeriod.BigDayPeriods[DayPeriod.MIDDAY].Start;

            //distance from origin to destination
            if (tour.OriginParcel != null && tour.DestinationParcel != null)
            {
                if (trip.Direction == Global.Settings.TourDirections.OriginToDestination)
                {
                    adis = ImpedanceRoster.GetValue("distance", Global.Settings.Modes.Sov, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, minute, tour.OriginParcel, tour.DestinationParcel).Variable;
                }
                else
                {
                    adis = ImpedanceRoster.GetValue("distance", Global.Settings.Modes.Sov, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, minute, destinationParcel, tour.OriginParcel).Variable;
                }
                logDist = Math.Log(1 + adis);
            }

            double shortestTravelTime = 0D;

            if (trip.Sequence > 1 && tour.OriginParcel != null && trip.OriginParcel != null)
            {
                if (trip.Direction == Global.Settings.TourDirections.OriginToDestination)
                {
                    shortestTravelTime = ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov2, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, minute, tour.OriginParcel, trip.OriginParcel).Variable;
                }
                else
                {
                    shortestTravelTime = ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov2, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, minute, trip.OriginParcel, tour.OriginParcel).Variable;
                }
            }

            double windowDuration = Math.Max(1.0,
                                             trip.IsHalfTourFromOrigin // first trip in half tour, use tour destination time
                    ? trip.Sequence == 1
                          ? tour.DestinationArrivalTime - tour.EarliestOriginDepartureTime - tour.IndicatedTravelTimeToDestination
                          : trip.GetPreviousTrip().ArrivalTime - tour.EarliestOriginDepartureTime - shortestTravelTime
                    : trip.Sequence == 1
                          ? tour.LatestOriginArrivalTime - tour.DestinationDepartureTime - tour.IndicatedTravelTimeFromDestination
                          : tour.LatestOriginArrivalTime - trip.GetPreviousTrip().ArrivalTime - shortestTravelTime);

            double duration = windowDuration / 60D;

            IEnumerable <PersonDayWrapper> orderedPersonDays = householdDay.PersonDays.OrderBy(p => p.GetJointTourParticipationPriority()).ToList().Cast <PersonDayWrapper>();
            int numChildrenOnJointTour = 0;
            int numAdultsOnJointTour   = 0;
            int totHHToursJT           = 0;

            //int totHHStopsJT=0;

            //MB use calculated variables at tour level rather than redoing time window
            //TimeWindow timeWindow = new TimeWindow();
            if (tour.JointTourSequence > 0)
            {
                foreach (PersonDayWrapper pDay in householdDay.PersonDays)
                {
                    ITourWrapper tInJoint = pDay.Tours.Find(t => t.JointTourSequence == tour.JointTourSequence);
                    if (!(tInJoint == null))
                    {
                        // set jointTour time window
                        //timeWindow.IncorporateAnotherTimeWindow(tInJoint.PersonDay.TimeWindow);
                        totHHToursJT = personDay.HomeBasedTours + totHHToursJT;

                        if (pDay.Person.Age < 18)
                        {
                            numChildrenOnJointTour++;
                        }

                        if (pDay.Person.Age >= 18)
                        {
                            numAdultsOnJointTour++;
                        }
                    }
                }
            }
            else if (trip.Direction == Global.Settings.TourDirections.OriginToDestination && tour.FullHalfTour1Sequence > 0)
            {
                foreach (PersonDayWrapper pDay in householdDay.PersonDays)
                {
                    ITourWrapper tInJoint = pDay.Tours.Find(t => t.FullHalfTour1Sequence == tour.FullHalfTour1Sequence);
                    if (!(tInJoint == null))
                    {
                        // set jointTour time window
                        //timeWindow.IncorporateAnotherTimeWindow(tInJoint.PersonDay.TimeWindow);
                        totHHToursJT = personDay.HomeBasedTours + totHHToursJT;

                        if (pDay.Person.Age < 18)
                        {
                            numChildrenOnJointTour++;
                        }

                        if (pDay.Person.Age >= 18)
                        {
                            numAdultsOnJointTour++;
                        }
                    }
                }
            }
            else if (trip.Direction == Global.Settings.TourDirections.DestinationToOrigin && tour.FullHalfTour2Sequence > 0)
            {
                foreach (PersonDayWrapper pDay in householdDay.PersonDays)
                {
                    ITourWrapper tInJoint = pDay.Tours.Find(t => t.FullHalfTour2Sequence == tour.FullHalfTour2Sequence);
                    if (!(tInJoint == null))
                    {
                        // set jointTour time window
                        //timeWindow.IncorporateAnotherTimeWindow(tInJoint.PersonDay.TimeWindow);
                        totHHToursJT = personDay.HomeBasedTours + totHHToursJT;

                        if (pDay.Person.Age < 18)
                        {
                            numChildrenOnJointTour++;
                        }

                        if (pDay.Person.Age >= 18)
                        {
                            numAdultsOnJointTour++;
                        }
                    }
                }
            }
            else if (tour.ParentTour == null)
            {
                //timeWindow.IncorporateAnotherTimeWindow(personDay.TimeWindow);
            }
            else
            {
                //timeWindow.IncorporateAnotherTimeWindow(tour.ParentTour.TimeWindow);
            }

            //timeWindow.SetBusyMinutes(Global.Settings.Times.EndOfRelevantWindow, Global.Settings.Times.MinutesInADay + 1);

            // time window in minutes for yet unmodeled portion of halftour, only consider persons on this trip
            //var availableWindow = timeWindow.AvailableWindow(destinationDepartureTime, Global.Settings.TimeDirections.Both);

            //var duration = availableWindow/ 60D;


            // 0 - NO MORE STOPS

            ChoiceProbabilityCalculator.Alternative alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.NoneOrHome, true, choice == Global.Settings.Purposes.NoneOrHome);

            alternative.Choice = Global.Settings.Purposes.NoneOrHome;

            alternative.AddUtilityTerm(1, twoSimulatedTripsFlag * halfTourFromOriginFlag * isIndividual);
            alternative.AddUtilityTerm(2, threeSimulatedTripsFlag * halfTourFromOriginFlag * isIndividual);
            alternative.AddUtilityTerm(3, fourSimulatedTripsFlag * halfTourFromOriginFlag * isIndividual);
            alternative.AddUtilityTerm(4, fivePlusSimulatedTripsFlag * halfTourFromOriginFlag * isIndividual);
            alternative.AddUtilityTerm(5, twoSimulatedTripsFlag * halfTourFromDestinationFlag * isIndividual);
            alternative.AddUtilityTerm(6, threeSimulatedTripsFlag * halfTourFromDestinationFlag * isIndividual);
            alternative.AddUtilityTerm(7, fourSimulatedTripsFlag * halfTourFromDestinationFlag * isIndividual);
            alternative.AddUtilityTerm(8, fivePlusSimulatedTripsFlag * halfTourFromDestinationFlag * isIndividual);
            alternative.AddUtilityTerm(9, homeBasedTours * isIndividual);
            alternative.AddUtilityTerm(10, homeBasedTours * isJointTour);
            alternative.AddUtilityTerm(11, notHomeBasedTourFlag);
            //alternative.AddUtilityTerm(12, beforeMandatoryDestinationFlag*isJointTour);
            alternative.AddUtilityTerm(13, beforeMandatoryDestinationFlag);
            alternative.AddUtilityTerm(14, numAdultsOnJointTour);
            alternative.AddUtilityTerm(15, numChildrenOnJointTour);
            alternative.AddUtilityTerm(16, totHHToursJT);
            //alternative.AddUtilityTerm(17, totHHStopsJT);
            alternative.AddUtilityTerm(22, (threeSimulatedTripsFlag + fourSimulatedTripsFlag + fivePlusSimulatedTripsFlag) * halfTourFromOriginFlag * isJoint);
            alternative.AddUtilityTerm(26, threeSimulatedTripsFlag * halfTourFromDestinationFlag * isJoint);
            alternative.AddUtilityTerm(27, fourSimulatedTripsFlag * halfTourFromDestinationFlag * isJoint);
            alternative.AddUtilityTerm(28, fivePlusSimulatedTripsFlag * halfTourFromDestinationFlag * isJoint);
            alternative.AddUtilityTerm(29, totalAggregateLogsum);

            // 1 - WORK STOP

            if ((personDay.WorkStops > 0 && tour.DestinationPurpose <= Global.Settings.Purposes.School) || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Work, true, choice == Global.Settings.Purposes.Work);

                alternative.Choice = Global.Settings.Purposes.Work;

                //alternative.AddUtilityTerm(32, isIndividualTour);
                alternative.AddUtilityTerm(33, workTourFlag);
                alternative.AddUtilityTerm(34, schoolTourFlag);
                alternative.AddUtilityTerm(35, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(36, Math.Log(1 + simulatedWorkStops));
                alternative.AddUtilityTerm(37, simulatedWorkStopsFlag);
                alternative.AddUtilityTerm(38, (5 - simulatedWorkStops));
                alternative.AddUtilityTerm(39, duration);
                alternative.AddUtilityTerm(40, from9AMto11AMFlag + from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag);
                //alternative.AddUtilityTerm(42, logDist);
                //alternative.AddUtilityTerm(43, transitTourFlag);
                //alternative.AddUtilityTerm(44, (person.IsPartTimeWorker).ToFlag());
                alternative.AddUtilityTerm(46, totalAggregateLogsum);
                //alternative.AddUtilityTerm(47,totEmpBuffer2);
                alternative.AddUtilityTerm(48, hov2TourFlag + hov3TourFlag);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Work, false, choice == Global.Settings.Purposes.Work);
            }

            // 2 - SCHOOL STOP

            if ((personDay.SchoolStops > 0 && tour.DestinationPurpose <= Global.Settings.Purposes.School) || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.School, true, choice == Global.Settings.Purposes.School);

                alternative.Choice = Global.Settings.Purposes.School;

                alternative.AddUtilityTerm(51, workTourFlag);
                alternative.AddUtilityTerm(52, schoolTourFlag);
                //alternative.AddUtilityTerm(53, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(54, Math.Log(1 + simulatedSchoolStops));
                alternative.AddUtilityTerm(55, (3 - simulatedSchoolStops));
                //alternative.AddUtilityTerm(55, remainingToursCount);
                alternative.AddUtilityTerm(56, duration);
                alternative.AddUtilityTerm(57, from7AMto9AMFlag + from7PMto9PMFlag + from9PMto11PMFlag + from11PMto7AMFlag);
                alternative.AddUtilityTerm(58, oneSimulatedTripFlag);
                //alternative.AddUtilityTerm(59, logDist);
                alternative.AddUtilityTerm(61, fullJointHalfTour * numChildrenOnJointTour);
                alternative.AddUtilityTerm(65, (person.Age < 12).ToFlag());
                alternative.AddUtilityTerm(66, totalAggregateLogsum);
                //alternative.AddUtilityTerm(66,  (person.IsUniversityStudent).ToFlag());
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.School, false, choice == Global.Settings.Purposes.School);
            }

            // 3 - ESCORT STOP

            if ((personDay.EscortStops > 0 && tour.DestinationPurpose <= Global.Settings.Purposes.Escort) || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Escort, true, choice == Global.Settings.Purposes.Escort);

                alternative.Choice = Global.Settings.Purposes.Escort;

                alternative.AddUtilityTerm(71, workTourFlag + schoolTourFlag);
                alternative.AddUtilityTerm(72, isJointTour);
                alternative.AddUtilityTerm(74, escortTourFlag);
                //alternative.AddUtilityTerm(75, socialOrRecreationTourFlag);
                //alternative.AddUtilityTerm(76, remainingToursCount);
                alternative.AddUtilityTerm(77, duration);
                alternative.AddUtilityTerm(78, from7AMto9AMFlag);
                //alternative.AddUtilityTerm(79, from9AMto11AMFlag + from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag);
                alternative.AddUtilityTerm(81, hov2TourFlag);
                alternative.AddUtilityTerm(82, hov3TourFlag);
                alternative.AddUtilityTerm(83, Math.Log(1 + simulatedEscortStops * isJointTour));
                alternative.AddUtilityTerm(84, Math.Log(1 + simulatedEscortStops * isIndividual));
                //alternative.AddUtilityTerm(85, (3 - simulatedEscortStops));

                alternative.AddUtilityTerm(85, totalAggregateLogsum);
                alternative.AddUtilityTerm(86, fullJointHalfTour);
                //alternative.AddUtilityTerm(88, enrollmentK8Buffer2);
                alternative.AddUtilityTerm(89, numChildrenOnJointTour);
                alternative.AddUtilityTerm(90, halfTourFromOriginFlag);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Escort, false, choice == Global.Settings.Purposes.Escort);
            }

            // 4 - PERSONAL BUSINESS STOP

            if (personDay.PersonalBusinessStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.PersonalBusiness, true, choice == Global.Settings.Purposes.PersonalBusiness);

                alternative.Choice = Global.Settings.Purposes.PersonalBusiness;

                alternative.AddUtilityTerm(91, (workTourFlag + schoolTourFlag));
                alternative.AddUtilityTerm(92, isJointTour);
                alternative.AddUtilityTerm(93, escortTourFlag);
                alternative.AddUtilityTerm(94, personalBusinessOrMedicalTourFlag * isIndividual);
                alternative.AddUtilityTerm(95, shoppingTourFlag);
                alternative.AddUtilityTerm(96, mealTourFlag);
                alternative.AddUtilityTerm(97, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(98, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(99, Math.Log(1 + simulatedPersonalBusinessStops * isIndividual));
                alternative.AddUtilityTerm(100, Math.Log(1 + simulatedPersonalBusinessStops * isJointTour));
                alternative.AddUtilityTerm(104, (3 - simulatedPersonalBusinessStops));
                alternative.AddUtilityTerm(101, duration);
                alternative.AddUtilityTerm(102, (from7AMto9AMFlag + from7PMto9PMFlag + from9PMto11PMFlag + from11PMto7AMFlag));
                alternative.AddUtilityTerm(103, from9AMto11AMFlag + from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag);
                alternative.AddUtilityTerm(105, hov2TourFlag);
                alternative.AddUtilityTerm(106, hov3TourFlag);
                alternative.AddUtilityTerm(109, fullJointHalfTour);
                alternative.AddUtilityTerm(110, totEmpBuffer2);
                alternative.AddUtilityTerm(111, totalAggregateLogsum);
                alternative.AddUtilityTerm(112, personalBusinessOrMedicalTourFlag * isJointTour);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.PersonalBusiness, false, choice == Global.Settings.Purposes.PersonalBusiness);
            }

            // 5 - SHOPPING STOP

            if (personDay.ShoppingStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Shopping, true, choice == Global.Settings.Purposes.Shopping);

                alternative.Choice = Global.Settings.Purposes.Shopping;

                alternative.AddUtilityTerm(121, workTourFlag + schoolTourFlag);
                alternative.AddUtilityTerm(122, isJointTour);
                alternative.AddUtilityTerm(123, escortTourFlag);
                alternative.AddUtilityTerm(124, personalBusinessOrMedicalTourFlag);
                alternative.AddUtilityTerm(125, shoppingTourFlag * isIndividual);
                alternative.AddUtilityTerm(126, mealTourFlag);
                alternative.AddUtilityTerm(127, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(128, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(129, Math.Log(1 + simulatedShoppingStops * isIndividual));
                alternative.AddUtilityTerm(130, Math.Log(1 + simulatedShoppingStops * isJointTour));
                alternative.AddUtilityTerm(131, duration);
                alternative.AddUtilityTerm(132, from7AMto9AMFlag + from9PMto11PMFlag + from11PMto7AMFlag);
                alternative.AddUtilityTerm(133, (from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag));
                //alternative.AddUtilityTerm(134, adultFemaleOnJointTour);
                alternative.AddUtilityTerm(135, hov2TourFlag);
                alternative.AddUtilityTerm(136, hov3TourFlag);
                alternative.AddUtilityTerm(137, Math.Log(1 + adis));
                alternative.AddUtilityTerm(138, shoppingTourFlag * isJointTour);
                alternative.AddUtilityTerm(140, totalAggregateLogsum);
                //alternative.AddUtilityTerm(141, retailBuffer2);
                //alternative.AddUtilityTerm(142, numChildrenOnJointTour);
                //alternative.AddUtilityTerm(143, (household.Has100KPlusIncome).ToFlag());
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Shopping, false, choice == Global.Settings.Purposes.Shopping);
            }

            // 6 - MEAL STOP

            if (personDay.MealStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Meal, true, choice == Global.Settings.Purposes.Meal);

                alternative.Choice = Global.Settings.Purposes.Meal;

                alternative.AddUtilityTerm(151, workTourFlag);
                //alternative.AddUtilityTerm(152, isJointTour);
                alternative.AddUtilityTerm(153, schoolTourFlag);
                alternative.AddUtilityTerm(154, escortTourFlag);
                alternative.AddUtilityTerm(155, personalBusinessOrMedicalTourFlag);
                alternative.AddUtilityTerm(156, shoppingTourFlag);
                alternative.AddUtilityTerm(157, mealTourFlag);
                alternative.AddUtilityTerm(158, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(159, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(160, Math.Log(1 + simulatedMealStops * isIndividual));
                alternative.AddUtilityTerm(161, Math.Log(1 + simulatedMealStops * isJointTour));
                alternative.AddUtilityTerm(162, duration);
                alternative.AddUtilityTerm(164, from11AMto1PMFlag + from1PMto3PMFlag);
                alternative.AddUtilityTerm(166, onePersonHouseholdFlag);
                alternative.AddUtilityTerm(167, hov2TourFlag);
                alternative.AddUtilityTerm(168, hov3TourFlag);
                alternative.AddUtilityTerm(170, numChildrenOnJointTour);
                alternative.AddUtilityTerm(171, oneSimulatedTripFlag);
                alternative.AddUtilityTerm(172, Math.Log(1 + adis));
                alternative.AddUtilityTerm(174, fullJointHalfTour);
                alternative.AddUtilityTerm(175, foodBuffer2);
                //alternative.AddUtilityTerm(176, homeFoodBuffer2);
                //alternative.AddUtilityTerm(177, (household.Has100KPlusIncome).ToFlag());
                alternative.AddUtilityTerm(178, numAdultsOnJointTour);
                alternative.AddUtilityTerm(179, totalAggregateLogsum);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Meal, false, choice == Global.Settings.Purposes.Meal);
            }

            // 7 - SOCIAL STOP

            if (personDay.SocialStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Social, true, choice == Global.Settings.Purposes.Social);

                alternative.Choice = Global.Settings.Purposes.Social;

                alternative.AddUtilityTerm(181, workTourFlag + schoolTourFlag);
                alternative.AddUtilityTerm(182, isJointTour);
                alternative.AddUtilityTerm(183, escortTourFlag);
                alternative.AddUtilityTerm(184, personalBusinessOrMedicalTourFlag);
                alternative.AddUtilityTerm(185, shoppingTourFlag);
                alternative.AddUtilityTerm(186, mealTourFlag);
                alternative.AddUtilityTerm(187, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(188, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(189, Math.Log(1 + simulatedSocialStops * isIndividual));
                alternative.AddUtilityTerm(197, Math.Log(1 + simulatedSocialStops * isJointTour));
                alternative.AddUtilityTerm(190, remainingToursCount);
                alternative.AddUtilityTerm(191, duration);
                alternative.AddUtilityTerm(192, from7AMto9AMFlag + from11PMto7AMFlag);
                alternative.AddUtilityTerm(194, hov2TourFlag);
                alternative.AddUtilityTerm(195, hov3TourFlag);
                alternative.AddUtilityTerm(196, logDist);
                alternative.AddUtilityTerm(198, totalAggregateLogsum);
                alternative.AddUtilityTerm(200, numAdultsOnJointTour);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Social, false, choice == Global.Settings.Purposes.Social);
            }


            // 8 - RECREATION STOP

            if (personDay.RecreationStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Recreation, true, choice == Global.Settings.Purposes.Recreation);

                alternative.Choice = Global.Settings.Purposes.Recreation;

                alternative.AddUtilityTerm(211, workTourFlag + schoolTourFlag);
                alternative.AddUtilityTerm(212, isJointTour);
                alternative.AddUtilityTerm(213, escortTourFlag);
                alternative.AddUtilityTerm(214, personalBusinessOrMedicalTourFlag);
                alternative.AddUtilityTerm(215, shoppingTourFlag);
                alternative.AddUtilityTerm(216, mealTourFlag);
                alternative.AddUtilityTerm(217, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(218, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(219, Math.Log(1 + simulatedRecreationStops * isIndividual));
                alternative.AddUtilityTerm(229, Math.Log(1 + simulatedRecreationStops * isJointTour));
                alternative.AddUtilityTerm(220, remainingToursCount);
                alternative.AddUtilityTerm(221, duration);
                alternative.AddUtilityTerm(222, from7AMto9AMFlag + from11PMto7AMFlag);
                alternative.AddUtilityTerm(223, from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag);
                alternative.AddUtilityTerm(225, hov3TourFlag);
                alternative.AddUtilityTerm(226, numChildrenOnJointTour);
                alternative.AddUtilityTerm(227, numAdultsOnJointTour);
                //alternative.AddUtilityTerm(228, fullJointHalfTour);
                //alternative.AddUtilityTerm(229, openSpaceBuffer2);
                alternative.AddUtilityTerm(228, totalAggregateLogsum);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Recreation, false, choice == Global.Settings.Purposes.Recreation);
            }

            // 9 - MEDICAL STOP

            if (personDay.MedicalStops > 0 || isJoint > 0)
            {
                alternative = choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Medical, true, choice == Global.Settings.Purposes.Medical);

                alternative.Choice = Global.Settings.Purposes.Medical;

                alternative.AddUtilityTerm(231, workTourFlag + schoolTourFlag + escortTourFlag);
                alternative.AddUtilityTerm(232, isJointTour);
                alternative.AddUtilityTerm(233, personalBusinessOrMedicalTourFlag * isIndividual);
                alternative.AddUtilityTerm(234, personalBusinessOrMedicalTourFlag * isJointTour);
                alternative.AddUtilityTerm(235, shoppingTourFlag);
                alternative.AddUtilityTerm(236, mealTourFlag);
                alternative.AddUtilityTerm(237, socialOrRecreationTourFlag);
                alternative.AddUtilityTerm(238, halfTourFromOriginFlag);
                alternative.AddUtilityTerm(239, Math.Log(1 + simulatedMedicalStops * isJointTour));
                alternative.AddUtilityTerm(240, Math.Log(1 + simulatedMedicalStops * isIndividual));
                //alternative.AddUtilityTerm(240, fullJointHalfTour);
                alternative.AddUtilityTerm(241, duration);
                alternative.AddUtilityTerm(242, from7AMto9AMFlag + from11PMto7AMFlag);
                alternative.AddUtilityTerm(243, from11AMto1PMFlag + from1PMto3PMFlag + from3PMto5PMFlag);
                //alternative.AddUtilityTerm(248, numChildrenOnJointTour);
                //alternative.AddUtilityTerm(249, adultFemaleOnJointTour);
                alternative.AddUtilityTerm(244, totalAggregateLogsum);
            }
            else
            {
                choiceProbabilityCalculator.GetAlternative(Global.Settings.Purposes.Medical, false, choice == Global.Settings.Purposes.Medical);
            }
        }
            public void SetUtilities(ISampleItem sampleItem, int sampleFrequency)
            {
                if (sampleItem == null)
                {
                    throw new ArgumentNullException("sampleItem");
                }

                ChoiceProbabilityCalculator.Alternative alternative = sampleItem.Alternative;

                if (!alternative.Available)
                {
                    return;
                }

                IHouseholdWrapper household = _tour.Household;
                IPersonWrapper    person    = _tour.Person;
                //                var personDay = _tour.PersonDay;
                bool householdHasChildren = household.HasChildren;

                IParcelWrapper destinationParcel = ChoiceModelFactory.Parcels[sampleItem.ParcelId];

                double fastestTravelTime =
                    ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov3, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, _fastestAvailableTimeOfDay, _tour.OriginParcel, destinationParcel).Variable +
                    ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov3, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, _fastestAvailableTimeOfDay, destinationParcel, _tour.OriginParcel).Variable;

                if (fastestTravelTime >= _maxAvailableMinutes)
                {
                    alternative.Available = false;

                    return;
                }

                alternative.Choice = destinationParcel;

                double tourLogsum;

                if (_tour.IsHomeBasedTour)
                {
                    if (_tour.DestinationPurpose == Global.Settings.Purposes.Escort)
                    {
                        ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <EscortTourModeModel>().RunNested(_tour, destinationParcel);
                        tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                    }
                    else
                    {
                        ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <OtherHomeBasedTourModeModel>().RunNested(_tour, destinationParcel);
                        tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                    }
                }
                else
                {
                    ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <WorkBasedSubtourModeModel>().RunNested(_tour, destinationParcel);
                    tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }

                //var purpose = _tour.TourPurposeSegment;
                int carOwnership = person.GetCarOwnershipSegment();
                //var votSegment = _tour.VotALSegment;
                //var transitAccess = destinationParcel.TransitAccessSegment();
                //var aggregateLogsum = Global.AggregateLogsums[destinationParcel.ZoneId][purpose][carOwnership][votSegment][transitAccess];
                //var aggregateLogsumHomeBased = Global.AggregateLogsums[destinationParcel.ZoneId][Global.Settings.Purposes.HomeBasedComposite][carOwnership][votSegment][transitAccess];
                //var aggregateLogsumWorkBased = Global.AggregateLogsums[destinationParcel.ZoneId][Global.Settings.Purposes.Work_BASED][carOwnership][votSegment][transitAccess];

                //distanceFromOrigin is in units of 10 miles, so 1=10 miles
                double distanceFromOrigin    = _tour.OriginParcel.DistanceFromOrigin(destinationParcel, _tour.DestinationArrivalTime);
                double distanceFromOrigin0   = Math.Max(0, Math.Min(distanceFromOrigin - .5, 1 - .5));
                double distanceFromOrigin3   = Math.Max(0, distanceFromOrigin - 1);                     //distance over 10 miles
                double distanceFromOrigin4   = Math.Min(distanceFromOrigin, .10);                       //distance up to 1 mile
                double distanceFromOrigin5   = Math.Max(0, Math.Min(distanceFromOrigin - .1, .5 - .1)); //distance between 1 and 5 miles
                double distanceFromOrigin8   = Math.Max(0, Math.Min(distanceFromOrigin - .1, .35 - .1));
                double distanceFromOrigin9   = Math.Max(0, Math.Min(distanceFromOrigin - .35, 1 - .35));
                double distanceFromOriginLog = Math.Log(1 + distanceFromOrigin);
                double distanceFromWorkLog   = person.UsualWorkParcel.DistanceFromWorkLog(destinationParcel, 1);
                double distanceFromSchoolLog = person.UsualSchoolParcel.DistanceFromSchoolLog(destinationParcel, 1);

                double timePressure = Math.Log(1 - fastestTravelTime / _maxAvailableMinutes);

                // log transforms of buffers for Neighborhood effects
                double empEduBuffer = Math.Log(destinationParcel.EmploymentEducationBuffer1 + 1.0);
                double empFooBuffer = Math.Log(destinationParcel.EmploymentFoodBuffer1 + 1.0);
                //                var EMPGOV_B = Math.Log(destinationParcel.EmploymentGovernmentBuffer1 + 1.0);
                double empOfcBuffer = Math.Log(destinationParcel.EmploymentOfficeBuffer1 + 1.0);
                double empRetBuffer = Math.Log(destinationParcel.EmploymentRetailBuffer1 + 1.0);
                double empSvcBuffer = Math.Log(destinationParcel.EmploymentServiceBuffer1 + 1.0);
                double empMedBuffer = Math.Log(destinationParcel.EmploymentMedicalBuffer1 + 1.0);
                //                var EMPIND_B = Math.Log(destinationParcel.EmploymentIndustrialBuffer1 + destinationParcel.EmploymentAgricultureConstructionBuffer1 + 1.0);
                double empTotBuffer  = Math.Log(destinationParcel.EmploymentTotalBuffer1 + 1.0);
                double housesBuffer  = Math.Log(destinationParcel.HouseholdsBuffer1 + 1.0);
                double studK12Buffer = Math.Log(destinationParcel.StudentsK8Buffer1 + destinationParcel.StudentsHighSchoolBuffer1 + 1.0);
                double studUniBuffer = Math.Log(destinationParcel.StudentsUniversityBuffer1 + 1.0);
                //                var EMPHOU_B = Math.Log(destinationParcel.EmploymentTotalBuffer1 + destinationParcel.HouseholdsBuffer1 + 1.0);

                // connectivity attributes
                double c34Ratio = destinationParcel.C34RatioBuffer1();

                int carCompetitionFlag   = FlagUtility.GetCarCompetitionFlag(carOwnership); // exludes no cars
                int noCarCompetitionFlag = FlagUtility.GetNoCarCompetitionFlag(carOwnership);
                int noCarsFlag           = FlagUtility.GetNoCarsFlag(carOwnership);

                alternative.AddUtilityTerm(1, sampleItem.AdjustmentFactor);
                alternative.AddUtilityTerm(2, (_tour.IsHomeBasedTour).ToFlag() * timePressure);

                alternative.AddUtilityTerm(3, _secondaryFlag * _workOrSchoolPatternFlag * distanceFromOrigin0);
                alternative.AddUtilityTerm(4, _secondaryFlag * _otherPatternFlag * distanceFromOrigin5);
                alternative.AddUtilityTerm(5, _secondaryFlag * _otherPatternFlag * distanceFromOrigin0);
                alternative.AddUtilityTerm(6, _secondaryFlag * _otherPatternFlag * distanceFromOrigin3);

                alternative.AddUtilityTerm(7, (!_tour.IsHomeBasedTour).ToFlag() * distanceFromOriginLog);
                //new calibration constants work-based tours
                alternative.AddUtilityTerm(58, (!_tour.IsHomeBasedTour).ToFlag() * distanceFromOrigin4);
                alternative.AddUtilityTerm(59, (!_tour.IsHomeBasedTour).ToFlag() * distanceFromOrigin3);
                alternative.AddUtilityTerm(60, (!_tour.IsHomeBasedTour).ToFlag() * distanceFromOrigin5);

                alternative.AddUtilityTerm(8, household.Has0To15KIncome.ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(9, household.HasMissingIncome.ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(10, person.IsRetiredAdult.ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(11, person.IsChildAge5Through15.ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(12, person.IsChildUnder5.ToFlag() * distanceFromOriginLog);

                alternative.AddUtilityTerm(13, (_tour.IsHomeBasedTour).ToFlag() * distanceFromSchoolLog);
                alternative.AddUtilityTerm(14, distanceFromWorkLog);

                alternative.AddUtilityTerm(15, carCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixInParcel());
                alternative.AddUtilityTerm(16, noCarCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixInParcel());
                alternative.AddUtilityTerm(17, carCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixBuffer1());
                alternative.AddUtilityTerm(18, noCarCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixBuffer1());

                alternative.AddUtilityTerm(19, noCarsFlag * c34Ratio);


                if (_tour.DestinationPurpose == Global.Settings.Purposes.Escort)
                {
                    alternative.AddUtilityTerm(20, tourLogsum);
                    alternative.AddUtilityTerm(21, distanceFromOrigin4);
                    alternative.AddUtilityTerm(22, distanceFromOrigin8);
                    alternative.AddUtilityTerm(23, distanceFromOrigin9);

                    // Neighborhood
                    alternative.AddUtilityTerm(24, householdHasChildren.ToFlag() * studK12Buffer);
                    alternative.AddUtilityTerm(25, empTotBuffer);

                    // Size terms
                    alternative.AddUtilityTerm(71, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(72, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentFood);
                    alternative.AddUtilityTerm(73, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(74, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(75, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentRetail);
                    alternative.AddUtilityTerm(76, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(77, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentMedical);
                    alternative.AddUtilityTerm(78, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentIndustrial + destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(79, (!householdHasChildren).ToFlag() * destinationParcel.Households);

                    alternative.AddUtilityTerm(80, householdHasChildren.ToFlag() * destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(81, householdHasChildren.ToFlag() * destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(82, householdHasChildren.ToFlag() * destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(83, householdHasChildren.ToFlag() * destinationParcel.EmploymentRetail);
                    alternative.AddUtilityTerm(84, householdHasChildren.ToFlag() * destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(85, householdHasChildren.ToFlag() * destinationParcel.EmploymentMedical);
                    alternative.AddUtilityTerm(86, householdHasChildren.ToFlag() * destinationParcel.EmploymentIndustrial + destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(87, householdHasChildren.ToFlag() * destinationParcel.Households);
                    alternative.AddUtilityTerm(88, householdHasChildren.ToFlag() * destinationParcel.GetStudentsK12());
                }
                else if (_tour.DestinationPurpose == Global.Settings.Purposes.PersonalBusiness || _tour.DestinationPurpose == Global.Settings.Purposes.Medical)
                {
                    alternative.AddUtilityTerm(26, tourLogsum);
                    alternative.AddUtilityTerm(27, distanceFromOrigin4);
                    alternative.AddUtilityTerm(28, distanceFromOrigin8);
                    alternative.AddUtilityTerm(29, distanceFromOrigin9);
                    alternative.AddUtilityTerm(30, distanceFromOrigin3);

                    // Neighborhood
                    alternative.AddUtilityTerm(31, empEduBuffer);
                    alternative.AddUtilityTerm(32, empSvcBuffer);
                    alternative.AddUtilityTerm(33, empMedBuffer);
                    alternative.AddUtilityTerm(34, housesBuffer); // also psrc
                    alternative.AddUtilityTerm(35, studUniBuffer);


                    // Size terms
                    alternative.AddUtilityTerm(89, destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(90, destinationParcel.EmploymentFood);
                    alternative.AddUtilityTerm(91, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(92, destinationParcel.EmploymentRetail);
                    alternative.AddUtilityTerm(93, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(94, destinationParcel.EmploymentMedical);
                    alternative.AddUtilityTerm(95, destinationParcel.EmploymentIndustrial + destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(96, destinationParcel.Households);
                    alternative.AddUtilityTerm(97, destinationParcel.GetStudentsK12());
                }
                else if (_tour.DestinationPurpose == Global.Settings.Purposes.Shopping)
                {
                    alternative.AddUtilityTerm(36, tourLogsum);
                    alternative.AddUtilityTerm(37, distanceFromOrigin4);
                    alternative.AddUtilityTerm(38, distanceFromOrigin8);
                    alternative.AddUtilityTerm(39, distanceFromOrigin9);
                    alternative.AddUtilityTerm(40, distanceFromOrigin3);

                    // Neighborhood
                    alternative.AddUtilityTerm(41, empEduBuffer); // also psrc
                    alternative.AddUtilityTerm(42, empRetBuffer); // also psrc

                    // Size terms
                    alternative.AddUtilityTerm(98, destinationParcel.EmploymentFood);
                    alternative.AddUtilityTerm(99, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(100, destinationParcel.EmploymentRetail);
                    alternative.AddUtilityTerm(101, destinationParcel.EmploymentService);
                }
                else if (_tour.DestinationPurpose == Global.Settings.Purposes.Meal)
                {
                    alternative.AddUtilityTerm(43, tourLogsum);
                    alternative.AddUtilityTerm(44, distanceFromOrigin4);
                    alternative.AddUtilityTerm(45, distanceFromOrigin8);
                    alternative.AddUtilityTerm(46, distanceFromOrigin9);
                    alternative.AddUtilityTerm(47, distanceFromOrigin3);

                    // Neighborhood
                    alternative.AddUtilityTerm(48, empFooBuffer); // psrc

                    // Size terms
                    alternative.AddUtilityTerm(102, destinationParcel.EmploymentFood);
                    alternative.AddUtilityTerm(103, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(104, destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(105, destinationParcel.Households);
                }
                else if (_tour.DestinationPurpose == Global.Settings.Purposes.Social || _tour.DestinationPurpose == Global.Settings.Purposes.Recreation)
                {
                    alternative.AddUtilityTerm(49, tourLogsum);
                    alternative.AddUtilityTerm(50, distanceFromOrigin4);
                    alternative.AddUtilityTerm(51, distanceFromOrigin8);
                    alternative.AddUtilityTerm(52, distanceFromOrigin9);
                    alternative.AddUtilityTerm(53, distanceFromOrigin3);

                    // Neighborhood
                    alternative.AddUtilityTerm(54, empOfcBuffer);  // also psrc
                    alternative.AddUtilityTerm(55, empSvcBuffer);  // also psrc
                    alternative.AddUtilityTerm(56, housesBuffer);  // also psrc
                    alternative.AddUtilityTerm(57, studUniBuffer); // psrc

                    // Size terms
                    alternative.AddUtilityTerm(106, destinationParcel.EmploymentFood);
                    alternative.AddUtilityTerm(107, destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(108, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(109, destinationParcel.EmploymentRetail);
                    alternative.AddUtilityTerm(110, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(111, destinationParcel.Households);
                    alternative.AddUtilityTerm(112, destinationParcel.StudentsUniversity);
                    alternative.AddUtilityTerm(113, destinationParcel.GetStudentsK12());
                    //new size variable for log(sq ft open space)
                    if (destinationParcel.LandUseCode > 0)
                    {
                        alternative.AddUtilityTerm(120, (Global.Configuration.UseParcelLandUseCodeAsSquareFeetOpenSpace) ? Math.Log(destinationParcel.LandUseCode + 1.0) : 0.0);
                    }
                }

                //add any region-specific new terms in region-specific class, using coefficient numbers 114-120, or other unused variable #
                _parentClass.RegionSpecificOtherTourDistrictCoefficients(alternative, _tour, destinationParcel);

                // OD shadow pricing
                if (Global.Configuration.ShouldUseODShadowPricing)
                {
                    int ori = _tour.OriginParcel.District;
                    int des = destinationParcel.District;
                    //var first = res <= des? res : des;
                    //var second = res <= des? des : res;
                    double shadowPriceConfigurationParameter = ori == des ? Global.Configuration.OtherTourDestinationOOShadowPriceCoefficient : Global.Configuration.OtherTourDestinationODShadowPriceCoefficient;
                    int    odShadowPriceF12Value             = MAX_REGULAR_PARAMETER + Global.Configuration.NumberOfODShadowPricingDistricts * (ori - 1) + des;
                    alternative.AddUtilityTerm(odShadowPriceF12Value, shadowPriceConfigurationParameter);
                }
            }
            public void SetUtilities(ISampleItem sampleItem, int sampleFrequency)
            {
                if (sampleItem == null)
                {
                    throw new ArgumentNullException("sampleItem");
                }

                ChoiceProbabilityCalculator.Alternative alternative = sampleItem.Alternative;

                IHouseholdWrapper household = _tour.Household;
                IPersonWrapper    person    = _tour.Person;
                IPersonDayWrapper personDay = _tour.PersonDay;
                //                var householdHasChildren = household.HasChildren;

                IParcelWrapper destinationParcel = ChoiceModelFactory.Parcels[sampleItem.ParcelId];

                IParcelWrapper excludedParcel      = person.UsualWorkParcel == null || person.UsualWorkParcelId == household.ResidenceParcelId || _tour.DestinationPurpose != Global.Settings.Purposes.Work || _tour.GetTourCategory() == Global.Settings.TourCategories.WorkBased ? null : person.UsualWorkParcel;
                bool           usualWorkParcel     = (excludedParcel != null && excludedParcel.Id == destinationParcel.Id); // only 1 for oddball alternative on tours with oddball alternative
                int            usualWorkParcelFlag = usualWorkParcel.ToFlag();

                // Comment out these nesting calls when estimating the conditional flat model
                // model is NL with oddball alternative
                if (usualWorkParcelFlag == 0)
                {
                    // this alternative is in the non-oddball nest
                    alternative.AddNestedAlternative(_sampleSize + 2, 0, 60); // associates alternative with non-oddball nest
                }
                else
                {
                    // this is the oddball alternative
                    alternative.AddNestedAlternative(_sampleSize + 3, 1, 60); // associates alternative with oddball nest
                }


                if (!alternative.Available)
                {
                    return;
                }


                // use this block of code to eliminate the oddball alternative for estimation of the conditional model
                //if (usualWorkParcelFlag == 1) {
                //    alternative.Available = false;
                //
                //    return;
                //}

                double fastestTravelTime =
                    ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov3, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, _fastestAvailableTimeOfDay, _tour.OriginParcel, destinationParcel).Variable +
                    ImpedanceRoster.GetValue("ivtime", Global.Settings.Modes.Hov3, Global.Settings.PathTypes.FullNetwork, Global.Settings.ValueOfTimes.DefaultVot, _fastestAvailableTimeOfDay, destinationParcel, _tour.OriginParcel).Variable;

                if (fastestTravelTime >= _maxAvailableMinutes)
                {
                    alternative.Available = false;

                    return;
                }

                alternative.Choice = destinationParcel;

                double tourLogsum;

                if (_tour.IsHomeBasedTour)
                {
                    ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <WorkTourModeModel>().RunNested(_tour, destinationParcel, household.VehiclesAvailable, person.GetTransitFareDiscountFraction());
                    tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }
                else
                {
                    ChoiceProbabilityCalculator.Alternative nestedAlternative = Global.ChoiceModelSession.Get <WorkBasedSubtourModeModel>().RunNested(_tour, destinationParcel);
                    tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }

                //var purpose = _tour.TourPurposeSegment;
                //var nonWorkPurpose = _tour.DestinationPurpose != Global.Settings.Purposes.Work;
                int carOwnership = person.GetCarOwnershipSegment();
                //var votSegment = _tour.VotALSegment;
                //var transitAccess = destinationParcel.TransitAccessSegment();
                //var aggregateLogsum = Global.AggregateLogsums[destinationParcel.ZoneId][purpose][carOwnership][votSegment][transitAccess];
                //var aggregateLogsumHomeBased = Global.AggregateLogsums[destinationParcel.ZoneId][Global.Settings.Purposes.HomeBasedComposite][carOwnership][votSegment][transitAccess];
                //var aggregateLogsumWorkBased = Global.AggregateLogsums[destinationParcel.ZoneId][Global.Settings.Purposes.Work_BASED][carOwnership][votSegment][transitAccess];

                double distanceFromOrigin = _tour.OriginParcel.DistanceFromOrigin(destinationParcel, _tour.DestinationArrivalTime);
                //                var distanceFromOrigin0 = Math.Max(0, Math.Min(distanceFromOrigin - .5, 1 - .5));
                //                var distanceFromOrigin3 = Math.Max(0, distanceFromOrigin - 1);
                //                var distanceFromOrigin4 = Math.Min(distanceFromOrigin, .10);
                //                var distanceFromOrigin5 = Math.Max(0, Math.Min(distanceFromOrigin - .1, .5 - .1));
                //                var distanceFromOrigin8 = Math.Max(0, Math.Min(distanceFromOrigin - .1, .35 - .1));
                //                var distanceFromOrigin9 = Math.Max(0, Math.Min(distanceFromOrigin - .35, 1 - .35));
                double distanceFromOriginLog = Math.Log(1 + distanceFromOrigin);
                double distanceFromWorkLog   = person.UsualWorkParcel.DistanceFromWorkLog(destinationParcel, 1);
                double distanceFromSchoolLog = person.UsualSchoolParcel.DistanceFromSchoolLog(destinationParcel, 1);
                //                var millionsSquareFeet = destinationZoneTotals.MillionsSquareFeet();

                double timePressure = Math.Log(1 - fastestTravelTime / _maxAvailableMinutes);

                // log transforms of buffers for Neighborhood effects
                double empEduBuffer = Math.Log(destinationParcel.EmploymentEducationBuffer1 + 1.0);
                //                var EMPFOO_B = Math.Log(destinationParcel.EmploymentFoodBuffer1 + 1.0);
                //                var EMPGOV_B = Math.Log(destinationParcel.EmploymentGovernmentBuffer1 + 1.0);
                double empOfcBuffer = Math.Log(destinationParcel.EmploymentOfficeBuffer1 + 1.0);
                //                var EMPRET_B = Math.Log(destinationParcel.EmploymentRetailBuffer1 + 1.0);
                //                var EMPSVC_B = Math.Log(destinationParcel.EmploymentServiceBuffer1 + 1.0);
                //                var EMPMED_B = Math.Log(destinationParcel.EmploymentMedicalBuffer1 + 1.0);
                double empIndBuffer = Math.Log(destinationParcel.EmploymentIndustrialBuffer1 + destinationParcel.EmploymentAgricultureConstructionBuffer1 + 1.0);
                //                var EMPTOT_B = Math.Log(destinationParcel.EmploymentTotalBuffer1 + 1.0);
                double housesBuffer = Math.Log(destinationParcel.HouseholdsBuffer1 + 1.0);
                //                var STUDK12B = Math.Log(destinationParcel.StudentsK8Buffer1 + destinationParcel.StudentsHighSchoolBuffer1 + 1.0);
                //                var STUDUNIB = Math.Log(destinationParcel.StudentsUniversityBuffer1 + 1.0);
                //                var EMPHOU_B = Math.Log(destinationParcel.EmploymentTotalBuffer1 + destinationParcel.HouseholdsBuffer1 + 1.0);

                // parking attributes
                //                var parcelParkingDensity = destinationParcel.ParcelParkingPerTotalEmployment();
                //                var zoneParkingDensity = destinationParcel.ZoneParkingPerTotalEmploymentAndK12UniversityStudents(destinationZoneTotals, millionsSquareFeet);
                //                var ParkingPaidDailyLogBuffer1 = Math.Log(1 + destinationParcel.ParkingOffStreetPaidDailySpacesBuffer1);

                // connectivity attributes
                //                var c34Ratio = destinationParcel.C34RatioBuffer1();

                //                var carDeficitFlag = FlagUtility.GetCarDeficitFlag(carOwnership);  // includes no cars
                //                var carCompetitionFlag = FlagUtility.GetCarCompetitionFlag(carOwnership); // exludes no cars
                int noCarCompetitionFlag = FlagUtility.GetNoCarCompetitionFlag(carOwnership);

                //                var noCarsFlag = FlagUtility.GetNoCarsFlag(carOwnership);

                // Usual location attributes
                alternative.AddUtilityTerm(1, usualWorkParcelFlag);
                alternative.AddUtilityTerm(2, person.IsPartTimeWorker.ToFlag() * usualWorkParcelFlag);
                alternative.AddUtilityTerm(3, person.IsStudentAge.ToFlag() * usualWorkParcelFlag);
                alternative.AddUtilityTerm(4, _primaryFlag * personDay.TwoOrMoreWorkToursExist().ToFlag() * usualWorkParcelFlag);
                alternative.AddUtilityTerm(5, personDay.WorkStopsExist().ToFlag() * usualWorkParcelFlag);
                alternative.AddUtilityTerm(6, _secondaryFlag * usualWorkParcelFlag);

                // non-usual location attributes
                alternative.AddUtilityTerm(11, (!usualWorkParcel).ToFlag() * sampleItem.AdjustmentFactor);
                alternative.AddUtilityTerm(12, _tour.IsHomeBasedTour.ToFlag() * (!usualWorkParcel).ToFlag() * timePressure);

                alternative.AddUtilityTerm(13, (!usualWorkParcel).ToFlag() * person.IsFulltimeWorker.ToFlag() * tourLogsum);
                alternative.AddUtilityTerm(14, (!usualWorkParcel).ToFlag() * person.IsPartTimeWorker.ToFlag() * tourLogsum);
                alternative.AddUtilityTerm(15, (!usualWorkParcel).ToFlag() * person.IsNotFullOrPartTimeWorker.ToFlag() * tourLogsum);
                alternative.AddUtilityTerm(16, (!usualWorkParcel).ToFlag() * person.IsRetiredAdult.ToFlag() * distanceFromOriginLog);

                alternative.AddUtilityTerm(17, (!usualWorkParcel).ToFlag() * distanceFromWorkLog);
                alternative.AddUtilityTerm(18, (!usualWorkParcel).ToFlag() * person.IsStudentAge.ToFlag() * distanceFromSchoolLog);

                alternative.AddUtilityTerm(19, (!usualWorkParcel).ToFlag() * noCarCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixBuffer1());

                // non-usual location Neighborhood attributes
                alternative.AddUtilityTerm(31, (!usualWorkParcel).ToFlag() * empEduBuffer);
                alternative.AddUtilityTerm(32, (!usualWorkParcel).ToFlag() * empOfcBuffer);
                alternative.AddUtilityTerm(33, (!usualWorkParcel).ToFlag() * housesBuffer);
                alternative.AddUtilityTerm(34, (!usualWorkParcel).ToFlag() * empIndBuffer);

                // non-usual location Size terms (consider conditioning these by fulltime, parttime, notFTPT, an income (see original sacog spec)
                alternative.AddUtilityTerm(40, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentEducation);
                alternative.AddUtilityTerm(41, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentFood);
                alternative.AddUtilityTerm(42, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentGovernment);
                alternative.AddUtilityTerm(43, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentOffice);
                alternative.AddUtilityTerm(44, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentRetail);
                alternative.AddUtilityTerm(45, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentService);
                alternative.AddUtilityTerm(46, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentMedical);
                alternative.AddUtilityTerm(47, (!usualWorkParcel).ToFlag() * destinationParcel.EmploymentIndustrial + destinationParcel.EmploymentAgricultureConstruction);
                alternative.AddUtilityTerm(48, (!usualWorkParcel).ToFlag() * destinationParcel.Households);
                alternative.AddUtilityTerm(49, (!usualWorkParcel).ToFlag() * destinationParcel.StudentsUniversity);


                // OD shadow pricing
                if (!usualWorkParcel && Global.Configuration.ShouldUseODShadowPricing)
                {
                    int ori = _tour.OriginParcel.District;
                    int des = destinationParcel.District;
                    //var first = res <= des? res : des;
                    //var second = res <= des? des : res;
                    double shadowPriceConfigurationParameter = ori == des ? Global.Configuration.WorkTourDestinationOOShadowPriceCoefficient : Global.Configuration.WorkTourDestinationODShadowPriceCoefficient;
                    int    odShadowPriceF12Value             = MAX_REGULAR_PARAMETER + Global.Configuration.NumberOfODShadowPricingDistricts * (ori - 1) + des;
                    alternative.AddUtilityTerm(odShadowPriceF12Value, shadowPriceConfigurationParameter);
                }



                //        // usual location size term
                //        alternative.AddUtilityTerm(50, usualWorkParcelFlag * 1);

                //        // Comment out these nesting calls when estimating the conditional flat model
                //        // model is NL with oddball alternative
                //        if (usualWorkParcelFlag == 0) {
                //            // this alternative is in the non-oddball nest
                //            alternative.AddNestedAlternative(_sampleSize + 2, 0, 60); // associates alternative with non-oddball nest
                //        }
                //        else {
                //            // this is the oddball alternative
                //            alternative.AddNestedAlternative(_sampleSize + 3, 1, 60); // associates alternative with oddball nest
                //        }
            }