Skip to content

Commit

Permalink
have about half of the mandatory scheduling model implemented
Browse files Browse the repository at this point in the history
need to ask a few questions about the time windowing
  • Loading branch information
fscottfoti committed Mar 2, 2015
1 parent 53bf27c commit bb43936
Show file tree
Hide file tree
Showing 4 changed files with 523 additions and 524 deletions.
2 changes: 2 additions & 0 deletions example/configs/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ store: mtc_asim.h5

# area_types less than this are considered urban
urban_threshold: 4
cbd_threshold: 2
rural_threshold: 6

households_sample_size: 1000

Expand Down
2 changes: 1 addition & 1 deletion example/configs/tour_departure_and_duration.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Description,Expression,workFree-flow round trip auto time shift effects - departure,start,0.00114Free-flow round trip auto time shift effects - duration,duration,0.00221Part-time worker departure shift effects,(ptype == 2) * start,0.06736Non-working adult duration shift effects,(ptype == 4) * duration,0.1207University student departure shift effects,(ptype == 3) * start,0.05747Household income departure shift effects,income_in_thousands * start,0.00021Destination in CBD departure shift effects,start,0.04717Destination in CBD duration shift effects,duration,0.08679subsequent tour must start after previous tour ends,start < endOfPreviousTour,999First of 2+ work tours departure shift effects,start,0.3033First of 2+ work tours duration shift effects,duration,0.1861Subsequent 2+ work departure tours shift effects,start,0.5381Subsequent 2+ work duration tours shift effects,duration,0.3174Household income -- Early departure interaction,start < 6,0.4854Household income -- Late arrival interaction,end > 22,0.3839Destination in CBD -- Early departure interaction,start < 6,0.4566Destination in CBD -- Late arrival interaction,end > 22,0.2334Rural household -- Early departure interaction,start < 6,0.4039Rural household -- Late arrival interaction,end > 22,0.3451Full-time worker -- duration < 9 hours interaction,duration < 9,1.257Full-time worker -- 10 to 12 departure interaction,(start > 9)*(start < 13),0.5182Part-time worker -- 13 to 15 arrival interaction,(end > 12)*(end < 16),0.5433First of 2+ work tours- duration<8 hrs,duration < 8,1.98Subsequent of 2+ work tours- duration<8 hrs,duration < 8,2.582Work+school tours by worker- duration<8 hrs,duration < 8,0.9126School+work tours by student- duration<8 hrs,duration < 8,2.582Mode Choice Logsum,@@modeChoiceLogsumAlt,1.027Previously-scheduled tour ends in this departure hour,@@prevTourEndsThisDepartureHourAlt,0.8935Previously-scheduled tour begins in this arrival hour,@@prevTourBeginsThisArrivalHourAlt,1.334Adjacent window exists before this departure hour - first tour interaction,@@adjWindowBeforeThisHourAlt,0.1771Adjacent window exists afetr this arrival hour - first tour interaction,@@adjWindowAfterThisHourAlt,0.3627Adjacent window exists before this departure hour - second+ tour interaction,@@adjWindowBeforeThisHourAlt,0.2123Adjacent window exists after this arrival hour - second+ tour interaction,@@adjWindowAfterThisHourAlt,0.1012Remaining work/school tours to be scheduled / number of unscheduled hours,1 / @@remainingHoursAvailableAlt,18.68Departure Constants -- Early (up to 5),1,0.95273Departure Constants -- AM peak 1 (6),1,0.61618Departure Constants -- AM peak 2 (7),1,0Departure Constants -- AM peak 3 (8),1,0.25471Departure Constants -- AM peak 4 (9),1,1.25135Departure Constants -- Midday 1 (10 to 12),1,1.70587Departure Constants -- Midday 2 (13 to 15),1,1.69357Departure Constants -- PM peak (16 to 18),1,1.43999Departure Constants -- Evening (19 to 21),1,1.61051Departure Constants -- Late (22 and later),1,2.88342Arrival Constants -- Early (up to 6),1,0Arrival Constants -- AM peak (7 to 9),1,1.85452Arrival Constants -- Midday 1 (10 to 12),1,0.49597Arrival Constants -- Midday 2 (13 to 14),1,0.37855Arrival Constants -- PM peak 1 (15),1,0Arrival Constants -- PM peak 2 (16),1,0.27608Arrival Constants -- PM peak 3 (17),1,0.69959Arrival Constants -- PM peak 4 (18),1,0.79929Arrival Constants -- Evening (19 to 21),1,0.10357Arrival Constants -- Late (22 and later),1,0.96596Duration Constants -- 0 to 2 hours,1,2.52827Duration Constants -- 3 to 4 hours,1,0.91897Duration Constants -- 5 to 6 hours,1,0.71855Duration Constants -- 7 to 8 hours,1,0.13962Duration Constants -- 9 hours,1,0.05571Duration Constants -- 10 hours,1,0Duration Constants -- 11 hours,1,0.3478Duration Constants -- 12 to 13 hours,1,1.00822Duration Constants -- 14 to 18 hours,1,1.70186
Description,Expression,workFree-flow round trip auto time shift effects - departure,roundtrip_auto_time_to_work * start,0.00114Free-flow round trip auto time shift effects - duration,roundtrip_auto_time_to_work * duration,0.00221Part-time worker departure shift effects,(ptype == 2) * start,0.06736Non-working adult duration shift effects,(ptype == 4) * duration,0.1207University student departure shift effects,(ptype == 3) * start,0.05747Household income departure shift effects,income_in_thousands * start,0.00021Destination in CBD departure shift effects,workplace_in_cbd * start,0.04717Destination in CBD duration shift effects,workplace_in_cbd * duration,0.08679subsequent tour must start after previous tour ends,(start < end_of_previous_tour) & (tour_num == 2),-999First of 2+ work tours departure shift effects,(tour_num == 1) * start,0.3033First of 2+ work tours duration shift effects,(tour_num == 1) * duration,0.1861Subsequent 2+ work departure tours shift effects,(tour_num == 2) * start,0.5381Subsequent 2+ work duration tours shift effects,(tour_num == 2) * duration,0.3174Household income -- Early departure interaction,(income_in_thousands > 100) & (start < 6),0.4854Household income -- Late arrival interaction,(income_in_thousands > 100) & (end > 22),0.3839Destination in CBD -- Early departure interaction,workplace_in_cbd & (start < 6),0.4566Destination in CBD -- Late arrival interaction,workplace_in_cbd & (end > 22),0.2334Rural household -- Early departure interaction,home_is_rural & (start < 6),0.4039Rural household -- Late arrival interaction,home_is_rural & (end > 22),0.3451Full-time worker -- duration < 9 hours interaction,(ptype == 1) & (duration < 9),1.257Full-time worker -- 10 to 12 departure interaction,(ptype == 1) & (start > 9) & (start < 13),0.5182Part-time worker -- 13 to 15 arrival interaction,(ptype == 2) & (end > 12) & (end < 16),0.5433First of 2+ work tours- duration<8 hrs,(tour_num == 1) & (duration < 8),1.98Subsequent of 2+ work tours- duration<8 hrs,(tour_num == 2) & (duration < 8),2.582Work+school tours by worker- duration<8 hrs,(mandatory_tour_frequency == 'work_and_school') & is_worker & (duration < 8),0.9126School+work tours by student- duration<8 hrs,(mandatory_tour_frequency == 'work_and_school') & is_student & (duration < 8),2.582Mode Choice Logsum,mode_choice_logsum,1.027Previously-scheduled tour ends in this departure hour,prev_tour_end == start,0.8935Previously-scheduled tour begins in this arrival hour,prev_tour_begin == end,1.334Adjacent window exists before this departure hour - first tour interaction,@@adjWindowBeforeThisHourAlt,0.1771Adjacent window exists afetr this arrival hour - first tour interaction,@@adjWindowAfterThisHourAlt,0.3627Adjacent window exists before this departure hour - second+ tour interaction,@@adjWindowBeforeThisHourAlt,0.2123Adjacent window exists after this arrival hour - second+ tour interaction,@@adjWindowAfterThisHourAlt,0.1012Remaining work/school tours to be scheduled / number of unscheduled hours,1 / @@remainingHoursAvailableAlt,18.68Departure Constants -- Early (up to 5),start < 6,0.95273Departure Constants -- AM peak 1 (6),start == 6,0.61618Departure Constants -- AM peak 2 (7),start == 7,0Departure Constants -- AM peak 3 (8),start == 8,0.25471Departure Constants -- AM peak 4 (9),start == 9,1.25135Departure Constants -- Midday 1 (10 to 12),(start > 9) & (start < 13),1.70587Departure Constants -- Midday 2 (13 to 15),(start > 12) & (start < 16),1.69357Departure Constants -- PM peak (16 to 18),(start > 15) & (start < 19),1.43999Departure Constants -- Evening (19 to 21),(start > 18) & (start < 22),1.61051Departure Constants -- Late (22 and later),start > 21,2.88342Arrival Constants -- Early (up to 6),end < 7,0Arrival Constants -- AM peak (7 to 9),(end > 6) & (end < 10),1.85452Arrival Constants -- Midday 1 (10 to 12),(end > 9) & (end < 13),0.49597Arrival Constants -- Midday 2 (13 to 14),(end > 12) & (end < 15),0.37855Arrival Constants -- PM peak 1 (15),end == 15,0Arrival Constants -- PM peak 2 (16),end == 16,0.27608Arrival Constants -- PM peak 3 (17),end == 17,0.69959Arrival Constants -- PM peak 4 (18),end == 18,0.79929Arrival Constants -- Evening (19 to 21),(end > 18) & (end < 22),0.10357Arrival Constants -- Late (22 and later),end > 21,0.96596Duration Constants -- 0 to 2 hours,duration < 3,2.52827Duration Constants -- 3 to 4 hours,(duration > 2) & (duration < 5),0.91897Duration Constants -- 5 to 6 hours,(duration > 4) & (duration < 7),0.71855Duration Constants -- 7 to 8 hours,(duration > 6) & (duration < 9),0.13962Duration Constants -- 9 hours,duration == 9,0.05571Duration Constants -- 10 hours,duration == 10,0Duration Constants -- 11 hours,duration == 11,0.3478Duration Constants -- 12 to 13 hours,(duration > 11) & (duration < 14),1.00822Duration Constants -- 14 to 18 hours,(duration > 13) & (duration < 19),1.70186
Expand Down
131 changes: 115 additions & 16 deletions example/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def destination_choice_spec():
@sim.table()
def tour_departure_and_duration_spec():
f = os.path.join('configs', 'tour_departure_and_duration.csv')
return asim.read_model_spec(f, stack=False).head(4)
return asim.read_model_spec(f, stack=False)


"""
Expand Down Expand Up @@ -381,6 +381,55 @@ def non_mandatory_tours(persons,
cast_index=True, onto_on='person_id')


"""
This does the same as the above but for mandatory tours. Ending format is
the same as in the comment above except trip types are "work" and "school"
"""

@sim.table()
def mandatory_tours(persons):

persons = persons.to_frame(columns=["mandatory_tour_frequency",
"is_worker"])
persons = persons[~persons.mandatory_tour_frequency.isnull()]

tours = []
# this is probably easier to do in non-vectorized fashion (at least for now)
for key, row in persons.iterrows():

mtour = row.mandatory_tour_frequency
is_worker = row.is_worker

# 1 work trip
if mtour == "work1":
tours += [(key, "work", 1)]
# 2 work trips
elif mtour == "work2":
tours += [(key, "work", 1), (key, "work", 2)]
# 1 school trip
elif mtour == "school1":
tours += [(key, "school", 1)]
# 2 school trips
elif mtour == "school2":
tours += [(key, "school", 1), (key, "school", 2)]
# 1 work and 1 school trip
elif mtour == "work_and_school":
if is_worker:
# is worker, work trip goes first
tours += [(key, "work", 1), (key, "school", 2)]
else:
# is student, work trip goes second
tours += [(key, "school", 1), (key, "work", 2)]
else:
assert 0

return pd.DataFrame(tours, columns=["person_id", "trip_type", "tour_num"])


sim.broadcast('persons', 'mandatory_tours',
cast_index=True, onto_on='person_id')


"""
Given the tour generation from the above, each tour needs to have a
destination, so in this case tours are the choosers (with the associated
Expand Down Expand Up @@ -450,33 +499,60 @@ def destination_choice(non_mandatory_tours,


@sim.model()
def mandatory_tour_departure_and_duration(persons,
def mandatory_tour_departure_and_duration(mandatory_tours,
persons,
households,
land_use,
tour_departure_and_duration_alts,
tour_departure_and_duration_spec):

print tour_departure_and_duration_spec.to_frame().tail()
choosers = sim.merge_tables(mandatory_tours.name, tables=[mandatory_tours,
persons,
households,
land_use])

choosers = sim.merge_tables(persons.name, tables=[persons,
households,
land_use])
print "Running %d mandatory tour scheduling choices" % len(choosers)

# filter based on results of CDAP
choosers = choosers[choosers.cdap_activity == 'M']
print "%d persons run for workplace tour departure and duration model" % \
len(choosers)
# assert there's only a first or second mandatory tour - that's a basic
# assumption of this model formulation right now
assert choosers.tour_num.isin([1, 2]).value_counts()[True] == len(choosers)

choices, _ = \
asim.simple_simulate(choosers,
tour_departure_and_duration_alts.to_frame(),
tour_departure_and_duration_spec['work'],
mult_by_alt_col=False)
first_tours = choosers[choosers.tour_num == 1]
second_tours = choosers[choosers.tour_num == 2]

spec = tour_departure_and_duration_spec.work.head(27)
alts = tour_departure_and_duration_alts.to_frame()

print choosers.mandatory_tour_frequency.value_counts()
print spec

# this is a bit odd to python - we can't run through in for loops for
# performance reasons - we first have to do a pass for the first tours and
# then for the second tours - this is mainly because the second tours are
# dependent on the first tours' scheduling

print "Running %d mandatory first tour choices" % len(first_tours)

alts["end_of_previous_tour"] = -1

# FIXME - a note to remember that this also needs the mode choice logsum
alts["mode_choice_logsum"] = 0

first_choices, _ = \
asim.simple_simulate(first_tours, alts, spec, mult_by_alt_col=False)

print "Running %d mandatory second tour choices" % len(second_tours)

# FIXME need to set end_of_previous_tour to the ends computed above
second_choices, _ = \
asim.simple_simulate(second_tours, alts, spec, mult_by_alt_col=False)

choices = pd.concat([first_choices, second_choices])

# as with non-mandatory tour generation, this stores the INDEX of
# the alternative in the tour_departure and_duration_alts dataframe -
# to actually use it we'll have ot go back and grab the start and end times
print "Choices:\n", choices.value_counts()
print "Choices:\n", choices.describe()

sim.add_column("persons", "mandatory_tour_departure_and_duration", choices)

Expand Down Expand Up @@ -568,6 +644,12 @@ def home_is_urban(households, land_use, settings):
return s < settings['urban_threshold']


@sim.column('households')
def home_is_rural(households, land_use, settings):
s = usim_misc.reindex(land_use.area_type, households.home_taz)
return s > settings['rural_threshold']


@sim.column('households')
def car_sufficiency(households, persons):
return households.auto_ownership - persons.household_id.value_counts()
Expand Down Expand Up @@ -782,6 +864,16 @@ def under16_not_at_school(persons):
persons.cdap_activity.isin(["N", "H"]))


@sim.column("persons")
def is_worker(persons):
return persons.employed_cat.isin(['full', 'part'])


@sim.column("persons")
def is_student(persons):
return persons.student_cat.isin(['high', 'college'])


@sim.column("persons")
def workplace_taz(persons):
# FIXME this is really because we ask for ALL columns in the persons data
Expand Down Expand Up @@ -838,3 +930,10 @@ def roundtrip_auto_time_to_school(persons, sovam_skim, sovmd_skim):
sovmd_skim.get(persons.school_taz,
persons.home_taz),
index=persons.index)


@sim.column('persons')
def workplace_in_cbd(persons, land_use, settings):
s = usim_misc.reindex(land_use.area_type, persons.workplace_taz)
return s < settings['cbd_threshold']

Loading

0 comments on commit bb43936

Please sign in to comment.