Skip to content
Merged
Show file tree
Hide file tree
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
28 changes: 0 additions & 28 deletions activitysim/abm/models/location_choice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
90 changes: 90 additions & 0 deletions activitysim/abm/test/test_location_choice.py
Original file line number Diff line number Diff line change
@@ -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
Loading