From 54a8cc1ed40f1492c05a9086cd6f7125bc32817f Mon Sep 17 00:00:00 2001 From: David Hensle <51132108+dhensle@users.noreply.github.com> Date: Fri, 29 May 2026 14:52:45 -0700 Subject: [PATCH 1/3] location choice logsum not overwritten --- activitysim/abm/models/location_choice.py | 28 ----------------------- 1 file changed, 28 deletions(-) diff --git a/activitysim/abm/models/location_choice.py b/activitysim/abm/models/location_choice.py index 2d629a404c..f9f50b2406 100644 --- a/activitysim/abm/models/location_choice.py +++ b/activitysim/abm/models/location_choice.py @@ -873,34 +873,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" From 6554d59f7eb78911894d280d8b7b00adc752978c Mon Sep 17 00:00:00 2001 From: Jeff Newman Date: Tue, 4 Aug 2026 18:07:19 -0500 Subject: [PATCH 2/3] test: cover location choice logsum survey overrides --- activitysim/abm/test/test_location_choice.py | 84 ++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 activitysim/abm/test/test_location_choice.py diff --git a/activitysim/abm/test/test_location_choice.py b/activitysim/abm/test/test_location_choice.py new file mode 100644 index 0000000000..3e679feee4 --- /dev/null +++ b/activitysim/abm/test/test_location_choice.py @@ -0,0 +1,84 @@ +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(trace_hh_id=None)) + 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 From c576eaa929f1d0af584e99744eee0dc2dc1d9777 Mon Sep 17 00:00:00 2001 From: Jeff Newman Date: Tue, 4 Aug 2026 22:20:23 -0500 Subject: [PATCH 3/3] Set sampling options in location choice test --- activitysim/abm/test/test_location_choice.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/activitysim/abm/test/test_location_choice.py b/activitysim/abm/test/test_location_choice.py index 3e679feee4..37c375ccc7 100644 --- a/activitysim/abm/test/test_location_choice.py +++ b/activitysim/abm/test/test_location_choice.py @@ -55,7 +55,13 @@ def test_estimation_override_preserves_destination_choice_logsum(monkeypatch): LOGSUM_SETTINGS="tour_mode_choice.yaml", SEGMENT_IDS={"workers": 1}, ) - state = SimpleNamespace(settings=SimpleNamespace(trace_hh_id=None)) + 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(