Skip to content
Draft
Changes from all commits
Commits
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
34 changes: 19 additions & 15 deletions activitysim/abm/tables/shadow_pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,6 @@
TALLY_CHECKOUT = (1, -1)
TALLY_PENDING_PERSONS = (2, -1)

default_segment_to_name_dict = {
# model_selector : persons_segment_name
"school": "school_segment",
"workplace": "income_segment",
}


def size_table_name(model_selector):
"""
Expand Down Expand Up @@ -134,12 +128,6 @@ class ShadowPriceSettings(PydanticReadable, extra="forbid"):

WRITE_ITERATION_CHOICES: bool = False

SEGMENT_TO_NAME: dict[str, str] = {
"school": "school_segment",
"workplace": "income_segment",
} # pydantic uses deep copy, so mutable default value is ok here
"""Mapping from model_selector to persons_segment_name."""


class ShadowPriceCalculator:
def __init__(
Expand Down Expand Up @@ -176,6 +164,7 @@ def __init__(
)

self.model_selector = model_settings.MODEL_SELECTOR
self.chooser_segment_column = model_settings.CHOOSER_SEGMENT_COLUMN_NAME

if (self.num_processes > 1) and not state.settings.fail_fast:
# if we are multiprocessing, then fail_fast should be true or we will wait forever for failed processes
Expand Down Expand Up @@ -826,9 +815,24 @@ def update_shadow_prices(self, state):
sampled_persons = pd.DataFrame()
persons_merged = state.get_dataframe("persons_merged")

# need to join the segment to the choices to sample correct persons
segment_to_name_dict = self.shadow_settings.SEGMENT_TO_NAME
segment_name = segment_to_name_dict[self.model_selector]
# Use the model chooser segmentation to keep shadow-pricing resampling
# consistent with segment_ids in location choice settings.
segment_name = self.chooser_segment_column
if segment_name not in persons_merged.columns:
raise SystemConfigurationError(
f"Missing chooser segment column '{segment_name}' in persons_merged "
f"for {self.model_selector} simulation shadow pricing"
)

# Fail fast on obvious misconfiguration instead of silently sampling no one.
segment_values = set(self.segment_ids.values())
chooser_values = set(persons_merged[segment_name].dropna().unique())
if not segment_values.intersection(chooser_values):
raise SystemConfigurationError(
f"No overlap between SEGMENT_IDS values ({sorted(segment_values)}) and "
f"persons_merged['{segment_name}'] values for {self.model_selector} "
"simulation shadow pricing"
)

if type(self.choices_synced) != pd.DataFrame:
self.choices_synced = self.choices_synced.to_frame()
Expand Down
Loading