Example #1
0
        public ChoiceProbabilityCalculator.Alternative RunNested(TourWrapper tour, IParcelWrapper destinationParcel, int householdCars, double transitDiscountFraction)
        {
            if (Global.Configuration.AvoidDisaggregateModeChoiceLogsums)
            {
                return(null);
            }
            var choiceProbabilityCalculator = _helpers[ParallelUtility.GetBatchFromThreadId()].GetNestedChoiceProbabilityCalculator();

            HouseholdDayWrapper householdDay = (tour.PersonDay == null) ? null : (HouseholdDayWrapper)tour.PersonDay.HouseholdDay;

            int constrainedMode          = 0;
            int constrainedArrivalTime   = (Global.Configuration.ConstrainTimesForModeChoiceLogsums) ? tour.DestinationArrivalTime : 0;
            int constrainedDepartureTime = (Global.Configuration.ConstrainTimesForModeChoiceLogsums) ? tour.DestinationDepartureTime : 0;

            tour.DestinationParcel = destinationParcel;
            HTourModeTime.SetModeTimeImpedances(householdDay, tour, constrainedMode, constrainedArrivalTime, constrainedDepartureTime, householdCars, transitDiscountFraction);

            RunModel(choiceProbabilityCalculator, householdDay, tour, destinationParcel, householdCars, constrainedMode, constrainedArrivalTime, constrainedDepartureTime);

            return(choiceProbabilityCalculator.SimulateChoice(tour.Household.RandomUtility));
        }
        public void Run(TourWrapper tour, HouseholdDayWrapper householdDay, int sampleSize, IParcelWrapper constrainedParcel = null)
        {
            if (tour == null)
            {
                throw new ArgumentNullException("tour");
            }

            tour.PersonDay.ResetRandom(20 + tour.Sequence - 1);

            if (Global.Configuration.IsInEstimationMode)
            {
                if (Global.Configuration.EstimationModel != CHOICE_MODEL_NAME)
                {
                    return;
                }
                if (!TourDestinationUtilities.ShouldRunInEstimationModeForModel(tour))
                {
                    return;
                }
                // JLB 20140421 add the following to keep from estimatign twice for the same tour
                if (tour.DestinationModeAndTimeHaveBeenSimulated)
                {
                    return;
                }
            }

            if (tour.DestinationPurpose == Global.Settings.Purposes.School)
            {
                // the following lines were redundant.  Usual destination properties are set in GetMandatoryTourSimulatedData()
                // sets the destination for the school tour
                //tour.DestinationParcelId = tour.Person.UsualSchoolParcelId;
                //tour.DestinationParcel = tour.Person.UsualSchoolParcel;
                //tour.DestinationZoneKey = tour.Person.UsualSchoolZoneKey;
                //tour.DestinationAddressType = Global.Settings.AddressTypes.UsualSchool;
                return;
            }
            else if (tour.DestinationPurpose == Global.Settings.Purposes.Work)
            {
                return;
            }
            else if (constrainedParcel != null)
            {
                tour.DestinationParcel   = constrainedParcel;
                tour.DestinationParcelId = constrainedParcel.Id;
                tour.DestinationZoneKey  = constrainedParcel.ZoneId;
                return;
            }

            var choiceProbabilityCalculator = _helpers[ParallelUtility.GetBatchFromThreadId()].GetChoiceProbabilityCalculator(tour.Id);

            if (_helpers[ParallelUtility.GetBatchFromThreadId()].ModelIsInEstimationMode)
            {
                if (constrainedParcel == null)
                {
                    RunModel(choiceProbabilityCalculator, tour, householdDay, sampleSize, tour.DestinationParcel);

                    choiceProbabilityCalculator.WriteObservation();
                }
            }
            else
            {
                RunModel(choiceProbabilityCalculator, tour, householdDay, sampleSize);

                var chosenAlternative = choiceProbabilityCalculator.SimulateChoice(tour.Household.RandomUtility);

                if (chosenAlternative == null)
                {
                    Global.PrintFile.WriteNoAlternativesAvailableWarning(CHOICE_MODEL_NAME, "Run", tour.PersonDay.Id);
                    if (!Global.Configuration.IsInEstimationMode)
                    {
                        tour.PersonDay.IsValid = false;
                        tour.PersonDay.HouseholdDay.IsValid = false;
                    }

                    return;
                }

                var choice = (IParcelWrapper)chosenAlternative.Choice;

                tour.DestinationParcelId    = choice.Id;
                tour.DestinationParcel      = choice;
                tour.DestinationZoneKey     = ChoiceModelFactory.ZoneKeys[choice.ZoneId];
                tour.DestinationAddressType = Global.Settings.AddressTypes.Other;
            }
        }
        private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, TourWrapper tour, HouseholdDayWrapper householdDay, int sampleSize, IParcelWrapper choice = null)
        {
            timesStartedRunModel++;
            HouseholdWrapper household = (HouseholdWrapper)tour.Household;
            PersonWrapper    person    = (PersonWrapper)tour.Person;
            PersonDayWrapper personDay = (PersonDayWrapper)tour.PersonDay;

            //			var totalAvailableMinutes =
            //				tour.ParentTour == null
            //					? personDay.TimeWindow.TotalAvailableMinutes(1, Global.Settings.Times.MinutesInADay)
            //					: tour.ParentTour.TimeWindow.TotalAvailableMinutes(1, Global.Settings.Times.MinutesInADay);


            TimeWindow timeWindow = new TimeWindow();

            if (tour.JointTourSequence > 0)
            {
                foreach (PersonDayWrapper pDay in householdDay.PersonDays)
                {
                    TourWrapper tInJoint = (TourWrapper)pDay.Tours.Find(t => t.JointTourSequence == tour.JointTourSequence);
                    if (!(tInJoint == null))
                    {
                        // set jointTour time window
                        timeWindow.IncorporateAnotherTimeWindow(tInJoint.PersonDay.TimeWindow);
                    }
                }
            }
            else if (tour.ParentTour == null)
            {
                timeWindow.IncorporateAnotherTimeWindow(personDay.TimeWindow);
            }

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

            var maxAvailableMinutes =
                (tour.JointTourSequence > 0 || tour.ParentTour == null)
                                 ? timeWindow.MaxAvailableMinutesAfter(Global.Settings.Times.FiveAM)
                                          : tour.ParentTour.DestinationDepartureTime - tour.ParentTour.DestinationArrivalTime;


            //			var hoursAvailableInverse =
            //				tour.IsHomeBasedTour
            //					? (personDay.HomeBasedTours - personDay.SimulatedHomeBasedTours + 1) / (Math.Max(totalAvailableMinutes - 360, 30) / 60D)
            //					: 1 / (Math.Max(totalAvailableMinutes, 1) / 60D);

            var householdHasChildren   = household.HasChildren;
            var householdHasNoChildren = householdHasChildren ? false : true;

            var fastestAvailableTimeOfDay =
                tour.IsHomeBasedTour || tour.ParentTour == null
                                          ? 1
                                          : tour.ParentTour.DestinationArrivalTime + (tour.ParentTour.DestinationDepartureTime - tour.ParentTour.DestinationArrivalTime) / 2;

            var tourCategory = tour.GetTourCategory();
            //			var primaryFlag = ChoiceModelUtility.GetPrimaryFlag(tourCategory);
            var secondaryFlag           = ChoiceModelUtility.GetSecondaryFlag(tourCategory);
            var workOrSchoolPatternFlag = personDay.GetIsWorkOrSchoolPattern().ToFlag();
            var otherPatternFlag        = personDay.GetIsOtherPattern().ToFlag();
            int jointTourFlag           = (tour.JointTourSequence > 0).ToFlag();



            ChoiceModelUtility.DrawRandomTourTimePeriods(tour, tourCategory);

            if (tour.Household.Id == 80049 && tour.PersonDay.Day == 1 && tour.Person.Sequence == 2 && tour.Sequence == 4)
            {
                bool testbreak = true;
            }

            var segment = Global.Kernel.Get <SamplingWeightsSettingsFactory>().SamplingWeightsSettings.GetTourDestinationSegment(tour.DestinationPurpose, tour.IsHomeBasedTour ? Global.Settings.TourPriorities.HomeBasedTour : Global.Settings.TourPriorities.WorkBasedTour, Global.Settings.Modes.Sov, person.PersonType);


            var destinationSampler       = new DestinationSampler(choiceProbabilityCalculator, segment, sampleSize, tour.OriginParcel, choice);
            var tourDestinationUtilities = new TourDestinationUtilities(tour, sampleSize, secondaryFlag, personDay.GetIsWorkOrSchoolPattern().ToFlag(), personDay.GetIsOtherPattern().ToFlag(), fastestAvailableTimeOfDay, maxAvailableMinutes);

            // get destination sample and perform code that used to be in SetUtilities below
            var sampleItems = destinationSampler.SampleAndReturnTourDestinations(tourDestinationUtilities);

            int index = 0;

            foreach (var sampleItem in sampleItems)
            {
                bool   available         = sampleItem.Key.Available;
                bool   isChosen          = sampleItem.Key.IsChosen;
                double adjustmentFactor  = sampleItem.Key.AdjustmentFactor;
                var    destinationParcel = ChoiceModelFactory.Parcels[sampleItem.Key.ParcelId];

                if (isChosen)
                {
                    Global.PrintFile.WriteLine("Sequence {0}: Chosen parcel {1} Available {2} Sample item {3} of {4}", timesStartedRunModel, destinationParcel.Id, available, index, sampleItems.Count);
                }

                var alternative = choiceProbabilityCalculator.GetAlternative(index++, available, isChosen);


                if (!available)
                {
                    continue;
                }

                var 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;

                    continue;
                }

                alternative.Choice = destinationParcel;

                double tourLogsum;

                if (tour.IsHomeBasedTour)
                {
                    if (tour.DestinationPurpose == Global.Settings.Purposes.Work)
                    {
                        //JLB 201406
                        //var nestedAlternative = Global.ChoiceModelSession.Get<WorkTourModeModel>().RunNested(tour, destinationParcel);
                        // JLB 201602
                        //var nestedAlternative = Global.ChoiceModelSession.Get<WorkTourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                        var nestedAlternative = Global.ChoiceModelSession.Get <TourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                        tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                    }

                    // JLB201406
                    //else if (tour.DestinationPurpose == Global.Settings.Purposes.Escort) {
                    //	var nestedAlternative = Global.ChoiceModelSession.Get<EscortTourModeModel>().RunNested(tour, destinationParcel);
                    //	tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                    //}
                    else
                    {
                        // JLB201406
                        //var nestedAlternative = Global.ChoiceModelSession.Get<OtherHomeBasedTourModeModel>().RunNested(tour, destinationParcel);
                        // JLB 201602
                        //var nestedAlternative = Global.ChoiceModelSession.Get<OtherHomeBasedTourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                        var nestedAlternative = Global.ChoiceModelSession.Get <TourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                        tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                    }
                }
                else
                {
                    // JLB201406
                    //var nestedAlternative = Global.ChoiceModelSession.Get<WorkBasedSubtourModeModel>().RunNested(tour, destinationParcel);
                    // JLB 201602
                    //var nestedAlternative = Global.ChoiceModelSession.Get<WorkBasedSubtourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                    var nestedAlternative = Global.ChoiceModelSession.Get <TourModeTimeModel>().RunNested(tour, destinationParcel, tour.Household.VehiclesAvailable, tour.Person.GetTransitFareDiscountFraction());
                    tourLogsum = nestedAlternative == null ? 0 : nestedAlternative.ComputeLogsum();
                }

                //var purpose = tour.TourPurposeSegment;
                var carOwnership  = person.GetCarOwnershipSegment();
                var votSegment    = tour.GetVotALSegment();
                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.WorkBased][carOwnership][votSegment][transitAccess];

                var distanceFromOrigin = tour.OriginParcel.DistanceFromOrigin(destinationParcel, tour.DestinationArrivalTime);


                // 1. new from GV: Cph KM-distances
                var piecewiseDistanceFrom0To1Km = Math.Min(distanceFromOrigin, .10);

                var piecewiseDistanceFrom0To2Km = Math.Min(distanceFromOrigin, .20);                 //GV: added July 7th
                var piecewiseDistanceFrom0To5Km = Math.Min(distanceFromOrigin, .50);                 //GV: added July 7th

                var piecewiseDistanceFrom1To2Km         = Math.Max(0, Math.Min(distanceFromOrigin - .1, .2 - .1));
                var piecewiseDistanceFrom2To5Km         = Math.Max(0, Math.Min(distanceFromOrigin - .2, .5 - .2));
                var piecewiseDistanceFrom5To10Km        = Math.Max(0, Math.Min(distanceFromOrigin - .5, 1 - .5));
                var piecewiseDistanceFrom10To20Km       = Math.Max(0, Math.Min(distanceFromOrigin - 1, 2 - 1));
                var piecewiseDistanceFrom20KmToInfinity = Math.Max(0, distanceFromOrigin - 2);

                var piecewiseDistanceFrom10KmToInfinity = Math.Max(0, distanceFromOrigin - 1);
                // 1. finished

                var distanceFromOriginLog = Math.Log(1 + distanceFromOrigin);
                var distanceFromWorkLog   = person.UsualWorkParcel.DistanceFromWorkLog(destinationParcel, 1);
                var distanceFromSchoolLog = person.UsualSchoolParcel.DistanceFromSchoolLog(destinationParcel, 1);

                var timePressure = Math.Log(1 - fastestTravelTime / maxAvailableMinutes);


                // 2. new from GV: Cph buffers for neighborhood effects
                // log transforms of buffers for Neighborhood effects
                var logOfOnePlusEducationK8Buffer2          = Math.Log(destinationParcel.StudentsK8Buffer2 + 1.0);
                var logOfOnePlusEducationUniStuBuffer2      = Math.Log(destinationParcel.StudentsUniversityBuffer2 + 1.0);
                var logOfOnePlusEmploymentEducationBuffer2  = Math.Log(destinationParcel.EmploymentEducationBuffer2 + 1.0);
                var logOfOnePlusEmploymentGovernmentBuffer2 = Math.Log(destinationParcel.EmploymentGovernmentBuffer2 + 1.0);
                var logOfOnePlusEmploymentIndustrialBuffer2 = Math.Log(destinationParcel.EmploymentIndustrialBuffer2 + 1.0);
                var logOfOnePlusEmploymentOfficeBuffer2     = Math.Log(destinationParcel.EmploymentOfficeBuffer2 + 1.0);
                var logOfOnePlusEmploymentRetailBuffer2     = Math.Log(destinationParcel.EmploymentRetailBuffer2 + 1.0);
                var logOfOnePlusEmploymentServiceBuffer2    = Math.Log(destinationParcel.EmploymentServiceBuffer2 + 1.0);
                var logOfOnePlusEmploymentAgrConstrBuffer2  = Math.Log(destinationParcel.EmploymentAgricultureConstructionBuffer2 + 1.0);
                var logOfOnePlusEmploymentJobsBuffer2       = Math.Log(destinationParcel.EmploymentTotalBuffer2 + 1.0);
                var logOfOnePlusHouseholdsBuffer2           = Math.Log(destinationParcel.HouseholdsBuffer2 + 1.0);
                // 2. finished


                var logOfOnePlusParkingOffStreetDailySpacesBuffer1 = Math.Log(1 + destinationParcel.ParkingOffStreetPaidDailySpacesBuffer1);
                // connectivity attributes
                var c34Ratio = destinationParcel.C34RatioBuffer1();

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

                alternative.AddUtilityTerm(2, household.Id);
                alternative.AddUtilityTerm(3, personDay.Day);
                alternative.AddUtilityTerm(4, person.Sequence);
                alternative.AddUtilityTerm(5, tour.Sequence);

                alternative.AddUtilityTerm(8, adjustmentFactor);
                alternative.AddUtilityTerm(9, tourLogsum);

                // 3. new from GV: definition of Cph variables

                //alternative.AddUtilityTerm(260, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom0To1Km);
                alternative.AddUtilityTerm(260, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom0To2Km);                 //GV: added July 7th
                //alternative.AddUtilityTerm(261, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom1To2Km);
                alternative.AddUtilityTerm(262, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom2To5Km);
                alternative.AddUtilityTerm(263, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom5To10Km);
                alternative.AddUtilityTerm(264, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom10To20Km);
                alternative.AddUtilityTerm(265, secondaryFlag * workOrSchoolPatternFlag * piecewiseDistanceFrom20KmToInfinity);

                //alternative.AddUtilityTerm(266, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom0To1Km);
                alternative.AddUtilityTerm(266, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom0To2Km);                 //GV: added July 7th
                //alternative.AddUtilityTerm(267, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom1To2Km);
                alternative.AddUtilityTerm(268, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom2To5Km);
                alternative.AddUtilityTerm(269, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom5To10Km);
                alternative.AddUtilityTerm(270, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom10To20Km);
                alternative.AddUtilityTerm(271, secondaryFlag * otherPatternFlag * piecewiseDistanceFrom20KmToInfinity);

                //alternative.AddUtilityTerm(268, (!_tour.IsHomeBasedTour).ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(269, household.Has0To15KIncome.ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(270, household.HasMissingIncome.ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(271, person.IsRetiredAdult.ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(272, person.IsUniversityStudent.ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(273, person.IsChildAge5Through15.ToFlag() * distanceFromOriginLog);
                //alternative.AddUtilityTerm(274, person.IsChildUnder5.ToFlag() * distanceFromOriginLog);

                alternative.AddUtilityTerm(272, (!tour.IsHomeBasedTour).ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(273, (household.Income >= 300000 && household.Income < 600000).ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(274, (household.Income >= 600000 && household.Income < 900000).ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(275, (household.Income >= 900000).ToFlag() * distanceFromOriginLog);

                //alternative.AddUtilityTerm(276, person.IsChildUnder5.ToFlag() * distanceFromOriginLog); // commented out by GV, July 7th
                //alternative.AddUtilityTerm(277, person.IsChildAge5Through15.ToFlag() * distanceFromOriginLog); // commented out by GV, July 7th
                //alternative.AddUtilityTerm(278, person.IsChildUnder16.ToFlag() * distanceFromOriginLog); // commented out by GV, July 7th
                alternative.AddUtilityTerm(279, person.IsUniversityStudent.ToFlag() * distanceFromOriginLog);

                //GV: 17. june 2015 male commented out
                //alternative.AddUtilityTerm(280, person.IsAdultMale.ToFlag() * distanceFromOriginLog);
                alternative.AddUtilityTerm(281, person.IsAdultFemale.ToFlag() * distanceFromOriginLog);

                alternative.AddUtilityTerm(282, person.IsRetiredAdult.ToFlag() * distanceFromOriginLog);

                //alternative.AddUtilityTerm(283, (tour.IsHomeBasedTour).ToFlag() * timePressure); //commented out by GV: 7th July 2013
                alternative.AddUtilityTerm(284, (tour.IsHomeBasedTour).ToFlag() * distanceFromSchoolLog);
                //alternative.AddUtilityTerm(14, distanceFromWorkLog);

                // GV commented out this - on TO DO list
                //alternative.AddUtilityTerm(277, (carCompetitionFlag + noCarCompetitionFlag) * destinationParcel.ParkingHourlyEmploymentCommercialMixInParcel());
                //alternative.AddUtilityTerm(278, noCarCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixInParcel());
                //alternative.AddUtilityTerm(279, carCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixBuffer1());
                //alternative.AddUtilityTerm(280, noCarCompetitionFlag * destinationParcel.ParkingHourlyEmploymentCommercialMixBuffer1());
                //alternative.AddUtilityTerm(281, noCarsFlag * c34Ratio);
                //alternative.AddUtilityTerm(282, noCarCompetitionFlag * c34Ratio);
                //alternative.AddUtilityTerm(283, (carCompetitionFlag + noCarCompetitionFlag) * logOfOnePlusParkingOffStreetDailySpacesBuffer1);


                //alternative.AddUtilityTerm(285, jointTourFlag * piecewiseDistanceFrom0To1Km);
                //alternative.AddUtilityTerm(286, jointTourFlag * piecewiseDistanceFrom1To2Km);
                alternative.AddUtilityTerm(286, jointTourFlag * piecewiseDistanceFrom0To2Km);
                alternative.AddUtilityTerm(287, jointTourFlag * piecewiseDistanceFrom2To5Km);
                alternative.AddUtilityTerm(288, jointTourFlag * piecewiseDistanceFrom5To10Km);
                alternative.AddUtilityTerm(289, jointTourFlag * piecewiseDistanceFrom10To20Km);
                alternative.AddUtilityTerm(290, jointTourFlag * piecewiseDistanceFrom20KmToInfinity);
                // 3. finished


                //4. new from GV: purpose utilities
                // COMPAS puposes are: Work, Education, Escort, Shopping, Leisure, Personal business, business
                // You need NO "Work" and "Education", their destinations are known in the synthetic population
                if (tour.DestinationPurpose == Global.Settings.Purposes.Business)
                {
                    //alternative.AddUtilityTerm(10, piecewiseDistanceFrom0To1Km);
                    //alternative.AddUtilityTerm(11, piecewiseDistanceFrom1To2Km);
                    //alternative.AddUtilityTerm(12, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(12, piecewiseDistanceFrom0To5Km);
                    alternative.AddUtilityTerm(13, piecewiseDistanceFrom5To10Km);
                    alternative.AddUtilityTerm(14, piecewiseDistanceFrom10To20Km);
                    alternative.AddUtilityTerm(15, piecewiseDistanceFrom20KmToInfinity);

                    //GV: june 2016 - not sign
                    //alternative.AddUtilityTerm(16, aggregateLogsumWorkBased);

                    // Neighborhood
                    //GV: commented out just temp.
                    //alternative.AddUtilityTerm(20, logOfOnePlusEducationK8Buffer2);
                    //alternative.AddUtilityTerm(21, logOfOnePlusEducationUniStuBuffer2);
                    //alternative.AddUtilityTerm(22, logOfOnePlusEmploymentEducationBuffer2);
                    alternative.AddUtilityTerm(23, logOfOnePlusEmploymentGovernmentBuffer2);
                    //alternative.AddUtilityTerm(24, logOfOnePlusEmploymentIndustrialBuffer2);
                    //alternative.AddUtilityTerm(25, logOfOnePlusEmploymentOfficeBuffer2);
                    //alternative.AddUtilityTerm(26, logOfOnePlusEmploymentRetailBuffer2);
                    alternative.AddUtilityTerm(27, logOfOnePlusEmploymentServiceBuffer2);
                    //alternative.AddUtilityTerm(28, logOfOnePlusEmploymentAgrConstrBuffer2);
                    //alternative.AddUtilityTerm(29, logOfOnePlusEmploymentJobsBuffer2);

                    // Size terms
                    alternative.AddUtilityTerm(30, destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(31, destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(32, destinationParcel.EmploymentIndustrial);
                    alternative.AddUtilityTerm(33, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(34, destinationParcel.EmploymentRetail);
                    // GV: 35 is fixed to zero
                    alternative.AddUtilityTerm(35, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(36, destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(37, destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(38, destinationParcel.Households);
                }
                else if (tour.DestinationPurpose == Global.Settings.Purposes.Escort)
                {
                    //alternative.AddUtilityTerm(50, piecewiseDistanceFrom0To1Km);
                    alternative.AddUtilityTerm(51, piecewiseDistanceFrom0To2Km);
                    //alternative.AddUtilityTerm(52, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(52, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(53, piecewiseDistanceFrom5To10Km);
                    //alternative.AddUtilityTerm(54, piecewiseDistanceFrom10To20Km);
                    alternative.AddUtilityTerm(55, piecewiseDistanceFrom10KmToInfinity);
                    //alternative.AddUtilityTerm(55, piecewiseDistanceFrom20KmToInfinity);

                    //GV: june 2016 - not sign
                    //alternative.AddUtilityTerm(56, aggregateLogsumHomeBased);

                    // Neighborhood
                    //GV: commented out just temp.
                    alternative.AddUtilityTerm(60, householdHasNoChildren.ToFlag() * logOfOnePlusEmploymentJobsBuffer2);
                    //alternative.AddUtilityTerm(61, householdHasNoChildren.ToFlag() * logOfOnePlusHouseholdsBuffer2);
                    //alternative.AddUtilityTerm(62, householdHasChildren.ToFlag() * logOfOnePlusHouseholdsBuffer2);
                    //alternative.AddUtilityTerm(64, logOfOnePlusEmploymentJobsBuffer2);

                    // Size terms
                    // GV: no observations
                    alternative.AddUtilityTerm(70, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(71, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(72, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentIndustrial);
                    alternative.AddUtilityTerm(73, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(74, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentRetail);
                    // GV: 75 is fixed to zero
                    alternative.AddUtilityTerm(75, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(76, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(77, (!householdHasChildren).ToFlag() * destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(78, (!householdHasChildren).ToFlag() * destinationParcel.Households);

                    alternative.AddUtilityTerm(80, (householdHasChildren).ToFlag() * destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(81, (householdHasChildren).ToFlag() * destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(82, (householdHasChildren).ToFlag() * destinationParcel.EmploymentIndustrial);
                    alternative.AddUtilityTerm(83, (householdHasChildren).ToFlag() * destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(84, (householdHasChildren).ToFlag() * destinationParcel.EmploymentRetail);
                    // GV 85 is fixed to zero at the moment
                    alternative.AddUtilityTerm(85, (householdHasChildren).ToFlag() * destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(86, (householdHasChildren).ToFlag() * destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(87, (householdHasChildren).ToFlag() * destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(88, (householdHasChildren).ToFlag() * destinationParcel.Households);
                }
                else if (tour.DestinationPurpose == Global.Settings.Purposes.PersonalBusiness)
                {
                    alternative.AddUtilityTerm(90, piecewiseDistanceFrom0To2Km);
                    //alternative.AddUtilityTerm(91, piecewiseDistanceFrom1To2Km);
                    alternative.AddUtilityTerm(92, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(93, piecewiseDistanceFrom5To10Km);
                    alternative.AddUtilityTerm(95, piecewiseDistanceFrom10KmToInfinity);

                    //GV: june 2016 - not sign
                    //alternative.AddUtilityTerm(96, aggregateLogsumHomeBased);

                    // Neighborhood
                    //GV: commented out just temp.
                    //alternative.AddUtilityTerm(100, logOfOnePlusEmploymentEducationBuffer2);
                    //alternative.AddUtilityTerm(101, logOfOnePlusEmploymentGovernmentBuffer2);
                    //alternative.AddUtilityTerm(102, logOfOnePlusEmploymentIndustrialBuffer2);
                    alternative.AddUtilityTerm(103, logOfOnePlusEmploymentOfficeBuffer2);
                    alternative.AddUtilityTerm(104, logOfOnePlusEmploymentRetailBuffer2);
                    alternative.AddUtilityTerm(105, logOfOnePlusEmploymentServiceBuffer2);
                    //alternative.AddUtilityTerm(106, logOfOnePlusEmploymentAgrConstrBuffer2);
                    //alternative.AddUtilityTerm(107, logOfOnePlusEmploymentJobsBuffer2);

                    // Size terms
                    alternative.AddUtilityTerm(110, destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(111, destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(112, destinationParcel.EmploymentIndustrial);
                    alternative.AddUtilityTerm(113, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(114, destinationParcel.EmploymentRetail);
                    // GV 115 is fixed to zero
                    alternative.AddUtilityTerm(115, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(116, destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(117, destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(118, destinationParcel.Households);
                }
                else if (tour.DestinationPurpose == Global.Settings.Purposes.Shopping)
                {
                    //alternative.AddUtilityTerm(120, piecewiseDistanceFrom0To1Km);
                    alternative.AddUtilityTerm(121, piecewiseDistanceFrom0To2Km);
                    alternative.AddUtilityTerm(122, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(123, piecewiseDistanceFrom5To10Km);
                    alternative.AddUtilityTerm(124, piecewiseDistanceFrom10To20Km);
                    alternative.AddUtilityTerm(125, piecewiseDistanceFrom20KmToInfinity);

                    //GV: june 2016 - not sign
                    //alternative.AddUtilityTerm(126, aggregateLogsumHomeBased);

                    // Neighborhood
                    //GV: commented out just temp.
                    //alternative.AddUtilityTerm(130, logOfOnePlusEmploymentEducationBuffer2);
                    alternative.AddUtilityTerm(131, logOfOnePlusEmploymentRetailBuffer2);
                    //alternative.AddUtilityTerm(132, logOfOnePlusEmploymentJobsBuffer2);

                    // Size terms
                    alternative.AddUtilityTerm(140, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(141, destinationParcel.EmploymentRetail);
                    // GV 142 is fixed to zero
                    alternative.AddUtilityTerm(142, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(143, destinationParcel.EmploymentTotal);
                }
                else if (tour.DestinationPurpose == Global.Settings.Purposes.Social)
                {
                    //alternative.AddUtilityTerm(170, piecewiseDistanceFrom0To1Km);
                    //alternative.AddUtilityTerm(171, piecewiseDistanceFrom1To2Km);
                    alternative.AddUtilityTerm(170, piecewiseDistanceFrom0To2Km);
                    alternative.AddUtilityTerm(172, piecewiseDistanceFrom2To5Km);
                    alternative.AddUtilityTerm(173, piecewiseDistanceFrom5To10Km);
                    alternative.AddUtilityTerm(174, piecewiseDistanceFrom10To20Km);
                    alternative.AddUtilityTerm(175, piecewiseDistanceFrom20KmToInfinity);

                    //GV: june 2016 - not sign
                    //alternative.AddUtilityTerm(176, aggregateLogsumHomeBased);

                    // Neighborhood
                    //GV: commented out just temp.
                    //alternative.AddUtilityTerm(180, logOfOnePlusEmploymentOfficeBuffer2);
                    alternative.AddUtilityTerm(181, logOfOnePlusEmploymentRetailBuffer2);
                    alternative.AddUtilityTerm(182, logOfOnePlusEmploymentServiceBuffer2);
                    //alternative.AddUtilityTerm(183, logOfOnePlusEmploymentJobsBuffer2);

                    // Size terms
                    alternative.AddUtilityTerm(190, destinationParcel.EmploymentEducation);
                    alternative.AddUtilityTerm(191, destinationParcel.EmploymentGovernment);
                    alternative.AddUtilityTerm(192, destinationParcel.EmploymentIndustrial);
                    alternative.AddUtilityTerm(193, destinationParcel.EmploymentOffice);
                    alternative.AddUtilityTerm(194, destinationParcel.EmploymentRetail);
                    // GV 195 is fixed to zero
                    alternative.AddUtilityTerm(195, destinationParcel.EmploymentService);
                    alternative.AddUtilityTerm(196, destinationParcel.EmploymentAgricultureConstruction);
                    alternative.AddUtilityTerm(197, destinationParcel.EmploymentTotal);
                    alternative.AddUtilityTerm(198, destinationParcel.Households);
                }
            }
        }
Example #4
0
        public void Run(HouseholdDayWrapper householdDay, TourWrapper tour,
                        int constrainedMode, int constrainedArrivalTime, int constrainedDepartureTime)
        {
            if (tour == null)
            {
                throw new ArgumentNullException("tour");
            }

            //HTourModeTime.InitializeTourModeTimes();

            tour.PersonDay.ResetRandom(50 + tour.Sequence - 1);

            if (Global.Configuration.IsInEstimationMode)
            {
                if (Global.Configuration.EstimationModel != CHOICE_MODEL_NAME)
                {
                    return;
                }
                // JLB 20140421 add the following to keep from estimatign twice for the same tour
                if (tour.DestinationModeAndTimeHaveBeenSimulated)
                {
                    return;
                }
                if (tour.DestinationParcel == null || tour.OriginParcel == null || tour.Mode < Global.Settings.Modes.Walk || tour.Mode > Global.Settings.Modes.WalkRideBike)
                {
                    return;
                }
            }

            // set remaining inputs

            HTourModeTime.SetModeTimeImpedances(householdDay, tour, constrainedMode, constrainedArrivalTime, constrainedDepartureTime, -1, -1.0);

            var choiceProbabilityCalculator = _helpers[ParallelUtility.GetBatchFromThreadId()].GetChoiceProbabilityCalculator(tour.Id);

            if (_helpers[ParallelUtility.GetBatchFromThreadId()].ModelIsInEstimationMode)
            {
                var observedChoice = new HTourModeTime(tour.Mode, tour.DestinationArrivalTime, tour.DestinationDepartureTime);

                RunModel(choiceProbabilityCalculator, householdDay, tour, tour.DestinationParcel, tour.Household.VehiclesAvailable,
                         constrainedMode, constrainedArrivalTime, constrainedDepartureTime,
                         observedChoice);

                choiceProbabilityCalculator.WriteObservation();
            }
            else if (Global.Configuration.TestEstimationModelInApplicationMode)
            {
                Global.Configuration.IsInEstimationMode = false;

                RunModel(choiceProbabilityCalculator, householdDay, tour, tour.DestinationParcel, tour.Household.VehiclesAvailable,
                         constrainedMode, constrainedArrivalTime, constrainedDepartureTime);

                var observedChoice = new HTourModeTime(tour.Mode, tour.DestinationArrivalTime, tour.DestinationDepartureTime);

                var simulatedChoice = choiceProbabilityCalculator.SimulateChoice(tour.Household.RandomUtility, tour.Id, observedChoice.Index);

                Global.Configuration.IsInEstimationMode = true;
            }
            else
            {
                HTourModeTime choice;

                if (constrainedMode > 0 && constrainedArrivalTime > 0 && constrainedDepartureTime > 0)
                {
                    choice = new HTourModeTime(constrainedMode, constrainedArrivalTime, constrainedDepartureTime);
                }
                else
                {
                    RunModel(choiceProbabilityCalculator, householdDay, tour, tour.DestinationParcel, tour.Household.VehiclesAvailable,
                             constrainedMode, constrainedArrivalTime, constrainedDepartureTime);
                    var simulatedChoice = choiceProbabilityCalculator.SimulateChoice(tour.Household.RandomUtility);
                    if (simulatedChoice == null)
                    {
                        Global.PrintFile.WriteNoAlternativesAvailableWarning(CHOICE_MODEL_NAME, "Run", tour.PersonDay.Id);
                        if (!Global.Configuration.IsInEstimationMode)
                        {
                            tour.PersonDay.IsValid = false;
                            tour.PersonDay.HouseholdDay.IsValid = false;
                        }
                        return;
                    }
                    choice = (HTourModeTime)simulatedChoice.Choice;
                }
                if (Global.Configuration.TraceModelResultValidity)
                {
                    Global.PrintFile.WriteLine("  >> TourModeTimeModel HH/P/T/mode {0} {1} {2} {3}", tour.Household.Id, tour.Person.Sequence, tour.Sequence, choice.Mode);
                }
                tour.Mode = choice.Mode;
                tour.HalfTour1AccessCost         = choice.OriginAccessCost / 2.0;
                tour.HalfTour1AccessDistance     = choice.OriginAccessDistance / 2.0;
                tour.HalfTour1AccessMode         = choice.OriginAccessMode;
                tour.HalfTour1AccessStopAreaKey  = choice.ParkAndRideOriginStopAreaKey;
                tour.HalfTour1AccessTime         = choice.OriginAccessTime / 2.0;
                tour.HalfTour1EgressCost         = choice.DestinationAccessCost / 2.0;
                tour.HalfTour1EgressDistance     = choice.DestinationAccessDistance / 2.0;
                tour.HalfTour1EgressMode         = choice.DestinationAccessMode;
                tour.HalfTour1EgressStopAreaKey  = choice.ParkAndRideDestinationStopAreaKey;
                tour.HalfTour1EgressTime         = choice.DestinationAccessTime / 2.0;
                tour.HalfTour2AccessCost         = choice.DestinationAccessCost / 2.0;
                tour.HalfTour2AccessDistance     = choice.DestinationAccessDistance / 2.0;
                tour.HalfTour2AccessMode         = choice.DestinationAccessMode;
                tour.HalfTour2AccessStopAreaKey  = choice.ParkAndRideDestinationStopAreaKey;
                tour.HalfTour2AccessTime         = choice.DestinationAccessTime / 2.0;
                tour.HalfTour2EgressCost         = choice.OriginAccessCost / 2.0;
                tour.HalfTour2EgressDistance     = choice.OriginAccessDistance / 2.0;
                tour.HalfTour2EgressMode         = choice.OriginAccessMode;
                tour.HalfTour2EgressStopAreaKey  = choice.ParkAndRideOriginStopAreaKey;
                tour.HalfTour2EgressTime         = choice.OriginAccessTime / 2.0;
                tour.HalfTour1TravelTime         = choice.TravelTimeToDestination;
                tour.HalfTour2TravelTime         = choice.TravelTimeFromDestination;
                tour.TravelCostForPTBikeTour     = choice.PathCost;
                tour.TravelDistanceForPTBikeTour = choice.PathDistance;


                var arrivalPeriod   = choice.ArrivalPeriod;
                var departurePeriod = choice.DeparturePeriod;
                //use constrained times to set temporary arrival and departure times with minimum duration of stay for time window calculations
                if (constrainedArrivalTime > 0 || constrainedDepartureTime > 0)
                {
                    if (constrainedArrivalTime > 0)
                    {
                        tour.DestinationArrivalTime = constrainedArrivalTime;
                    }
                    else
                    {
                        tour.DestinationArrivalTime = Math.Min(arrivalPeriod.End, constrainedDepartureTime - Global.Settings.Times.MinimumActivityDuration);
                    }
                    if (constrainedDepartureTime > 0)
                    {
                        tour.DestinationDepartureTime = constrainedDepartureTime;
                    }
                    else
                    {
                        tour.DestinationDepartureTime = Math.Max(departurePeriod.Start, constrainedArrivalTime + Global.Settings.Times.MinimumActivityDuration);
                    }
                }
                //or if times aren't constrained use periods to set temporary arrival and departure times with minimum duration of stay for time window calculations
                else if (arrivalPeriod == departurePeriod)
                {
                    var departureTime = Math.Max(choice.GetRandomDepartureTime(householdDay, tour), departurePeriod.Start + Global.Settings.Times.MinimumActivityDuration);
                    tour.DestinationArrivalTime   = departureTime - Global.Settings.Times.MinimumActivityDuration;
                    tour.DestinationDepartureTime = departureTime;
                }
                else if (arrivalPeriod.End == departurePeriod.Start - 1)
                {
                    tour.DestinationArrivalTime   = arrivalPeriod.End;
                    tour.DestinationDepartureTime = arrivalPeriod.End + Global.Settings.Times.MinimumActivityDuration;
                }
                else
                {
                    tour.DestinationArrivalTime   = arrivalPeriod.End;
                    tour.DestinationDepartureTime = departurePeriod.Start;
                }
            }
        }
Example #5
0
        private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, HouseholdDayWrapper householdDay, TourWrapper tour,
                              IParcelWrapper destinationParcel, int householdCars,
                              int constrainedMode, int constrainedArrivalTime, int constrainedDepartureTime, HTourModeTime choice = null)
        {
            //private void RunModel(ChoiceProbabilityCalculator choiceProbabilityCalculator, HouseholdDayWrapper householdDay, TourWrapper tour,
            //			int constrainedMode, int constrainedArrivalTime, int constrainedDepartureTime, HTourModeTime choice = null) {

            var household       = tour.Household;
            var person          = tour.Person;
            var personDay       = tour.PersonDay;
            var householdTotals = household.HouseholdTotals;

            // household inputs
            var childrenUnder5        = householdTotals.ChildrenUnder5;
            var childrenAge5Through15 = householdTotals.ChildrenAge5Through15;
            var nonworkingAdults      = householdTotals.NonworkingAdults;
            var retiredAdults         = householdTotals.RetiredAdults;

            var onePersonHouseholdFlag = household.IsOnePersonHousehold.ToFlag();
            var twoPersonHouseholdFlag = household.IsTwoPersonHousehold.ToFlag();

            //var householdCars = household.VehiclesAvailable;
            var noCarsInHouseholdFlag   = household.GetFlagForNoCarsInHousehold(householdCars);
            var carsLessThanDriversFlag = household.GetFlagForCarsLessThanDrivers(householdCars);
            var carsLessThanWorkersFlag = household.GetFlagForCarsLessThanWorkers(householdCars);

            var HHwithChildrenFlag      = household.HasChildren.ToFlag();
            var HHwithSmallChildrenFlag = household.HasChildrenUnder5.ToFlag();
            var HHwithLowIncomeFlag     = (household.Income >= 300000 && household.Income < 600000).ToFlag();
            var HHwithMidleIncomeFlag   = (household.Income >= 600000 && household.Income < 900000).ToFlag();
            var HHwithHighIncomeFlag    = (household.Income >= 900000).ToFlag();

            var primaryFamilyTimeFlag = (householdDay == null) ? 0 : householdDay.PrimaryPriorityTimeFlag;

            // person inputs
            var partTimeWorkerFlag     = person.IsPartTimeWorker.ToFlag();
            var nonworkingAdultFlag    = person.IsNonworkingAdult.ToFlag();
            var universityStudentFlag  = person.IsUniversityStudent.ToFlag();
            var retiredAdultFlag       = person.IsRetiredAdult.ToFlag();
            var fullTimeWorkerFlag     = person.IsFulltimeWorker.ToFlag();
            var childAge5Through15Flag = person.IsChildAge5Through15.ToFlag();
            var childUnder5Flag        = person.IsChildUnder5.ToFlag();
            var adultFlag = person.IsAdult.ToFlag();

            var maleFlag   = person.IsMale.ToFlag();
            var femaleFlag = person.IsFemale.ToFlag();

            var PTpass = person.TransitPassOwnership;

            // person-day inputs
            var homeBasedToursOnlyFlag          = 1;
            var firstSimulatedHomeBasedTourFlag = 1;
            var laterSimulatedHomeBasedTourFlag = 0;
            var totalStops              = 0;
            var totalSimulatedStops     = 0;
            var escortStops             = 0;
            var homeBasedTours          = 1;
            var simulatedHomeBasedTours = 0;

            if (!(personDay == null))
            {
                homeBasedToursOnlyFlag          = personDay.OnlyHomeBasedToursExist().ToFlag();
                firstSimulatedHomeBasedTourFlag = personDay.IsFirstSimulatedHomeBasedTour().ToFlag();
                laterSimulatedHomeBasedTourFlag = personDay.IsLaterSimulatedHomeBasedTour().ToFlag();
                totalStops              = personDay.GetTotalStops();
                totalSimulatedStops     = personDay.GetTotalSimulatedStops();
                escortStops             = personDay.EscortStops;
                homeBasedTours          = personDay.HomeBasedTours;
                simulatedHomeBasedTours = personDay.SimulatedHomeBasedTours;
            }

            // tour inputs
            var escortTourFlag           = tour.IsEscortPurpose().ToFlag();
            var shoppingTourFlag         = tour.IsShoppingPurpose().ToFlag();
            var socialTourFlag           = tour.IsSocialPurpose().ToFlag();
            var personalBusinessTourFlag = tour.IsPersonalBusinessPurpose().ToFlag();
            var workTourFlag             = tour.IsWorkPurpose().ToFlag();
            var educationTourFlag        = tour.IsSchoolPurpose().ToFlag();
            var businessTourFlag         = tour.IsBusinessPurpose().ToFlag();

            var originParcel = tour.OriginParcel;
            //var destinationParcel = tour.DestinationParcel;
            var  jointTourFlag        = (tour.JointTourSequence > 0) ? 1 : 0;
            var  partialHalfTour1Flag = (tour.PartialHalfTour1Sequence > 0) ? 1 : 0;
            var  partialHalfTour2Flag = (tour.PartialHalfTour2Sequence > 0) ? 1 : 0;
            bool partialHalfTour      = (tour.PartialHalfTour1Sequence > 0 || tour.PartialHalfTour2Sequence > 0);
            var  fullHalfTour1Flag    = (tour.FullHalfTour1Sequence > 0) ? 1 : 0;
            var  fullHalfTour2Flag    = (tour.FullHalfTour2Sequence > 0) ? 1 : 0;


            // remaining inputs

            //Initialize a few variables in case personDay is null
            // Higher priority tour of 2+ tours for the same purpose
            var highPrioritySameFlag = 0;
            // Lower priority tour(s) of 2+ tours for the same purpose
            var lowPrioritySameFlag = 0;
            // Higher priority tour of 2+ tours for different purposes
            var highPriorityDifferentFlag = 0;
            // Lower priority tour of 2+ tours for different purposes
            var lowPriorityDifferentFlag = 0;

            if (!(personDay == null))
            {
                // Higher priority tour of 2+ tours for the same purpose
                highPrioritySameFlag = (tour.GetTotalToursByPurpose() > tour.GetTotalSimulatedToursByPurpose() && tour.GetTotalSimulatedToursByPurpose() == 1).ToFlag();
                // Lower priority tour(s) of 2+ tours for the same purpose
                lowPrioritySameFlag = (tour.GetTotalSimulatedToursByPurpose() > 1).ToFlag();
                // Higher priority tour of 2+ tours for different purposes
                highPriorityDifferentFlag = (personDay.IsFirstSimulatedHomeBasedTour() && personDay.HomeBasedToursExist()).ToFlag() * (1 - highPrioritySameFlag);
                // Lower priority tour of 2+ tours for different purposes
                lowPriorityDifferentFlag = (personDay.IsLaterSimulatedHomeBasedTour() && personDay.HomeBasedToursExist()).ToFlag() * (1 - lowPrioritySameFlag);
            }

            var timeWindow = (householdDay == null) ? new TimeWindow() : tour.GetRelevantTimeWindow(householdDay);
            var totalMinutesAvailableInDay = timeWindow.TotalAvailableMinutes(1, 1440);

            if (totalMinutesAvailableInDay < 0)
            {
                if (!Global.Configuration.IsInEstimationMode)
                {
                    householdDay.IsValid = false;
                }
                totalMinutesAvailableInDay = 0;
            }

            int bigPeriodCount = DayPeriod.H_BIG_DAY_PERIOD_TOTAL_TOUR_TIMES;
            int nPeriodCombs   = bigPeriodCount * (bigPeriodCount + 1) / 2;

            bool useTimeComponents = Global.Configuration.IsInEstimationMode || constrainedArrivalTime == 0 || constrainedDepartureTime == 0;
            int  componentIndex    = 0;
            int  periodComb        = -1;

            //set components
            if (useTimeComponents)
            {
                for (var arrivalPeriodIndex = 0; arrivalPeriodIndex < bigPeriodCount; arrivalPeriodIndex++)
                {
                    var arrivalPeriod = DayPeriod.HBigDayPeriods[arrivalPeriodIndex];
                    var arrivalPeriodAvailableMinutes = timeWindow.TotalAvailableMinutes(arrivalPeriod.Start, arrivalPeriod.End);

                    for (var departurePeriodIndex = arrivalPeriodIndex; departurePeriodIndex < bigPeriodCount; departurePeriodIndex++)
                    {
                        var departurePeriod = DayPeriod.HBigDayPeriods[departurePeriodIndex];
                        var departurePeriodAvailableMinutes = timeWindow.TotalAvailableMinutes(departurePeriod.Start, departurePeriod.End);

                        if (arrivalPeriod == departurePeriod)
                        {
                            componentIndex = arrivalPeriodIndex;
                            choiceProbabilityCalculator.CreateUtilityComponent(componentIndex);
                            var arrivalComponent = choiceProbabilityCalculator.GetUtilityComponent(componentIndex);

                            if (arrivalPeriodAvailableMinutes > 0)
                            {
                                var hoursArrival = arrivalPeriod.Middle / 60.0;
                                var firstCoef    = 300;
                                arrivalComponent.AddUtilityTerm(300, Math.Log(arrivalPeriodAvailableMinutes));
                                //arrival shift variables
                                arrivalComponent.AddUtilityTerm(firstCoef + 2, partTimeWorkerFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 3, nonworkingAdultFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 4, universityStudentFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 5, retiredAdultFlag * hoursArrival);

                                arrivalComponent.AddUtilityTerm(firstCoef + 6, childAge5Through15Flag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 7, childUnder5Flag * hoursArrival);

                                arrivalComponent.AddUtilityTerm(firstCoef + 8, educationTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 9, escortTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 10, shoppingTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 11, businessTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 12, personalBusinessTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 13, socialTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 14, workTourFlag * hoursArrival);

                                arrivalComponent.AddUtilityTerm(firstCoef + 15, primaryFamilyTimeFlag * hoursArrival);

                                arrivalComponent.AddUtilityTerm(firstCoef + 16, HHwithLowIncomeFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 17, HHwithMidleIncomeFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 18, HHwithHighIncomeFlag * hoursArrival);

                                arrivalComponent.AddUtilityTerm(firstCoef + 19, highPrioritySameFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 20, lowPrioritySameFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 21, highPriorityDifferentFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 22, lowPriorityDifferentFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 23, jointTourFlag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 24, partialHalfTour1Flag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 25, fullHalfTour1Flag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 26, partialHalfTour2Flag * hoursArrival);
                                arrivalComponent.AddUtilityTerm(firstCoef + 27, fullHalfTour2Flag * hoursArrival);
                            }

                            componentIndex = bigPeriodCount + departurePeriodIndex;
                            choiceProbabilityCalculator.CreateUtilityComponent(componentIndex);
                            var departureComponent = choiceProbabilityCalculator.GetUtilityComponent(componentIndex);


                            if (departurePeriodAvailableMinutes > 0)
                            {
                                departureComponent.AddUtilityTerm(300, Math.Log(departurePeriodAvailableMinutes));
                            }
                        }
                        // set period combination component
                        periodComb++;
                        componentIndex = 2 * bigPeriodCount + periodComb;
                        choiceProbabilityCalculator.CreateUtilityComponent(componentIndex);
                        var combinationComponent = choiceProbabilityCalculator.GetUtilityComponent(componentIndex);

                        if (arrivalPeriodAvailableMinutes > 0 && departurePeriodAvailableMinutes > 0)
                        {
                            var hoursDuration = (departurePeriod.Middle - arrivalPeriod.Middle) / 60.0;

                            var firstCoef = 700;
                            //combination constants
                            combinationComponent.AddUtilityTerm(firstCoef + periodComb, 1.0);
                            // duration shift variables
                            combinationComponent.AddUtilityTerm(firstCoef + 30, primaryFamilyTimeFlag * hoursDuration);

                            combinationComponent.AddUtilityTerm(firstCoef + 31, escortTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 32, shoppingTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 33, educationTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 34, socialTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 35, personalBusinessTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 36, businessTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 37, workTourFlag * hoursDuration);

                            combinationComponent.AddUtilityTerm(firstCoef + 38, highPrioritySameFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 39, lowPrioritySameFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 40, highPriorityDifferentFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 41, lowPriorityDifferentFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 42, partTimeWorkerFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 43, jointTourFlag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 44, partialHalfTour1Flag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 45, fullHalfTour1Flag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 46, partialHalfTour2Flag * hoursDuration);
                            combinationComponent.AddUtilityTerm(firstCoef + 47, fullHalfTour2Flag * hoursDuration);

                            // peak-to-peak variables
                            if (arrivalPeriod.Index == DayPeriod.AM_PEAK && departurePeriod.Index == DayPeriod.PM_PEAK)
                            {
                                combinationComponent.AddUtilityTerm(firstCoef + 48, fullTimeWorkerFlag);
                                combinationComponent.AddUtilityTerm(firstCoef + 49, partTimeWorkerFlag);
                                combinationComponent.AddUtilityTerm(firstCoef + 50, maleFlag);
                            }
                        }
                    }
                }
            }
            //for (var mode = Global.Settings.Modes.Walk; mode <= Global.Settings.Modes.WalkRideBike; mode++) {  replaced 20171120 JLB
            for (var mode = Global.Settings.Modes.Walk; mode <= Global.Settings.Modes.PaidRideShare; mode++)
            {
                componentIndex = 2 * bigPeriodCount + nPeriodCombs + mode - 1;
                choiceProbabilityCalculator.CreateUtilityComponent(componentIndex);
                var modeComponent = choiceProbabilityCalculator.GetUtilityComponent(componentIndex);

                //if (mode == Global.Settings.Modes.SchoolBus) {
                //	modeComponent.AddUtilityTerm(10, 1);
                //}
                if (mode == Global.Settings.Modes.Transit)
                {
                    modeComponent.AddUtilityTerm(20, 1);
                    modeComponent.AddUtilityTerm(21, femaleFlag);
                    //modeComponent.AddUtilityTerm(22, retiredAdultFlag);

                    modeComponent.AddUtilityTerm(22, PTpass);

                    //GV: one person HH; 8. juni 2016
                    //modeComponent.AddUtilityTerm(23, onePersonHouseholdFlag);

                    //GV: income effect is not with a correct sign
                    //modeComponent.AddUtilityTerm(23, HHwithLowIncomeFlag);
                    //modeComponent.AddUtilityTerm(24, HHwithMidleIncomeFlag);
                    //modeComponent.AddUtilityTerm(25, HHwithHighIncomeFlag);

                    //GV: not significant
                    //modeComponent.AddUtilityTerm(26, childrenUnder5);
                    //modeComponent.AddUtilityTerm(27, childrenAge5Through15);

                    modeComponent.AddUtilityTerm(28, nonworkingAdults + retiredAdults);

                    //modeComponent.AddUtilityTerm(26, noCarsInHouseholdFlag);
                    modeComponent.AddUtilityTerm(29, carsLessThanDriversFlag);
                }
                else if (mode == Global.Settings.Modes.Hov3)
                {
                    modeComponent.AddUtilityTerm(30, 1);
                    modeComponent.AddUtilityTerm(31, childrenUnder5);
                    modeComponent.AddUtilityTerm(32, childrenAge5Through15);
                    modeComponent.AddUtilityTerm(33, nonworkingAdults + retiredAdults);
                    modeComponent.AddUtilityTerm(34, femaleFlag);

                    //modeComponent.AddUtilityTerm(38, onePersonHouseholdFlag);
                    modeComponent.AddUtilityTerm(36, twoPersonHouseholdFlag);

                    //GV: commented out 7. june 2016
                    //modeComponent.AddUtilityTerm(37, noCarsInHouseholdFlag);
                    modeComponent.AddUtilityTerm(38, carsLessThanDriversFlag);
                }
                else if (mode == Global.Settings.Modes.Hov2)
                {
                    modeComponent.AddUtilityTerm(40, 1);
                    modeComponent.AddUtilityTerm(41, maleFlag);
                    //modeComponent.AddUtilityTerm(41, onePersonHouseholdFlag);

                    //GV: Testing coeff. 42-44 again, 26. may 2016, coeff. numbering changed
                    modeComponent.AddUtilityTerm(42, childrenUnder5);
                    modeComponent.AddUtilityTerm(43, childrenAge5Through15);
                    modeComponent.AddUtilityTerm(44, nonworkingAdults + retiredAdults);

                    //GV: these are significant and plus; 8. juni 2016
                    //modeComponent.AddUtilityTerm(45, HHwithLowIncomeFlag);
                    //modeComponent.AddUtilityTerm(46, HHwithMidleIncomeFlag);
                    //modeComponent.AddUtilityTerm(47, HHwithHighIncomeFlag);

                    //GV coeff. numbering changed; 8. june 2016 - not significant
                    //modeComponent.AddUtilityTerm(48, noCarsInHouseholdFlag);
                    //modeComponent.AddUtilityTerm(49, carsLessThanDriversFlag);
                }
                else if (mode == Global.Settings.Modes.Sov)
                {
                    modeComponent.AddUtilityTerm(50, 1);
                    //not significant: modeComponent.AddUtilityTerm(51, maleFlag);
                    modeComponent.AddUtilityTerm(52, fullTimeWorkerFlag);
                    modeComponent.AddUtilityTerm(53, partTimeWorkerFlag);
                    modeComponent.AddUtilityTerm(54, onePersonHouseholdFlag);

                    //GV: these are NOT significant
                    //modeComponent.AddUtilityTerm(55, HHwithLowIncomeFlag);
                    //modeComponent.AddUtilityTerm(56, HHwithMidleIncomeFlag);
                    //modeComponent.AddUtilityTerm(57, HHwithHighIncomeFlag);

                    //GV: coeff. numbering changed, 26. may 2016
                    modeComponent.AddUtilityTerm(58, carsLessThanWorkersFlag);
                }
                else if (mode == Global.Settings.Modes.Bike)
                {
                    modeComponent.AddUtilityTerm(60, 1);
                    modeComponent.AddUtilityTerm(61, femaleFlag);
                    //modeComponent.AddUtilityTerm(62, childrenUnder5);
                    //GV: changed small kids to retired; 3. june 2016
                    modeComponent.AddUtilityTerm(62, retiredAdults);
                    modeComponent.AddUtilityTerm(63, childAge5Through15Flag);

                    //GV: 3. june 2016 - added "no cars in HH" for full/part_time workers
                    modeComponent.AddUtilityTerm(64, fullTimeWorkerFlag + noCarsInHouseholdFlag);
                    modeComponent.AddUtilityTerm(65, partTimeWorkerFlag + noCarsInHouseholdFlag);

                    //modeComponent.AddUtilityTerm(66, noCarsInHouseholdFlag);
                    modeComponent.AddUtilityTerm(67, carsLessThanDriversFlag);

                    //GV: university students; 3. june 2016 - not significant
                    //modeComponent.AddUtilityTerm(68, universityStudentFlag);

                    //GV: one person HH; 8. juni 2016
                    modeComponent.AddUtilityTerm(69, onePersonHouseholdFlag);
                }
                else if (mode == Global.Settings.Modes.Walk)
                {
                    modeComponent.AddUtilityTerm(70, 1.0);
                    //GV: Testing female variable again; 26. may 2016 - not sign.
                    //modeComponent.AddUtilityTerm(71, femaleFlag);
                    modeComponent.AddUtilityTerm(72, nonworkingAdults);
                    //not sign.: modeComponent.AddUtilityTerm(73, retiredAdults);

                    //GV: one person HH
                    modeComponent.AddUtilityTerm(74, onePersonHouseholdFlag);

                    //GV: not significant
                    //modeComponent.AddUtilityTerm(76, noCarsInHouseholdFlag);
                    //modeComponent.AddUtilityTerm(77, carsLessThanDriversFlag);
                }
                else if (mode == Global.Settings.Modes.ParkAndRide)
                {
                    modeComponent.AddUtilityTerm(80, 1.0);
                }
                else if (mode == Global.Settings.Modes.CarKissRideWalk)
                {
                    modeComponent.AddUtilityTerm(90, 1.0);
                }
                else if (mode == Global.Settings.Modes.BikeParkRideWalk)
                {
                    modeComponent.AddUtilityTerm(100, 1.0);
                }
                else if (mode == Global.Settings.Modes.BikeParkRideBike)
                {
                    modeComponent.AddUtilityTerm(110, 1.0);
                }
                else if (mode == Global.Settings.Modes.BikeOnTransit)
                {
                    modeComponent.AddUtilityTerm(120, 1.0);
                }
                else if (mode == Global.Settings.Modes.CarParkRideBike)
                {
                    modeComponent.AddUtilityTerm(130, 1.0);
                }
                else if (mode == Global.Settings.Modes.WalkRideBike)
                {
                    modeComponent.AddUtilityTerm(140, 1.0);
                }
                else if (mode == Global.Settings.Modes.PaidRideShare)
                {
                    //modeComponent.AddUtilityTerm(150, 1.0);

                    var modeConstant = Global.Configuration.AV_PaidRideShareModeUsesAVs
                                         ? Global.Configuration.AV_PaidRideShare_ModeConstant
                                       + Global.Configuration.AV_PaidRideShare_DensityCoefficient * Math.Min(originParcel.HouseholdsBuffer2 + originParcel.StudentsUniversityBuffer2 + originParcel.EmploymentTotalBuffer2, 6000)
                                       + Global.Configuration.AV_PaidRideShare_AVOwnerCoefficient * (household.OwnsAutomatedVehicles > 0).ToFlag()
                                         : Global.Configuration.PaidRideShare_ModeConstant
                                       + Global.Configuration.PaidRideShare_DensityCoefficient * Math.Min(originParcel.HouseholdsBuffer2 + originParcel.StudentsUniversityBuffer2 + originParcel.EmploymentTotalBuffer2, 6000);

                    modeComponent.AddUtilityTerm(150, modeConstant);
                    modeComponent.AddUtilityTerm(150, Global.Configuration.PaidRideShare_Age26to35Coefficient * tour.Person.AgeIsBetween26And35.ToFlag());
                    modeComponent.AddUtilityTerm(150, Global.Configuration.PaidRideShare_Age18to25Coefficient * tour.Person.AgeIsBetween18And25.ToFlag());
                    modeComponent.AddUtilityTerm(150, Global.Configuration.PaidRideShare_AgeOver65Coefficient * (tour.Person.Age >= 65).ToFlag());
                }


                //GV: Estimation of importance of "purpose" per mode - SOV is zero-alt and Work is zero-alt
                if (mode == Global.Settings.Modes.Walk || mode == Global.Settings.Modes.Bike || mode == Global.Settings.Modes.Hov2 ||
                    mode == Global.Settings.Modes.Hov3 || mode == Global.Settings.Modes.Transit)
                {
                    var firstCoef = 200 + 10 * mode;

                    modeComponent.AddUtilityTerm(firstCoef + 0, escortTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 1, shoppingTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 2, educationTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 3, socialTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 4, personalBusinessTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 5, businessTourFlag);
                    //modeComponent.AddUtilityTerm(firstCoef + 6, workTourFlag); //GV: "work" is zero alternative

                    modeComponent.AddUtilityTerm(firstCoef + 7, jointTourFlag);
                    modeComponent.AddUtilityTerm(firstCoef + 8, Math.Min(partialHalfTour1Flag + partialHalfTour2Flag, 1.0));
                    modeComponent.AddUtilityTerm(firstCoef + 9, Math.Min(fullHalfTour1Flag + fullHalfTour2Flag, 1.0));
                }
            }



            //loop on all alternatives, using modeTimes objects
            {
                foreach (var modeTimes in HTourModeTime.ModeTimes[ParallelUtility.GetBatchFromThreadId()])
                {
                    var arrivalPeriod = modeTimes.ArrivalPeriod;
                    var arrivalPeriodAvailableMinutes = timeWindow.TotalAvailableMinutes(arrivalPeriod.Start, arrivalPeriod.End);

                    var departurePeriod = modeTimes.DeparturePeriod;
                    var departurePeriodAvailableMinutes = timeWindow.TotalAvailableMinutes(departurePeriod.Start, departurePeriod.End);
                    periodComb = modeTimes.PeriodCombinationIndex;

                    var mode = modeTimes.Mode;

                    var altIndex = modeTimes.Index;



                    //limit availability based on mode and tour purpose
                    bool available = (mode == Global.Settings.Modes.BikeParkRideBike || mode == Global.Settings.Modes.CarParkRideBike || mode == Global.Settings.Modes.WalkRideBike) &&
                                     (!(tour.IsWorkPurpose() || tour.IsSchoolPurpose())) ? false : true;

                    //further limit availability on mode
                    if (mode == Global.Settings.Modes.PaidRideShare && !Global.Configuration.PaidRideShareModeIsAvailable)
                    {
                        available = false;
                    }

                    //further limit availability if tour includes joint travel
                    if ((tour.JointTourSequence > 0 ||
                         tour.FullHalfTour1Sequence > 0 || tour.FullHalfTour2Sequence > 0 ||
                         tour.PartialHalfTour1Sequence > 0 || tour.PartialHalfTour2Sequence > 0) &&
                        (mode > Global.Settings.Modes.Transit))
                    {
                        available = false;
                    }

                    //further limit availability:  kissAndRide and carParkRideBike are not supported
                    available = (available == true) && (mode != Global.Settings.Modes.CarKissRideWalk) && (mode != Global.Settings.Modes.CarParkRideBike);

                    //further limit availabillity based on time window variables and any constrained choices
                    available = (available == true) &&
                                (modeTimes.LongestFeasibleWindow != null) && (mode > 0)
                                //&& (mode <= Global.Settings.Modes.Transit)
                                && (person.Age >= 18 || (modeTimes.Mode != Global.Settings.Modes.Sov && modeTimes.Mode != Global.Settings.Modes.HovDriver)) &&
                                (constrainedMode > 0 || mode == Global.Settings.Modes.Walk || mode == Global.Settings.Modes.Bike || mode == Global.Settings.Modes.HovDriver || mode == Global.Settings.Modes.Transit || !partialHalfTour) &&
                                (constrainedMode <= 0 || constrainedMode == mode) &&
                                (constrainedArrivalTime <= 0 || (constrainedArrivalTime >= arrivalPeriod.Start && constrainedArrivalTime <= arrivalPeriod.End)) &&
                                (constrainedDepartureTime <= 0 || (constrainedDepartureTime >= departurePeriod.Start && constrainedDepartureTime <= departurePeriod.End));

                    var alternative = choiceProbabilityCalculator.GetAlternative(altIndex, available,
                                                                                 choice != null && choice.Index == altIndex);

                    alternative.Choice = modeTimes;                     // JLB added 20130420

                    //alternative.AddNestedAlternative(HTourModeTime.TOTAL_TOUR_MODE_TIMES + periodComb + 1, periodComb, THETA_PARAMETER);
                    alternative.AddNestedAlternative(HTourModeTime.TotalTourModeTimes + mode, mode - 1, THETA_PARAMETER);

                    //if (Global.Configuration.IsInEstimationMode && altIndex == choice.Index) {
                    //	Global.PrintFile.WriteLine("Aper Dper Mode {0} {1} {2} Travel Times {3} {4} Window {5} {6}",
                    //										arrivalPeriod.Index, departurePeriod.Index, mode,
                    //										modeTimes.ModeAvailableToDestination ? modeTimes.TravelTimeToDestination : -1,
                    //										modeTimes.ModeAvailableFromDestination ? modeTimes.TravelTimeFromDestination : -1,
                    //										modeTimes.LongestFeasibleWindow != null ? modeTimes.LongestFeasibleWindow.Start : -1,
                    //										modeTimes.LongestFeasibleWindow != null ? modeTimes.LongestFeasibleWindow.End : -1);

                    //}
                    //Following code was used to test handling of partially joint half tours (JLB 20140603)
                    //if (partialHalfTour) {
                    //	Global.PrintFile.WriteLine("HH pers {0} {1} avail {2} Aper Dper Mode {3} {4} {5} Travel Times {6} {7} Window {8} {9}",
                    //	   household.Id, person.Sequence,
                    //    available,
                    //		arrivalPeriod.Index, departurePeriod.Index, mode,
                    //	                           modeTimes.ModeAvailableToDestination ? modeTimes.TravelTimeToDestination : -1,
                    //	                           modeTimes.ModeAvailableFromDestination ? modeTimes.TravelTimeFromDestination : -1,
                    //	                           modeTimes.LongestFeasibleWindow != null ? modeTimes.LongestFeasibleWindow.Start : -1,
                    //	                           modeTimes.LongestFeasibleWindow != null ? modeTimes.LongestFeasibleWindow.End : -1);
                    //}

                    //if in application mode and combination is not available, can skip the rest
                    if (!Global.Configuration.IsInEstimationMode && !alternative.Available)
                    {
                        continue;
                    }
                    if (useTimeComponents)
                    {
                        // arrival period utility component
                        alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(arrivalPeriod.Index));

                        // departure period utility component
                        alternative.AddUtilityComponent(
                            choiceProbabilityCalculator.GetUtilityComponent(bigPeriodCount + departurePeriod.Index));

                        // period combination utility component
                        alternative.AddUtilityComponent(choiceProbabilityCalculator.GetUtilityComponent(2 * bigPeriodCount + periodComb));
                    }

                    // mode utility component
                    alternative.AddUtilityComponent(
                        choiceProbabilityCalculator.GetUtilityComponent(2 * bigPeriodCount + nPeriodCombs + mode - 1));

                    //even in estimation mode, do not need the rest of the code if not available
                    if (!alternative.Available)
                    {
                        continue;
                    }

                    //GV and JB: the parking cost are handled as part of genaralised time

                    var minimumTimeNeeded = modeTimes.TravelTimeToDestination + modeTimes.TravelTimeFromDestination + Global.Settings.Times.MinimumActivityDuration;

                    alternative.AddUtilityTerm(1, modeTimes.GeneralizedTimeToDestination + modeTimes.GeneralizedTimeFromDestination);

                    //alternative.AddUtilityTerm(3,
                    //                           Math.Log(modeTimes.LongestFeasibleWindow.End - modeTimes.LongestFeasibleWindow.Start -
                    //                                    minimumTimeNeeded + 1.0));

                    // JLB 20140204 replaced coeff 3 with a different time window formulation:  time pressure
                    //    instead of having positive utility for increasing time window, have negative utility for decreasing time window
                    alternative.AddUtilityTerm(3,
                                               Math.Log(Math.Max(Constants.EPSILON, 1 -
                                                                 Math.Pow(minimumTimeNeeded / (Math.Min(840, modeTimes.LongestFeasibleWindow.End - modeTimes.LongestFeasibleWindow.Start)), 0.8)
                                                                 )));



                    alternative.AddUtilityTerm(4, Math.Log((totalMinutesAvailableInDay + 1.0) / (minimumTimeNeeded + 1.0)));

                    alternative.AddUtilityTerm(5,
                                               (maleFlag == 0 && mode == Global.Settings.Modes.Walk &&
                                                arrivalPeriod.Index >= DayPeriod.EVENING)
                                                                                                                        ? 1
                                                                                                                        : 0);

                    if (altIndex == 0)
                    {
                        alternative.AddUtilityTerm(998, tour.DestinationPurpose);
                        alternative.AddUtilityTerm(999, (tour.ParentTour == null) ? 0 : 1);
                    }
                }
            }
        }