diff --git a/activitysim/abm/models/location_choice.py b/activitysim/abm/models/location_choice.py index faaa50863..951a5411c 100644 --- a/activitysim/abm/models/location_choice.py +++ b/activitysim/abm/models/location_choice.py @@ -950,34 +950,6 @@ def run_location_choice( ) estimator.write_override_choices(choices_df.choice) - if want_logsums: - # if we override choices, we need to to replace choice logsum with ologsim for override location - # fortunately, as long as we aren't sampling dest alts, the logsum will be in location_sample_df - - # if we start sampling dest alts, we will need code below to compute override location logsum - assert estimator.want_unsampled_alternatives - - # merge mode_choice_logsum for the overridden location - # alt_logsums columns: ['person_id', 'choice', 'logsum'] - alt_dest_col = model_settings.ALT_DEST_COL_NAME - alt_logsums = ( - location_sample_df[[alt_dest_col, ALT_LOGSUM]] - .rename(columns={alt_dest_col: "choice", ALT_LOGSUM: "logsum"}) - .reset_index() - ) - - # choices_df columns: ['person_id', 'choice'] - choices_df = choices_df[["choice"]].reset_index() - - # choices_df columns: ['person_id', 'choice', 'logsum'] - choices_df = pd.merge(choices_df, alt_logsums, how="left").set_index( - "person_id" - ) - - logger.debug( - f"{trace_label} segment {segment_name} estimation: override logsums" - ) - if state.settings.trace_hh_id: estimation_trace_label = tracing.extend_trace_label( trace_label, f"estimation.{segment_name}.survey_choices" diff --git a/activitysim/abm/test/test_location_choice.py b/activitysim/abm/test/test_location_choice.py new file mode 100644 index 000000000..37c375ccc --- /dev/null +++ b/activitysim/abm/test/test_location_choice.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +from types import SimpleNamespace +from unittest.mock import Mock + +import pandas as pd +import pandas.testing as pdt + +from activitysim.abm.models import location_choice + + +def test_estimation_override_preserves_destination_choice_logsum(monkeypatch): + """Survey overrides should only change the chosen destination's mode logsum.""" + person_index = pd.Index([1], name="person_id") + location_sample = pd.DataFrame( + { + "alt_dest": [101, 202], + location_choice.ALT_LOGSUM: [5.0, 7.0], + }, + index=pd.Index([1, 1], name="person_id"), + ) + modeled_choices = pd.DataFrame( + {"choice": [101], "logsum": [-1.5]}, index=person_index + ) + + # Keep the test focused on the estimation override and final logsum merge. + monkeypatch.setattr( + location_choice, + "run_location_sample", + lambda *args, **kwargs: location_sample.copy(), + ) + monkeypatch.setattr( + location_choice, + "run_location_logsums", + lambda *args, **kwargs: location_sample.copy(), + ) + monkeypatch.setattr( + location_choice, + "run_location_simulate", + lambda *args, **kwargs: modeled_choices.copy(), + ) + + estimator = Mock() + estimator.get_survey_values.return_value = pd.Series( + [202], index=person_index, name="choice" + ) + shadow_price_calculator = Mock() + shadow_price_calculator.dest_size_terms.return_value = pd.Series( + [1.0, 1.0], index=[101, 202] + ) + model_settings = SimpleNamespace( + ALT_DEST_COL_NAME="alt_dest", + CHOOSER_SEGMENT_COLUMN_NAME="segment", + DEST_CHOICE_COLUMN_NAME="workplace_zone_id", + LOGSUM_SETTINGS="tour_mode_choice.yaml", + SEGMENT_IDS={"workers": 1}, + ) + state = SimpleNamespace( + settings=SimpleNamespace( + sample_method="monte_carlo", + trace_hh_id=None, + use_explicit_error_terms=False, + ) + ) + persons = pd.DataFrame({"segment": [1]}, index=person_index) + + choices, sample = location_choice.run_location_choice( + state=state, + persons_merged_df=persons, + network_los=Mock(), + shadow_price_calculator=shadow_price_calculator, + want_logsums=True, + want_sample_table=False, + estimator=estimator, + model_settings=model_settings, + chunk_size=0, + chunk_tag="workplace_location", + trace_label="workplace_location", + ) + + expected = pd.DataFrame( + { + "choice": [202], + "logsum": [-1.5], + location_choice.ALT_LOGSUM: [7.0], + }, + index=person_index, + ) + pdt.assert_frame_equal(choices, expected) + assert sample is None