Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
f79341d
Differentiate examples between quality and validity of example models…
jpn-- Aug 3, 2022
3b7e551
black and isort (#578)
jpn-- Aug 4, 2022
468270b
stop emitting output dir
jpn-- Aug 6, 2022
74b1465
trace files in nested directories
jpn-- Aug 7, 2022
3b12814
swap files for xborder model
jpn-- Aug 7, 2022
e92ac72
repair ARC MP
jpn-- Aug 8, 2022
93650ab
print checksum even when not used
jpn-- Aug 9, 2022
ee6c9e6
add hashes for sandag_xborder_full
jpn-- Aug 9, 2022
e097c70
fix dtype in university hack
jpn-- Aug 9, 2022
7481f73
fix persons to match tours
jpn-- Aug 9, 2022
1176399
repair ARC
jpn-- Aug 10, 2022
e4910e5
Bump version: 1.0.4 → 1.1.0
jpn-- Aug 11, 2022
0412a0b
Merge pull request #580 from camsys/small-fixes
jpn-- Aug 11, 2022
f189143
Merge pull request #582 from ActivitySim/develop
jpn-- Aug 12, 2022
6d887b7
Added mwcog small area
AndrewTheTM Aug 15, 2022
4d6287d
missed one edit
AndrewTheTM Aug 15, 2022
e1fe792
reformatting
AndrewTheTM Aug 16, 2022
788a2db
Update README.MD
AndrewTheTM Aug 16, 2022
af8e1b9
call as module
jpn-- Aug 16, 2022
6226a56
github actions tests
jpn-- Aug 16, 2022
d16b5fb
pre commit hooks
jpn-- Aug 16, 2022
800989a
pyproject toml
jpn-- Aug 16, 2022
c05204e
limit numpy
jpn-- Aug 16, 2022
3d08096
docs for mamba instead of conda
jpn-- Aug 16, 2022
f72ce38
ignore generated files
jpn-- Aug 16, 2022
098ed44
add nbmake to test env
jpn-- Aug 16, 2022
1fb852a
fix dupe line
jpn-- Aug 16, 2022
8c8cba4
repair test multiple zones for github actions
jpn-- Aug 17, 2022
0cc4439
publish develop docs
jpn-- Aug 17, 2022
03dc574
fix docbuild env
jpn-- Aug 17, 2022
38cfde8
Update .travis.yml
AndrewTheTM Aug 18, 2022
175219f
fixed testing files
AndrewTheTM Aug 18, 2022
997669b
Merge branch 'develop' of https://github.com/AndrewTheTM/activitysim …
AndrewTheTM Aug 18, 2022
3db9db5
fixed testing files (again)
AndrewTheTM Aug 18, 2022
493dc9a
fixed test script again
AndrewTheTM Aug 18, 2022
f325e99
publish docs to branch name
jpn-- Aug 19, 2022
093ead1
updated testing scripts (note shorter travis script for now)
AndrewTheTM Aug 22, 2022
2bfdea2
fixed slash (windows vs. linux testing issue)
AndrewTheTM Aug 22, 2022
8b4f081
added output folders
AndrewTheTM Aug 22, 2022
fb74cd0
updated travis script to run all tests, should pass
AndrewTheTM Aug 22, 2022
b785d67
docs cleaning
jpn-- Aug 23, 2022
b3af10e
docs re-style
jpn-- Aug 23, 2022
69de8d2
rebuild
jpn-- Aug 23, 2022
a0188a2
dynamic versioning docs
jpn-- Aug 23, 2022
8159f17
version switcher
jpn-- Aug 23, 2022
f2e8e9b
blacken
jpn-- Aug 23, 2022
3e254ff
fix switcher url
jpn-- Aug 23, 2022
30455f2
fix conf
jpn-- Aug 23, 2022
91beb97
switcher update
jpn-- Aug 23, 2022
1cba29e
master to main
jpn-- Aug 23, 2022
82efce4
deployment actions
jpn-- Aug 23, 2022
04feee0
actions
jpn-- Aug 23, 2022
62b1fb7
Merge pull request #586 from camsys/infrastructure
jpn-- Aug 23, 2022
d311432
build wheel
jpn-- Aug 23, 2022
e7d34a1
Merge pull request #588 from camsys/infrastructure
jpn-- Aug 23, 2022
73378a8
fix for testpypi
jpn-- Aug 24, 2022
f979a84
blacken
jpn-- Aug 24, 2022
8d419f3
manual switcher
jpn-- Aug 24, 2022
569d563
branch docs service [makedocs]
jpn-- Aug 24, 2022
6d20cef
syntax [makedocs]
jpn-- Aug 24, 2022
b61f78b
travis depends
jpn-- Aug 24, 2022
05940d5
checkout v3, fix versioning in docs
jpn-- Aug 24, 2022
c6b9c9f
only build develop docs once
jpn-- Aug 24, 2022
822e177
failsafe version
jpn-- Aug 24, 2022
9a782f8
documentation repairs
jpn-- Aug 24, 2022
8b7737c
python-simplified-semver
jpn-- Aug 24, 2022
6bb1d53
front cards
jpn-- Aug 24, 2022
4944aef
end testing w travis
jpn-- Aug 25, 2022
dbae2f3
merge to latest
jpn-- Aug 25, 2022
df70b6c
add mwcog test to gh-actions
jpn-- Aug 25, 2022
4cbeccb
add mwcog to docs
jpn-- Aug 25, 2022
8fb416d
point to data not copy it
jpn-- Aug 29, 2022
35586ff
sort dependencies
jpn-- Aug 29, 2022
5fd488f
req sh 2.2.4
jpn-- Aug 29, 2022
f51c609
account for variance across platforms in trip dest est
jpn-- Aug 29, 2022
236072e
copy bike skims for sandag test
jpn-- Aug 29, 2022
45b1709
Merge pull request #1 from camsys/develop-mwcog
AndrewTheTM Aug 30, 2022
96bf698
Merge pull request #585 from AndrewTheTM/develop
jpn-- Aug 30, 2022
156c771
param on rtol
jpn-- Aug 31, 2022
7455375
fix sandag_2 test files
jpn-- Sep 1, 2022
f14c078
fix test file names
jpn-- Sep 1, 2022
7ead422
Merge pull request #594 from camsys/develop
jpn-- Sep 2, 2022
59f5753
added pre-processor option to trip scheduling
dhensle Sep 14, 2022
1e758f8
trip scheduling relative mode initial commit
dhensle Oct 6, 2022
02087b8
moved everything to mwcog example
dhensle Oct 6, 2022
983462d
adding output analysis notebook
dhensle Oct 7, 2022
56968f5
adding additional segmentation
dhensle Dec 1, 2022
d0805dc
testing and documentation
dhensle Dec 1, 2022
5924bfe
blacken
dhensle Dec 1, 2022
cd3265c
not assuming scheduling mode is set
dhensle Dec 1, 2022
9dde8b5
merging trip_scheduling with BayDAG
dhensle Dec 1, 2022
c60b5a1
fixing merge trip scheduling
dhensle Dec 1, 2022
07c3f4d
still fixing merge
dhensle Dec 1, 2022
330176b
reverting regression trips
dhensle Dec 1, 2022
d62cbc1
fixing bad merge and updating test
dhensle Dec 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions activitysim/abm/models/non_mandatory_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from .util.school_escort_tours_trips import create_pure_school_escort_tours

from .util.vectorize_tour_scheduling import vectorize_tour_scheduling
from activitysim.core.util import assign_in_place


logger = logging.getLogger(__name__)
DUMP = False
Expand Down
59 changes: 51 additions & 8 deletions activitysim/abm/models/trip_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@

from activitysim.abm.models.util import estimation
from activitysim.abm.models.util.trip import cleanup_failed_trips, failed_trip_cohorts
from activitysim.core import chunk, config, inject, logit, pipeline, tracing
from activitysim.core import (
chunk,
config,
inject,
logit,
pipeline,
tracing,
expressions,
)
from activitysim.core.util import reindex

from .util.school_escort_tours_trips import split_out_school_escorting_trips
Expand Down Expand Up @@ -36,13 +44,15 @@

DEPARTURE_MODE = "departure"
DURATION_MODE = "stop_duration"
RELATIVE_MODE = "relative"
PROBS_JOIN_COLUMNS_DEPARTURE_BASED = [
"primary_purpose",
"outbound",
"tour_hour",
"trip_num",
]
PROBS_JOIN_COLUMNS_DURATION_BASED = ["outbound", "stop_num"]
PROBS_JOIN_COLUMNS_RELATIVE_BASED = ["outbound", "periods_left"]


def set_tour_hour(trips, tours):
Expand Down Expand Up @@ -181,6 +191,7 @@ def schedule_trips_in_leg(
failfix = model_settings.get(FAILFIX, FAILFIX_DEFAULT)
depart_alt_base = model_settings.get("DEPART_ALT_BASE", 0)
scheduling_mode = model_settings.get("scheduling_mode", "departure")
preprocessor_settings = model_settings.get("preprocessor", None)

if scheduling_mode == "departure":
probs_join_cols = model_settings.get(
Expand All @@ -190,10 +201,14 @@ def schedule_trips_in_leg(
probs_join_cols = model_settings.get(
"probs_join_cols", PROBS_JOIN_COLUMNS_DURATION_BASED
)
elif scheduling_mode == "relative":
probs_join_cols = model_settings.get(
"probs_join_cols", PROBS_JOIN_COLUMNS_RELATIVE_BASED
)
else:
logger.error(
"Invalid scheduling mode specified: {0}.".format(scheduling_mode),
"Please select one of ['departure', 'stop_duration'] and try again.",
"Please select one of ['departure', 'stop_duration', 'relative'] and try again.",
)

# logger.debug("%s scheduling %s trips" % (trace_label, trips.shape[0]))
Expand Down Expand Up @@ -232,18 +247,35 @@ def schedule_trips_in_leg(
ADJUST_NEXT_DEPART_COL = "latest"
trips.next_trip_id = trips.next_trip_id.where(~is_final, NO_TRIP_ID)

network_los = inject.get_injectable("network_los")
locals_dict = {"network_los": network_los}
locals_dict.update(config.get_model_constants(model_settings))

first_trip_in_leg = True
for i in range(trips.trip_num.min(), trips.trip_num.max() + 1):

if outbound or scheduling_mode == DURATION_MODE:
nth_trace_label = tracing.extend_trace_label(trace_label, "num_%s" % i)

# - annotate trips
if preprocessor_settings:
expressions.assign_columns(
df=trips,
model_settings=preprocessor_settings,
locals_dict=locals_dict,
trace_label=nth_trace_label,
)

if (
outbound
or (scheduling_mode == DURATION_MODE)
or (scheduling_mode == RELATIVE_MODE)
):
# iterate in ascending trip_num order
nth_trips = trips[trips.trip_num == i]
else:
# iterate over inbound trips in descending trip_num order, skipping the final trip
nth_trips = trips[trips.trip_num == trips.trip_count - i]

nth_trace_label = tracing.extend_trace_label(trace_label, "num_%s" % i)

choices = ps.make_scheduling_choices(
nth_trips,
scheduling_mode,
Expand All @@ -265,6 +297,12 @@ def schedule_trips_in_leg(
)
choices = choices.fillna(trips[ADJUST_NEXT_DEPART_COL])

if scheduling_mode == RELATIVE_MODE:
# choices are relative to the previous departure time
choices = nth_trips.earliest + choices
# need to update the departure time based on the choice
update_tour_earliest(trips, choices)

# adjust allowed depart range of next trip
has_next_trip = nth_trips.next_trip_id != NO_TRIP_ID
if has_next_trip.any():
Expand Down Expand Up @@ -437,9 +475,9 @@ def trip_scheduling(trips, tours, chunk_size, trace_hh_id):
]
estimator.write_choosers(trips_df[chooser_cols_for_estimation])

probs_spec = pd.read_csv(
config.config_file_path("trip_scheduling_probs.csv"), comment="#"
)
probs_spec_file = model_settings.get("PROBS_SPEC", "trip_scheduling_probs.csv")
logger.debug(f"probs_spec_file: {config.config_file_path(probs_spec_file)}")
probs_spec = pd.read_csv(config.config_file_path(probs_spec_file), comment="#")
# FIXME for now, not really doing estimation for probabilistic model - just overwriting choices
# besides, it isn't clear that named coefficients would be helpful if we had some form of estimation
# coefficients_df = simulate.read_model_coefficients(model_settings)
Expand Down Expand Up @@ -499,6 +537,11 @@ def trip_scheduling(trips, tours, chunk_size, trace_hh_id):
failed = choices.reindex(trips_chunk.index).isnull()
logger.info("%s %s failed", trace_label_i, failed.sum())

if (failed.sum() > 0) & (
model_settings.get("scheduling_mode") == "relative"
):
raise RuntimeError("failed trips with relative scheduling mode")

if not is_last_iteration:
# boolean series of trips whose leg scheduling failed
failed_cohorts = failed_trip_cohorts(trips_chunk, failed)
Expand Down
26 changes: 24 additions & 2 deletions activitysim/abm/models/util/probabilistic_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,22 @@ def _preprocess_scheduling_probs(
)
elif scheduling_mode == "stop_duration":
chooser_probs = _preprocess_stop_duration_probs(choosers)
elif scheduling_mode == "relative":
# creating a dataframe with just the trip_id as index and alternatives as columns
probs_cols = [
c
for c in probs_spec.columns
if ((c not in probs_join_cols) & (c.isnumeric()))
]
chooser_probs = choosers.loc[:, probs_cols]
chooser_probs = chooser_probs.div(chooser_probs.sum(axis=1), axis=0)
assert (
~chooser_probs.isna().values.any()
), f"Missing probabilities for trips \n {chooser_probs[chooser_probs.isna().any(axis=1)].index}"
else:
logger.error(
"Invalid scheduling mode specified: {0}.".format(scheduling_mode),
"Please select one of ['departure', 'stop_duration'] and try again.",
"Please select one of ['departure', 'stop_duration', 'relative'] and try again.",
)

# probs should sum to 1 with residual probs resulting in choice of 'fail'
Expand All @@ -196,6 +208,12 @@ def _postprocess_scheduling_choices(
# convert alt choice index to depart time (setting failed choices to -1)
failed = choices == choice_cols.get_loc("fail")

if scheduling_mode == "relative":
if failed.any():
RuntimeError(
f"Failed trips in realtive mode for {failed.sum()} trips: {choosers[failed]}"
)

# For the stop duration-based probabilities, the alternatives are offsets that
# get applied to trip-specific departure and arrival times, so depart_alt_base
# is a column/series rather than a scalar.
Expand Down Expand Up @@ -334,7 +352,11 @@ def make_scheduling_choices(
if failed.any():
choices = choices[~failed]

if all([check_col in choosers_df.columns for check_col in ["earliest", "latest"]]):
if all(
[check_col in choosers_df.columns for check_col in ["earliest", "latest"]]
) & (scheduling_mode != "relative"):
# check to make sure choice does not come before previously scheduled trip or after end of tour
# does not apply if choices are relative to previous trip depart
assert (choices >= choosers_df.earliest[~failed]).all()
assert (choices <= choosers_df.latest[~failed]).all()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@

# int to add to probs column index to get time period it represents.
# e.g. depart_alt_base = 5 means first column (column 0) represents period 5
DEPART_ALT_BASE: 1
DEPART_ALT_BASE: 0

MAX_ITERATIONS: 100

#FAILFIX: drop_and_cleanup
FAILFIX: choose_most_initial

# --- relative trip scheduling settings
PROBS_SPEC: trip_scheduling_probs_purpose_stops.csv

scheduling_mode: relative

probs_join_cols:
- periods_left_min
- periods_left_max
- outbound
- tour_purpose_grouped
- half_tour_stops_remaining_grouped

preprocessor:
SPEC: trip_scheduling_preprocessor
DF: choosers
TABLES:
- tours
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Description,Target,Expression
,periods_left,(df.latest - df.earliest)
# binning the periods differently for inbound and outbound
,periods_left_min,"np.where(df['outbound'], periods_left.clip(upper=25), periods_left.clip(upper=34))"
,periods_left_max,"np.where(((periods_left >= 25) & (df['outbound'])) | ((periods_left >= 34) & (~df['outbound'])), 47, periods_left)"
,tour_purpose,"reindex(tours.tour_type, df.tour_id)"
,tour_purpose_grouped,"np.where(tour_purpose.isin(['work','school','univ']), 'mand', 'non_mand')"
,half_tour_stops_remaining_grouped,(df.trip_count - df.trip_num).clip(upper=1)
Loading