private static void GenerateWorkBusinessEpisode(ITashaPerson person, Schedule workSchedule, Random random, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { int freqB = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random, householdPD, workPD, generationAdjustments); for (int i = 0; i < freqB; i++) { for (int attempt = 0; attempt < Scheduler.EpisodeSchedulingAttempts; attempt++) { if (!TimeTable.GetStartTime(person, Activity.WorkBasedBusiness, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(person, Activity.WorkBasedBusiness, startTime, random, out Time duration)) { continue; } var endTime = startTime + duration; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } Episode workEpisode = new ActivityEpisode(new TimeWindow(startTime, startTime + duration), Activity.WorkBasedBusiness, person); workSchedule.Insert(workEpisode, random); break; } } }
private static void ProcessWorkBusiness(ITashaPerson person, Schedule workSchedule, Random random, Episode primWorkEpisode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { Time startTime = primWorkEpisode.StartTime; Time endTime = primWorkEpisode.EndTime; int freq = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random, Scheduler.MaxFrequency, startTime, endTime, householdPD, workPD, generationAdjustments); for (int i = 0; i < freq; i++) { var attempt = 0; while (attempt < Scheduler.EpisodeSchedulingAttempts) { attempt++; if (!TimeTable.GetStartTime(person, Activity.WorkBasedBusiness, freq, startTime, endTime, random, out Time startTimeB)) { continue; } if (!TimeTable.GetDuration(person, Activity.WorkBasedBusiness, startTimeB, endTime - startTimeB, random, out Time durationB)) { continue; } Episode businessEpisode; businessEpisode = new ActivityEpisode(new TimeWindow(startTimeB, startTimeB + durationB), Activity.WorkBasedBusiness, person); if (workSchedule.Insert(businessEpisode, random)) { break; } } } }
internal static void AddHouseholdProjects(this ITashaHousehold household, Schedule schedule, Random random) { for (int i = 0; i < schedule.EpisodeCount; i++) { var episode = (Episode)schedule.Episodes[i]; episode.ContainingSchedule = schedule; var people = episode.People; if (people != null) { bool first = true; IZone zone = null; foreach (var person in people) { var pData = (SchedulerPersonData)person["SData"]; //var check = pData.Schedule.EpisodeCount > 0; var ep = new ActivityEpisode(new TimeWindow(episode.StartTime, episode.EndTime) /*window*/, schedule.Episodes[i].ActivityType, person); if (first) { pData.Schedule.Insert(ep, random); zone = ep.Zone; first = false; } else { pData.Schedule.Insert(ep, zone); pData.Schedule.CheckEpisodeIntegrity(); } } } } }
internal static void AddHouseholdProjects(this ITashaHousehold household, Schedule schedule, Random random) { for ( int i = 0; i < schedule.EpisodeCount; i++ ) { var episode = (Episode)schedule.Episodes[i]; episode.ContainingSchedule = schedule; var people = episode.People; if ( people != null ) { bool first = true; IZone zone = null; foreach ( var person in people ) { var pData = person["SData"] as SchedulerPersonData; //var check = pData.Schedule.EpisodeCount > 0; var ep = new ActivityEpisode( 0, new TimeWindow( episode.StartTime, episode.EndTime ) /*window*/, schedule.Episodes[i].ActivityType, person ); if ( first ) { pData.Schedule.Insert( ep, random ); zone = ep.Zone; first = false; } else { pData.Schedule.Insert( ep, zone ); pData.Schedule.CheckEpisodeIntegrity(); } } } } }
/// <summary> /// Return home from work creates a return home from work activity (return home from work may involve /// going to lunch at home or going to check up on something in the house during work). /// </summary> /// <param name="person"></param> /// <param name="schedule"></param> /// <param name="episode"></param> /// <returns></returns> private static bool ProcessReturnHomeFromWork(ITashaPerson person, Schedule schedule, Random random, Episode episode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { int freq = 0; //the current work schedule doesn't allow for a return from work activity if (episode.StartTime > Scheduler.MaxPrimeWorkStartTimeForReturnHomeFromWork || episode.Duration < Scheduler.MinPrimaryWorkDurationForReturnHomeFromWork) { return(false); } //End time of work to home activity Time endTime = episode.EndTime + new Time(0.3f) < Scheduler.ReturnHomeFromWorkMaxEndTime ? episode.EndTime + new Time(0.3f) : Scheduler.ReturnHomeFromWorkMaxEndTime; freq = TimeTable.GetFrequency(person, Activity.ReturnFromWork, random, 1, episode.StartTime + new Time(0.3f), endTime, householdPD, workPD, generationAdjustments); if (freq == 1) { IZone homeZone = person.Household.HomeZone; Time HalfAnHour = new Time() { Minutes = 30 }; Time MaxEndTime = ((episode.EndTime - HalfAnHour) < Scheduler.ReturnHomeFromWorkMaxEndTime) ? (episode.EndTime - HalfAnHour) : Scheduler.ReturnHomeFromWorkMaxEndTime; Time startTime; if (!TimeTable.GetStartTime(person, Activity.ReturnFromWork , freq , episode.StartTime + HalfAnHour , MaxEndTime, random, out startTime)) { return(false); } Time maxDuration = new Time(Math.Min((Scheduler.ReturnHomeFromWorkMaxEndTime - Time.OneHour).ToFloat(), (episode.EndTime - HalfAnHour - startTime).ToFloat())); Time duration; if (!TimeTable.GetDuration(person, Activity.ReturnFromWork, startTime, maxDuration, random, out duration)) { // reject return(false); } Episode returnFromWorkEpisode; returnFromWorkEpisode = new ActivityEpisode(0, new TimeWindow(startTime, startTime + duration), Activity.ReturnFromWork, person); returnFromWorkEpisode.Zone = homeZone; schedule.Insert(returnFromWorkEpisode, random); } return(true); }
private void AssignEpisodes(ITashaPerson person, ref Time workStartTime, ref Time workEndTime, Random random) { person.InitializePersonalProjects(); var personData = (SchedulerPersonData)person["SData"]; foreach (var tripChain in person.TripChains) { for (int j = 0; j < (tripChain.Trips.Count - 1); j++) { var thisTrip = tripChain.Trips[j]; var nextTrip = tripChain.Trips[j + 1]; thisTrip.Mode = thisTrip[ObservedMode] as ITashaMode; nextTrip.Mode = nextTrip[ObservedMode] as ITashaMode; var startTime = thisTrip.OriginalZone == null || thisTrip.DestinationZone == null ? thisTrip.TripStartTime : thisTrip.ActivityStartTime; var endTime = nextTrip.TripStartTime; var duration = endTime - startTime; if (duration < Time.Zero) { endTime = Time.EndOfDay; } if (endTime < startTime) { startTime = thisTrip.TripStartTime; } if (thisTrip.Purpose == Activity.PrimaryWork || thisTrip.Purpose == Activity.SecondaryWork || thisTrip.Purpose == Activity.WorkBasedBusiness) { var newEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), thisTrip.Purpose, person) { Zone = thisTrip.DestinationZone }; if (thisTrip.Purpose == Activity.PrimaryWork || thisTrip.Purpose == Activity.WorkBasedBusiness) { if (workStartTime == Time.Zero || newEpisode.StartTime < workStartTime) { workStartTime = newEpisode.StartTime; } if (workEndTime == Time.Zero || newEpisode.EndTime > workEndTime) { workEndTime = newEpisode.EndTime; } } personData.WorkSchedule.Schedule.Insert(newEpisode, random); } if (thisTrip.Purpose == Activity.School) { var newEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), thisTrip.Purpose, person) { Zone = thisTrip.DestinationZone }; personData.SchoolSchedule.Schedule.Insert(newEpisode, random); } } } }
/// <summary> /// Secondary work creates a secondary work activity for person /// </summary> /// <param name="person"></param> /// <param name="schedule"></param> /// <param name="random"></param> /// <param name="primaryWorkEpisode"></param> /// <param name="householdPD"></param> /// <param name="workPD"></param> /// <param name="generationAdjustments"></param> private static void ProcessSecondaryWork(ITashaPerson person, Schedule schedule, Random random, Episode primaryWorkEpisode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { if (random == null) { throw new ArgumentNullException(nameof(random)); } //can only work if finish primary work by 7:00PM if (primaryWorkEpisode.EndTime < Scheduler.SecondaryWorkThreshold) { int freqR; //getting earliest possible startTime Time hourAfterWork = primaryWorkEpisode.EndTime + Time.OneHour; Time minStartTime = hourAfterWork > Scheduler.SecondaryWorkMinStartTime ? hourAfterWork : Scheduler.SecondaryWorkMinStartTime; freqR = TimeTable.GetFrequency(person, Activity.SecondaryWork, random, 10, minStartTime, Time.EndOfDay, householdPD, workPD, generationAdjustments); for (int i = 0; i < freqR; i++) { //zone same as work zone IZone zone = primaryWorkEpisode.Zone.ZoneNumber == Scheduler.Tasha.ZoneSystem.RoamingZoneNumber ? Scheduler.LocationChoiceModel.GetLocationHomeBased(Activity.SecondaryWork, person.Household.HomeZone, random) : primaryWorkEpisode.Zone; if (!TimeTable.GetStartTime(person, primaryWorkEpisode.ActivityType, freqR, minStartTime, Time.EndOfDay, random, out Time startTimeR)) { //TODO: We might want to reconsider this, skipping instead of just throwing an exception //throw new XTMFRuntimeException("Unable to find a start time for a primary work episode"); return; } if (!TimeTable.GetDuration(person, Activity.SecondaryWork, startTimeR, Time.EndOfDay - startTimeR, random, out Time durationR)) { //throw new XTMFRuntimeException("Unable to find a duration for a primary work episode"); return; } //inserting secondary work into schedule Episode secondaryWorkEpisode; secondaryWorkEpisode = new ActivityEpisode(new TimeWindow(startTimeR, startTimeR + durationR), Activity.SecondaryWork, person) { Zone = zone }; schedule.Insert(secondaryWorkEpisode, random); } } }
private void AssignWorkSchoolEpisodes(ITashaPerson person, out Time workStartTime, out Time workEndTime, Random random) { var PersonData = person["SData"] as SchedulerPersonData; var primaryVehicle = PrimaryMode.RequiresVehicle; workStartTime = Time.Zero; workEndTime = Time.Zero; foreach (var TripChain in person.TripChains) { bool usePrimary = SecondaryMode == null || primaryVehicle == null || primaryVehicle.CanUse(person); // ignore the last trip because by definition it must be to home for (int j = 0; j < (TripChain.Trips.Count - 1); j++) { var ThisTrip = TripChain.Trips[j]; var NextTrip = TripChain.Trips[j + 1]; ThisTrip.Mode = NextTrip.Mode = usePrimary ? PrimaryMode : SecondaryMode; var startTime = ThisTrip.DestinationZone == null || ThisTrip.OriginalZone == null ? ThisTrip.TripStartTime : ThisTrip.ActivityStartTime; var endTime = NextTrip.TripStartTime; if (endTime < startTime) { endTime = Time.EndOfDay; } if (endTime < startTime) { startTime = ThisTrip.TripStartTime; } if (ThisTrip.Purpose == Activity.PrimaryWork || ThisTrip.Purpose == Activity.SecondaryWork || ThisTrip.Purpose == Activity.WorkBasedBusiness) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, TripChain.Person); NewEpisode.Zone = ThisTrip.DestinationZone; if (workStartTime == Time.Zero || NewEpisode.StartTime < workStartTime) { workStartTime = NewEpisode.StartTime; } if (workEndTime == Time.Zero || NewEpisode.EndTime > workEndTime) { workEndTime = NewEpisode.EndTime; } PersonData.WorkSchedule.Schedule.Insert(NewEpisode, random); } else if (ThisTrip.Purpose == Activity.School) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, TripChain.Person); NewEpisode.Zone = ThisTrip.DestinationZone; PersonData.SchoolSchedule.Schedule.Insert(NewEpisode, random); } } } }
private void AssignEpisodes(ITashaPerson person, ref Time workStartTime, ref Time workEndTime, Random random) { person.InitializePersonalProjects(); var PersonData = person["SData"] as SchedulerPersonData; var primaryVehicle = this.PrimaryMode.RequiresVehicle; foreach (var TripChain in person.TripChains) { for (int j = 0; j < (TripChain.Trips.Count - 1); j++) { var ThisTrip = TripChain.Trips[j]; var NextTrip = TripChain.Trips[j + 1]; ThisTrip.Mode = this.PrimaryMode; var startTime = ThisTrip.OriginalZone == null || ThisTrip.DestinationZone == null ? ThisTrip.TripStartTime : ThisTrip.ActivityStartTime; var endTime = NextTrip.TripStartTime; var duration = endTime - startTime; if (duration < Time.Zero) { endTime = Time.EndOfDay; } if (endTime < startTime) { startTime = ThisTrip.TripStartTime; } if (ThisTrip.Purpose == Activity.PrimaryWork || ThisTrip.Purpose == Activity.SecondaryWork || ThisTrip.Purpose == Activity.WorkBasedBusiness) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, TripChain.Person); NewEpisode.Zone = ThisTrip.DestinationZone; if (ThisTrip.Purpose == Activity.PrimaryWork) { if (workStartTime == Time.Zero || NewEpisode.StartTime < workStartTime) { workStartTime = NewEpisode.StartTime; } if (workEndTime == Time.Zero || NewEpisode.EndTime > workEndTime) { workEndTime = NewEpisode.EndTime; } } PersonData.WorkSchedule.Schedule.Insert(NewEpisode, random); } if (ThisTrip.Purpose == Activity.School) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, TripChain.Person); NewEpisode.Zone = ThisTrip.DestinationZone; PersonData.SchoolSchedule.Schedule.Insert(NewEpisode, random); } } } }
private static void ProcessWorkAtHome(ITashaPerson person, Schedule workSchedule, Random random, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { int freq_A = TimeTable.GetFrequency(person, Activity.WorkAtHomeBusiness, random, householdPD, workPD, generationAdjustments); Time duration, startTime; for (int i = 0; i < freq_A; i++) { bool success = false; short attempt = 0; while (!success && (attempt < Scheduler.EpisodeSchedulingAttempts)) { if (!TimeTable.GetStartTime(person, Activity.WorkAtHomeBusiness, freq_A, random, out startTime)) { success = false; attempt++; continue; } if (!TimeTable.GetDuration(person, Activity.WorkAtHomeBusiness, startTime, Time.EndOfDay - startTime, random, out duration)) { success = false; attempt++; continue; } Time endTime = startTime + duration; SchedulerHousehold.CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode wahBusinessEpisode; wahBusinessEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.WorkAtHomeBusiness, person); if (!workSchedule.Insert(wahBusinessEpisode, random)) { success = false; attempt++; } else { success = true; } } } }
private static bool GenerateWorkEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; foreach (ITashaPerson person in household.Persons) { // people need to be older than "11" to be allowed to work if (person.Age < Scheduler.MinimumWorkingAge) { continue; } // Check to see if they are in a regular job type case Project workProject = person.GetWorkProject(); Schedule workSchedule = workProject.Schedule; if ((person.Occupation == Occupation.NotEmployed) | (person.Occupation == Occupation.Unknown)) { continue; } if (((person.EmploymentStatus == TTSEmploymentStatus.FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.PartTime))) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; if (person.EmploymentZone == null) { //continue; throw new XTMFRuntimeException(TashaRuntime, "There was a person whom had no employment zone however was a full-time/part-time worker!"); } //Employment zone doesn't exist so generate our own based on distributions if (person.EmploymentZone.ZoneNumber == TashaRuntime.ZoneSystem.RoamingZoneNumber) { GenerateWorkBusinessEpisode(person, workSchedule, random, householdPD, workPD, generationAdjustments); continue; } int freq = TimeTable.GetFrequency(person, Activity.PrimaryWork, random, householdPD, workPD, generationAdjustments); if (freq <= 0) { continue; } Time startTime = Time.Zero; Time duration = Time.Zero; bool success = false; for (int i = 0; i < freq; i++) { for (int attempts = 0; attempts < Scheduler.EpisodeSchedulingAttempts; attempts++) { // If we use an and here the compiler can't prove that we assign to duration if (!TimeTable.GetStartTime(person, Activity.PrimaryWork, freq, random, out startTime)) { continue; } if (TimeTable.GetDuration(person, Activity.PrimaryWork, startTime, random, out duration)) { // if we got the duration, success lets continue on success = true; break; } } // if we were unable to get a duration if (!success) { // try the next person continue; } Time endTime = startTime + duration; CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode primWorkEpisode; primWorkEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.PrimaryWork, person) { Zone = person.EmploymentZone }; if (!workSchedule.Insert(primWorkEpisode, random) && i == 0) { throw new XTMFRuntimeException(TashaRuntime, "Failed to insert the primary work episode into the work project!"); } //set up work business activities ProcessWorkBusiness(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); //set up secondary work activities ProcessSecondaryWork(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); //set up return home from work activities ProcessReturnHomeFromWork(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); } } // Check to see if they work from home else if (person.Age >= 19 && ((person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_PartTime))) { ProcessWorkAtHome(person, workSchedule, random, householdPD, householdPD, generationAdjustments); } // If they don't work, just continue on } return(true); }
private static bool GenerateIndividualOtherEpisodes(this ITashaHousehold household, Random random) { foreach(var person in household.Persons) { if(!person.Child) { int freqO = TimeTable.GetFrequency(person, Activity.IndividualOther, random); int outerAttempts = 0; Time durationO, startTimeO = Time.Zero; for(int i = 0; i < freqO; i++) { bool success = false; for(int attempt = 0; !success && (attempt < Scheduler.EpisodeSchedulingAttempts); attempt++) { if(!TimeTable.GetStartTime(person, Activity.IndividualOther, freqO, random, out startTimeO)) { success = false; continue; } if(!TimeTable.GetDuration(person, Activity.IndividualOther, startTimeO, random, out durationO)) { success = false; continue; } var endTime = startTimeO + durationO; if(endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { success = false; continue; } Episode otherEpisode; otherEpisode = new ActivityEpisode(0, new TimeWindow(startTimeO, endTime), Activity.IndividualOther, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(otherEpisode) + schoolProjSchedule.CheckOverlap(otherEpisode); float percentOverlap = overlap / durationO; if(percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; if(otherSchedule.Insert(otherEpisode, random)) { //inserted ok success = true; } } } if((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { i = -1; Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; otherSchedule.Clear(); } } } } return true; }
private static bool GenerateSchoolEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; foreach (ITashaPerson person in household.Persons) { if (person.StudentStatus == StudentStatus.FullTime || person.StudentStatus == StudentStatus.PartTime) { if (person.Age >= 11) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; var freq = TimeTable.GetFrequency(person, Activity.School, random, householdPD, workPD, generationAdjustments); //if there is a school activity generated for (int i = 0; i < freq; i++) { bool success = false; short attempt = 0; int maxAttempts = Scheduler.EpisodeSchedulingAttempts; while (!success && (attempt < maxAttempts)) { attempt++; //get start time end time and duration if (!TimeTable.GetStartTime(person, Activity.School, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(person, Activity.School, startTime, random, out Time duration)) { continue; } if (duration != Time.Zero) // no valid duration { var endTime = startTime + duration; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } //instantiate temporary school episode; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, startTime + duration), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; success = schoolSchedule.Insert(schoolEpisode, random); } } } } else if (person.Age >= 6) { //this child is in kindergarten //generate random number between 0 and 1 Time startTime, endTime; startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolAfternoonEnd; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } else if (person.Age == 5) { //this child is in kindergarten //generate random number between 0 and 1 int randNum = random.Next(0, 1); Time startTime, endTime; if (randNum <= 0.5) //morning shift { //morning shift startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolMorningEnd; } else { //afternoon shift startTime = Scheduler.SchoolAfternoonStart; endTime = Scheduler.SchoolAfternoonEnd; } Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } } } return(true); }
private static bool GenerateJointOtherEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; //make sure there at least 2 people and one adult if ((household.Persons.Length >= 2) & (household.NumberOfAdults > 0)) { int freqJ = TimeTable.GetFrequency(household, Activity.JointOther, random, householdPD, 0, generationAdjustments); int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointOther); for (int i = 0; i < freqJ; i++) { bool success = false; int attempt = 0; while (!success && attempt < Scheduler.EpisodeSchedulingAttempts) { if (!TimeTable.GetStartTime(household, Activity.JointOther, freqJ, random, out Time startTime)) { attempt++; continue; } if (!TimeTable.GetDuration(household, Activity.JointOther, startTime, random, out Time duration)) { attempt++; continue; } if (duration == Time.Zero || startTime == Time.Zero) { attempt++; } else { Time endTime = startTime + duration; List <ITashaPerson> availableAdults = new List <ITashaPerson>(); foreach (ITashaPerson person in household.Persons) { Time workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); Time workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); bool available = false; if (workSchoolStartTime > endTime || workSchoolEndTime < startTime || workSchoolStartTime == Time.Zero) { available = true; } if (person.Age >= 16 && available) { availableAdults.Add(person); } } if (availableAdults.Count >= numEpisodeAdults && availableAdults.Count > 0) { Episode jointOtherEpisode; var owner = availableAdults[0]; jointOtherEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.JointOther, owner); for (int j = 0; j < numEpisodeAdults; j++) { jointOtherEpisode.AddPerson(availableAdults[j]); } Project jointOtherProject = household.GetJointOtherProject(); Schedule jointOtherSchedule = jointOtherProject.Schedule; bool inserted = jointOtherSchedule.Insert(jointOtherEpisode, random); success = true; if (!inserted) { success = false; attempt++; } } else { attempt++; } } } } } return(true); }
private static bool GenerateSchoolEpisodes(this ITashaHousehold household, Random random) { foreach(ITashaPerson person in household.Persons) { if(person.StudentStatus == StudentStatus.FullTime || person.StudentStatus == StudentStatus.PartTime) { if(person.Age >= 11) { var freq = TimeTable.GetFrequency(person, Activity.School, random); //if there is a school activity generated for(int i = 0; i < freq; i++) { bool success = false; short attempt = 0; Time duration = new Time(), startTime = new Time(); int maxAttempts = Scheduler.EpisodeSchedulingAttempts; while(!success && (attempt < maxAttempts)) { attempt++; //get start time end time and duration if(!TimeTable.GetStartTime(person, Activity.School, random, out startTime)) { continue; } if(!TimeTable.GetDuration(person, Activity.School, startTime, random, out duration)) { continue; } if(duration != Time.Zero) // no valid duration { var endTime = startTime + duration; if(endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { success = false; continue; } //instantiate temporary school episode; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(0, new TimeWindow(startTime, startTime + duration), Activity.School, person); schoolEpisode.Zone = person.SchoolZone != null ? person.SchoolZone : person.Household.HomeZone; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; success = schoolSchedule.Insert(schoolEpisode, random); } } } } else if(person.Age >= 6) { //this child is in kindergarten //generate random number between 0 and 1 Time startTime = new Time(), endTime = new Time(); startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolAfternoonEnd; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.School, person); schoolEpisode.Zone = person.SchoolZone != null ? person.SchoolZone : person.Household.HomeZone; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } else if(person.Age == 5) { //this child is in kindergarten //generate random number between 0 and 1 int randNum = random.Next(0, 1); Time duration = new Time(), startTime = new Time(), endTime = new Time(); if(randNum <= 0.5) //morning shift { //morning shift startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolMorningEnd; duration = endTime - startTime; } else { //afternoon shift startTime = Scheduler.SchoolAfternoonStart; endTime = Scheduler.SchoolAfternoonEnd; } Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.School, person); schoolEpisode.Zone = person.SchoolZone != null ? person.SchoolZone : person.Household.HomeZone; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } } } return true; }
private void AssignEpisodes(ITashaPerson person, ref Time workStartTime, ref Time workEndTime, Random random) { person.InitializePersonalProjects(); var PersonData = person["SData"] as SchedulerPersonData; foreach(var TripChain in person.TripChains) { for(int j = 0; j < (TripChain.Trips.Count - 1); j++) { var ThisTrip = TripChain.Trips[j]; var NextTrip = TripChain.Trips[j + 1]; ThisTrip.Mode = ThisTrip[ObservedMode] as ITashaMode; NextTrip.Mode = NextTrip[ObservedMode] as ITashaMode; var startTime = ThisTrip.OriginalZone == null || ThisTrip.DestinationZone == null ? ThisTrip.TripStartTime : ThisTrip.ActivityStartTime; var endTime = NextTrip.TripStartTime; var duration = endTime - startTime; if(duration < Time.Zero) { endTime = Time.EndOfDay; } if(endTime < startTime) { startTime = ThisTrip.TripStartTime; } if(ThisTrip.Purpose == Activity.PrimaryWork || ThisTrip.Purpose == Activity.SecondaryWork || ThisTrip.Purpose == Activity.WorkBasedBusiness) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, person); NewEpisode.Zone = ThisTrip.DestinationZone; if(ThisTrip.Purpose == Activity.PrimaryWork || ThisTrip.Purpose == Activity.WorkBasedBusiness) { if(workStartTime == Time.Zero || NewEpisode.StartTime < workStartTime) { workStartTime = NewEpisode.StartTime; } if(workEndTime == Time.Zero || NewEpisode.EndTime > workEndTime) { workEndTime = NewEpisode.EndTime; } } PersonData.WorkSchedule.Schedule.Insert(NewEpisode, random); } if(ThisTrip.Purpose == Activity.School) { var NewEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), ThisTrip.Purpose, person); NewEpisode.Zone = ThisTrip.DestinationZone; PersonData.SchoolSchedule.Schedule.Insert(NewEpisode, random); } } } }
private static void ProcessWorkBusiness(ITashaPerson person, Schedule workSchedule, Random random, Episode primWorkEpisode) { Time startTimeB; Time durationB; Time startTime = primWorkEpisode.StartTime; Time endTime = primWorkEpisode.EndTime; int freq = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random, Scheduler.MaxFrequency, startTime, endTime); for(int i = 0; i < freq; i++) { var attempt = 0; bool success = false; while(attempt < Scheduler.EpisodeSchedulingAttempts) { attempt++; if(!TimeTable.GetStartTime(person, Activity.WorkBasedBusiness, freq, startTime, endTime, random, out startTimeB)) { continue; } if(!TimeTable.GetDuration(person, Activity.WorkBasedBusiness, startTimeB, endTime - startTimeB, random, out durationB)) { continue; } Episode businessEpisode; businessEpisode = new ActivityEpisode(0, new TimeWindow(startTimeB, startTimeB + durationB), Activity.WorkBasedBusiness, person); if(workSchedule.Insert(businessEpisode, random)) { success = true; break; } } } }
private static void ProcessWorkAtHome(ITashaPerson person, Schedule workSchedule, Random random) { int freq_A = TimeTable.GetFrequency(person, Activity.WorkAtHomeBusiness, random); Time duration, startTime; for(int i = 0; i < freq_A; i++) { bool success = false; short attempt = 0; while(!success && (attempt < Scheduler.EpisodeSchedulingAttempts)) { if(!TimeTable.GetStartTime(person, Activity.WorkAtHomeBusiness, freq_A, random, out startTime)) { success = false; attempt++; continue; } if(!TimeTable.GetDuration(person, Activity.WorkAtHomeBusiness, startTime, Time.EndOfDay - startTime, random, out duration)) { success = false; attempt++; continue; } Time endTime = startTime + duration; SchedulerHousehold.CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode wahBusinessEpisode; wahBusinessEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.WorkAtHomeBusiness, person); if(!workSchedule.Insert(wahBusinessEpisode, random)) { success = false; attempt++; } else { success = true; } } } }
/// <summary> /// Secondary work creates a secondary work activity for person /// </summary> /// <param name="person"></param> /// <param name="schedule"></param> /// <param name="primaryWorkEpisode"></param> private static void ProcessSecondaryWork(ITashaPerson person, Schedule schedule, Random random, Episode primaryWorkEpisode) { //can only work if finish primary work by 7:00PM if(primaryWorkEpisode.EndTime < Scheduler.SecondaryWorkThreshold) { int freq_R = 0; //getting earliest possible startTime Time HourAfterWork = primaryWorkEpisode.EndTime + Time.OneHour; Time MinStartTime = HourAfterWork > Scheduler.SecondaryWorkMinStartTime ? HourAfterWork : Scheduler.SecondaryWorkMinStartTime; freq_R = TimeTable.GetFrequency(person, Activity.SecondaryWork, random, 10, MinStartTime, Time.EndOfDay); for(int i = 0; i < freq_R; i++) { //zone same as work zone IZone zone = primaryWorkEpisode.Zone.ZoneNumber == Scheduler.Tasha.ZoneSystem.RoamingZoneNumber ? Scheduler.LocationChoiceModel.GetLocationHomeBased(Activity.SecondaryWork, person.Household.HomeZone, random) : primaryWorkEpisode.Zone; //getting start time and duration of secondary work Time startTimeR; Time durationR; if(!TimeTable.GetStartTime(person, primaryWorkEpisode.ActivityType, freq_R, MinStartTime, Time.EndOfDay, random, out startTimeR)) { //TODO: We might want to reconsider this, skipping instead of just throwing an exception //throw new XTMFRuntimeException("Unable to find a start time for a primary work episode"); return; } if(!TimeTable.GetDuration(person, Activity.SecondaryWork, startTimeR, Time.EndOfDay - startTimeR, random, out durationR)) { //throw new XTMFRuntimeException("Unable to find a duration for a primary work episode"); return; } //inserting secondary work into schedule Episode secondaryWorkEpisode; secondaryWorkEpisode = new ActivityEpisode(0, new TimeWindow(startTimeR, startTimeR + durationR), Activity.SecondaryWork, person); secondaryWorkEpisode.Zone = zone; schedule.Insert(secondaryWorkEpisode, random); } } }
/// <summary> /// Return home from work creates a return home from work activity (return home from work may involve /// going to lunch at home or going to check up on something in the house during work). /// </summary> /// <param name="person"></param> /// <param name="schedule"></param> /// <param name="episode"></param> /// <returns></returns> private static bool ProcessReturnHomeFromWork(ITashaPerson person, Schedule schedule, Random random, Episode episode) { int freq = 0; //the current work schedule doesn't allow for a return from work activity if(episode.StartTime > Scheduler.MaxPrimeWorkStartTimeForReturnHomeFromWork || episode.Duration < Scheduler.MinPrimaryWorkDurationForReturnHomeFromWork) { return false; } //End time of work to home activity Time endTime = episode.EndTime + new Time(0.3f) < Scheduler.ReturnHomeFromWorkMaxEndTime ? episode.EndTime + new Time(0.3f) : Scheduler.ReturnHomeFromWorkMaxEndTime; freq = TimeTable.GetFrequency(person, Activity.ReturnFromWork, random, 1, episode.StartTime + new Time(0.3f), endTime); if(freq == 1) { IZone homeZone = person.Household.HomeZone; Time HalfAnHour = new Time() { Minutes = 30 }; Time MaxEndTime = ((episode.EndTime - HalfAnHour) < Scheduler.ReturnHomeFromWorkMaxEndTime) ? (episode.EndTime - HalfAnHour) : Scheduler.ReturnHomeFromWorkMaxEndTime; Time startTime; if(!TimeTable.GetStartTime(person, Activity.ReturnFromWork , freq , episode.StartTime + HalfAnHour , MaxEndTime, random, out startTime)) { return false; } Time maxDuration = new Time(Math.Min((Scheduler.ReturnHomeFromWorkMaxEndTime - Time.OneHour).ToFloat(), (episode.EndTime - HalfAnHour - startTime).ToFloat())); Time duration; if(!TimeTable.GetDuration(person, Activity.ReturnFromWork, startTime, maxDuration, random, out duration)) { // reject return false; } Episode returnFromWorkEpisode; returnFromWorkEpisode = new ActivityEpisode(0, new TimeWindow(startTime, startTime + duration), Activity.ReturnFromWork, person); returnFromWorkEpisode.Zone = homeZone; schedule.Insert(returnFromWorkEpisode, random); } return true; }
private static bool GenerateWorkEpisodes(this ITashaHousehold household, Random random) { foreach(ITashaPerson person in household.Persons) { // people need to be older than "11" to be allowed to work if(person.Age < Scheduler.MinimumWorkingAge) continue; // Check to see if they are in a regular job type case Project workProject = person.GetWorkProject(); Schedule workSchedule = workProject.Schedule; if((person.Occupation == Occupation.NotEmployed) | (person.Occupation == Occupation.Unknown)) { continue; } if(((person.EmploymentStatus == TTSEmploymentStatus.FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.PartTime))) { if(person.EmploymentZone == null) { //continue; throw new XTMFRuntimeException("There was a person whom had no employment zone however was a full-time/part-time worker!"); } //Employment zone doesn't exist so generate our own based on distributions if(person.EmploymentZone.ZoneNumber == TashaRuntime.ZoneSystem.RoamingZoneNumber) { GenerateWorkBusinessEpisode(person, workSchedule, random); continue; } int freq = TimeTable.GetFrequency(person, Activity.PrimaryWork, random); if(freq <= 0) { continue; } Time startTime = Time.Zero; Time duration = Time.Zero; bool success = false; for(int i = 0; i < freq; i++) { for(int attempts = 0; attempts < Scheduler.EpisodeSchedulingAttempts; attempts++) { // If we use an and here the compiler can't prove that we assign to duration if(!TimeTable.GetStartTime(person, Activity.PrimaryWork, freq, random, out startTime)) { continue; } if(TimeTable.GetDuration(person, Activity.PrimaryWork, startTime, random, out duration)) { // if we got the duration, success lets continue on success = true; break; } } // if we were unable to get a duration if(!success) { // try the next person continue; } Time endTime = startTime + duration; SchedulerHousehold.CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode primWorkEpisode; primWorkEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.PrimaryWork, person); primWorkEpisode.Zone = person.EmploymentZone; if(!workSchedule.Insert(primWorkEpisode, random) && i == 0) { throw new XTMFRuntimeException("Failed to insert the primary work episode into the work project!"); } //set up work business activities ProcessWorkBusiness(person, workSchedule, random, primWorkEpisode); //set up secondary work activities ProcessSecondaryWork(person, workSchedule, random, primWorkEpisode); //set up return home from work activities ProcessReturnHomeFromWork(person, workSchedule, random, primWorkEpisode); } } // Check to see if they work from home else if(person.Age >= 19 && ((person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_PartTime))) { ProcessWorkAtHome(person, workSchedule, random); } // If they don't work, just continue on } return true; }
private static void GenerateWorkBusinessEpisode(ITashaPerson person, Schedule workSchedule, Random random) { int freq_B = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random); for(int i = 0; i < freq_B; i++) { Time startTime; Time duration; for(int attempt = 0; attempt < Scheduler.EpisodeSchedulingAttempts; attempt++) { if(!TimeTable.GetStartTime(person, Activity.WorkBasedBusiness, random, out startTime)) { continue; } if(!TimeTable.GetDuration(person, Activity.WorkBasedBusiness, startTime, random, out duration)) { continue; } var endTime = startTime + duration; if(endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } Episode workEpisode = new ActivityEpisode(System.Threading.Interlocked.Increment(ref Episode.GeneratedEpisodes), new TimeWindow(startTime, startTime + duration), Activity.WorkBasedBusiness, person); workSchedule.Insert(workEpisode, random); break; } } }
private static bool GenerateIndividualMarketEpisodes(this ITashaHousehold household, Random random) { foreach(var person in household.Persons) { if(!person.Child) { int freq_I = TimeTable.GetFrequency(person, Activity.Market, random); int outerAttempts = 0; for(int j = 0; j < freq_I; ++j) { //Update the trip generation count Time startTime; Time duration; bool success = false; for(int attempt = 0; attempt < Scheduler.EpisodeSchedulingAttempts && !success; attempt++) { if(!TimeTable.GetStartTime(person, Activity.Market, random, out startTime)) { continue; } if(!TimeTable.GetDuration(person, Activity.Market, startTime, random, out duration)) { continue; } var endTime = startTime + duration; if(endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { success = false; continue; } //instantiate a temporary individual market episode on the heap space and store pointer in p_marketEpisode Episode MarketEpisode = new ActivityEpisode(0, new TimeWindow(startTime, startTime + duration), Activity.Market, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(MarketEpisode) + schoolProjSchedule.CheckOverlap(MarketEpisode); float percentOverlap = overlap / duration; if(percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; if(marketSchedule.Insert(MarketEpisode, random)) { //inserted ok success = true; } else { success = false; //didn't work } } else // i.e. too much overlap with the work and school projects { // attempt will be auto incremented so we don't need to worry about this } } if((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { j = -1; Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; marketSchedule.Clear(); } } } } return true; }
private static bool GenerateJointMarketEpisodes(this ITashaHousehold household, Random random) { // initialize available adults var availableAdults = new List<ITashaPerson>(household.Persons.Length); // We can only do this with households with more than one person if(household.Persons.Length >= 2 && household.NumberOfAdults > 0) { // Figure out how many times this home is going to go on a joint market trip int howManyTimes = TimeTable.GetFrequency(household, Activity.JointMarket, random); // Processes each of those trips for(int i = 0; i < howManyTimes; i++) { Time startTime, duration; int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointMarket); bool success = false; // continue to try until either we get it to work or we fail to schedule this episode for(int attempt = 0; !success && attempt < Scheduler.EpisodeSchedulingAttempts; attempt++) { if(!TimeTable.GetStartTime(household, Activity.JointMarket, random, out startTime)) { continue; } if(!TimeTable.GetDuration(household, Activity.JointMarket, startTime, random, out duration)) { continue; } // Now that we have our start time and duration, compute our end time Time endTime = startTime + duration; if(availableAdults.Count > 0) availableAdults.Clear(); Time workSchoolStartTime, workSchoolEndTime; bool available = false; foreach(var person in household.Persons) { workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); // this person is available if available = (workSchoolStartTime > endTime) | (workSchoolEndTime < startTime) | (workSchoolStartTime == Time.Zero); if(person.Age >= 16 && available) { availableAdults.Add(person); } } if((availableAdults.Count > 0) & (availableAdults.Count >= numEpisodeAdults)) { Episode jointMarketEpisode; jointMarketEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.JointMarket, availableAdults[0]); foreach(ITashaPerson adult in availableAdults) { jointMarketEpisode.AddPerson(adult); } Project jointMarketProject = household.GetJointMarketProject(); Schedule jointMarketSchedule = jointMarketProject.Schedule; bool insert = jointMarketSchedule.Insert(jointMarketEpisode, random); success = insert; } } } } return true; }
public override bool Insert(Episode ep, Random random) { /* This is where episodes are first put near their other common types * RULES: * 1) Unless it is a Work Business episode, we are not allowed to have a "split" conflict type * 2) We are not allowed to squish things past the threshold allowed (50% by default) */ // Learn what type of case we are going to be in ConflictReport conflict = InsertCase(null, ep, false); switch (conflict.Type) { case ScheduleConflictType.NoConflict: { InsertAt(ep, conflict.Position); return(true); } case ScheduleConflictType.Split: { if ((ep.ActivityType != Activity.WorkBasedBusiness) & (ep.ActivityType != Activity.ReturnFromWork)) { return(false); } if (Episodes[conflict.Position].ActivityType != Activity.PrimaryWork) { return(false); } // Since it is a primary work episode we need to split it var postEp = new ActivityEpisode(new TimeWindow(ep.EndTime, Episodes[conflict.Position].EndTime), Activity.PrimaryWork, Episodes[conflict.Position].Owner) { Zone = Episodes[conflict.Position].Zone }; ((Episode)Episodes[conflict.Position]).EndTime = ep.StartTime; InsertAt(ep, conflict.Position + 1); InsertAt(postEp, conflict.Position + 2); return(true); } case ScheduleConflictType.Posterior: { // the given position is the element we need to go after Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)Episodes[conflict.Position]; Episode middle = ep; Episode post = (Episode)((conflict.Position < EpisodeCount - 1) ? Episodes[conflict.Position + 1] : null); if (conflict.Position >= 1) { earlyTimeBound = Episodes[conflict.Position - 1].EndTime; } if (EpisodeCount - conflict.Position > 2) { lateTimeBound = Episodes[conflict.Position + 2].StartTime; } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position + 1); return(true); } return(false); } case ScheduleConflictType.Prior: { // The given position is the element we need to go before Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)(conflict.Position > 0 ? Episodes[conflict.Position - 1] : null); Episode middle = ep; Episode post = (Episode)Episodes[conflict.Position]; if (conflict.Position >= 2) { earlyTimeBound = Episodes[conflict.Position - 2].EndTime; } if (EpisodeCount - conflict.Position > 1) { lateTimeBound = Episodes[conflict.Position + 1].StartTime; } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position); return(true); } return(false); } case ScheduleConflictType.CompleteOverlap: { // There are no cases where a complete overlap is allowed return(false); } default: { // We came across a type of conflict that we do not know how to handle! throw new NotImplementedException(String.Format("This conflict type \"{0}\" has not been coded for yet!", Enum.GetName(typeof(ScheduleConflictType), conflict.Type))); } } }
private static bool GenerateIndividualOtherEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { int householdPD = household.HomeZone.PlanningDistrict; foreach (var person in household.Persons) { if (!person.Child) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; int freqO = TimeTable.GetFrequency(person, Activity.IndividualOther, random, householdPD, workPD, generationAdjustments); int outerAttempts = 0; for (int i = 0; i < freqO; i++) { bool success = false; for (int attempt = 0; !success && (attempt < Scheduler.EpisodeSchedulingAttempts); attempt++) { if (!TimeTable.GetStartTime(person, Activity.IndividualOther, freqO, random, out Time startTimeO)) { continue; } if (!TimeTable.GetDuration(person, Activity.IndividualOther, startTimeO, random, out Time durationO)) { continue; } var endTime = startTimeO + durationO; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } Episode otherEpisode; otherEpisode = new ActivityEpisode(new TimeWindow(startTimeO, endTime), Activity.IndividualOther, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(otherEpisode) + schoolProjSchedule.CheckOverlap(otherEpisode); float percentOverlap = overlap / durationO; if (percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; if (otherSchedule.Insert(otherEpisode, random)) { //inserted ok success = true; } } } if ((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { i = -1; Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; otherSchedule.Clear(); } } } } return(true); }
private static bool GenerateJointMarketEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustment) { var householdPD = household.HomeZone.PlanningDistrict; // initialize available adults var availableAdults = new List <ITashaPerson>(household.Persons.Length); // We can only do this with households with more than one person if (household.Persons.Length >= 2 && household.NumberOfAdults > 0) { // Figure out how many times this home is going to go on a joint market trip int howManyTimes = TimeTable.GetFrequency(household, Activity.JointMarket, random, householdPD, 0, generationAdjustment); // Processes each of those trips for (int i = 0; i < howManyTimes; i++) { int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointMarket); bool success = false; // continue to try until either we get it to work or we fail to schedule this episode for (int attempt = 0; !success && attempt < Scheduler.EpisodeSchedulingAttempts; attempt++) { if (!TimeTable.GetStartTime(household, Activity.JointMarket, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(household, Activity.JointMarket, startTime, random, out Time duration)) { continue; } // Now that we have our start time and duration, compute our end time Time endTime = startTime + duration; if (availableAdults.Count > 0) { availableAdults.Clear(); } Time workSchoolStartTime, workSchoolEndTime; bool available; foreach (var person in household.Persons) { workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); // this person is available if available = (workSchoolStartTime > endTime) | (workSchoolEndTime < startTime) | (workSchoolStartTime == Time.Zero); if (person.Age >= 16 && available) { availableAdults.Add(person); } } if ((availableAdults.Count > 0) & (availableAdults.Count >= numEpisodeAdults)) { Episode jointMarketEpisode; jointMarketEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.JointMarket, availableAdults[0]); foreach (ITashaPerson adult in availableAdults) { jointMarketEpisode.AddPerson(adult); } Project jointMarketProject = household.GetJointMarketProject(); Schedule jointMarketSchedule = jointMarketProject.Schedule; bool insert = jointMarketSchedule.Insert(jointMarketEpisode, random); success = insert; } } } } return(true); }
private static bool GenerateJointOtherEpisodes(this ITashaHousehold household, Random random) { //make sure there at least 2 people and one adult if((household.Persons.Length >= 2) & (household.NumberOfAdults > 0)) { int freqJ = TimeTable.GetFrequency(household, Activity.JointOther, random); Time duration, startTime; int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointOther); for(int i = 0; i < freqJ; i++) { bool success = false; int attempt = 0; while(!success && attempt < Scheduler.EpisodeSchedulingAttempts) { if(!TimeTable.GetStartTime(household, Activity.JointOther, freqJ, random, out startTime)) { success = false; attempt++; continue; } if(!TimeTable.GetDuration(household, Activity.JointOther, startTime, random, out duration)) { success = false; attempt++; continue; } if(duration == Time.Zero || startTime == Time.Zero) { success = false; attempt++; } else { Time endTime = startTime + duration; List<ITashaPerson> availableAdults = new List<ITashaPerson>(); foreach(ITashaPerson person in household.Persons) { Time workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); Time workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); bool available = false; if(workSchoolStartTime > endTime || workSchoolEndTime < startTime || workSchoolStartTime == Time.Zero) available = true; if(person.Age >= 16 && available) { availableAdults.Add(person); } } if(availableAdults.Count >= numEpisodeAdults && availableAdults.Count > 0) { Episode jointOtherEpisode; var owner = availableAdults[0]; jointOtherEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.JointOther, owner); for(int j = 0; j < numEpisodeAdults; j++) { jointOtherEpisode.AddPerson(availableAdults[j]); } Project jointOtherProject = household.GetJointOtherProject(); Schedule jointOtherSchedule = jointOtherProject.Schedule; bool inserted = jointOtherSchedule.Insert(jointOtherEpisode, random); success = true; if(!inserted) { success = false; attempt++; } } else { success = false; attempt++; } } } } } return true; }
private static bool GenerateIndividualMarketEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { int householdPD = household.HomeZone.PlanningDistrict; foreach (var person in household.Persons) { if (!person.Child) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; int freqI = TimeTable.GetFrequency(person, Activity.Market, random, householdPD, workPD, generationAdjustments); int outerAttempts = 0; for (int j = 0; j < freqI; ++j) { bool success = false; for (int attempt = 0; attempt < Scheduler.EpisodeSchedulingAttempts && !success; attempt++) { if (!TimeTable.GetStartTime(person, Activity.Market, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(person, Activity.Market, startTime, random, out Time duration)) { continue; } var endTime = startTime + duration; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } //instantiate a temporary individual market episode on the heap space and store pointer in p_marketEpisode var window = new TimeWindow(startTime, startTime + duration); Episode marketEpisode = new ActivityEpisode(window, Activity.Market, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(marketEpisode) + schoolProjSchedule.CheckOverlap(marketEpisode); float percentOverlap = overlap / duration; if (percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; if (marketSchedule.Insert(marketEpisode, random)) { //inserted ok success = true; } } } if ((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { j = -1; Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; marketSchedule.Clear(); } } } } return(true); }
public override bool Insert(Episode ep, Random random) { /* This is where episodes are first put near their other common types * RULES: * 1) Unless it is a Work Business episode, we are not allowed to have a "split" conflict type * 2) We are not allowed to squish things past the threshold allowed (50% by default) */ // Learn what type of case we are going to be in ConflictReport conflict = this.InsertCase(null, ep, false); switch(conflict.Type) { case ScheduleConflictType.NoConflict: { this.InsertAt(ep, conflict.Position); return true; } case ScheduleConflictType.Split: { if((ep.ActivityType != Activity.WorkBasedBusiness) & (ep.ActivityType != Activity.ReturnFromWork)) return false; if(this.Episodes[conflict.Position].ActivityType != Activity.PrimaryWork) return false; // Since it is a primary work episode we need to split it var postEp = new ActivityEpisode(0, new TimeWindow(ep.EndTime, this.Episodes[conflict.Position].EndTime), Activity.PrimaryWork, this.Episodes[conflict.Position].Owner); postEp.Zone = this.Episodes[conflict.Position].Zone; ((Episode)this.Episodes[conflict.Position]).EndTime = ep.StartTime; this.InsertAt(ep, conflict.Position + 1); this.InsertAt(postEp, conflict.Position + 2); return true; } case ScheduleConflictType.Posterior: { // the given position is the element we need to go after Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)this.Episodes[conflict.Position]; Episode middle = ep; Episode post = (Episode)((conflict.Position < this.EpisodeCount - 1) ? this.Episodes[conflict.Position + 1] : null); if(conflict.Position >= 1) { earlyTimeBound = this.Episodes[conflict.Position - 1].EndTime; } if(this.EpisodeCount - conflict.Position > 2) { lateTimeBound = this.Episodes[conflict.Position + 2].StartTime; } if(this.Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { this.InsertAt(ep, conflict.Position + 1); return true; } return false; } case ScheduleConflictType.Prior: { // The given position is the element we need to go before Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)(conflict.Position > 0 ? this.Episodes[conflict.Position - 1] : null); Episode middle = ep; Episode post = (Episode)this.Episodes[conflict.Position]; if(conflict.Position >= 2) { earlyTimeBound = this.Episodes[conflict.Position - 2].EndTime; } if(this.EpisodeCount - conflict.Position > 1) { lateTimeBound = this.Episodes[conflict.Position + 1].StartTime; } if(this.Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { this.InsertAt(ep, conflict.Position); return true; } return false; } case ScheduleConflictType.CompleteOverlap: { // There are no cases where a complete overlap is allowed return false; } default: { // We came across a type of conflict that we do not know how to handle! throw new NotImplementedException(String.Format("This conflict type \"{0}\" has not been coded for yet!", Enum.GetName(typeof(ScheduleConflictType), conflict.Type))); } } }