@@ -279,14 +279,28 @@ def run_trip_scheduling_choice(
279279 ) in chunk .adaptive_chunked_choosers (state , indirect_tours , trace_label ):
280280 # Sort the choosers and get the schedule alternatives
281281 choosers = choosers .sort_index ()
282- # FIXME-EET: For explicit error term choices, we need a stable alternative ID. Currently, we use
283- # SCHEDULE_ID, which justs enumerates all schedule alternatives, of which there are choosers times
284- # alternative, in the order they are processed, which depends on if there stops on outward/return leg.
285- # We might want to change SCHEDULE_ID to a fixed pattern of all possible combinations of
286- # (outbound, main, inbound) duration for the maximum possible tour duration (max time window). For
287- # 30min intervals, this leads to 1225 alternatives and therefore reasonable memory-wise for random numbers.
288- # It looks like all that would need to change for this is the generation of the schedule alternatives and
289- # the lookup of choices as elements in schedule after simulation because choosers are indexed by tour_id.
282+ # FIXME-EET: under use_explicit_error_terms, error terms here are aligned positionally, not keyed
283+ # to a stable alternative ID: no alts_context is passed to _interaction_sample_simulate (this direct
284+ # private call also bypasses the public wrapper's warning about that), so each tour draws one EV1
285+ # error per alternative slot from its own tour_id-keyed channel, and the j-th draw attaches to the
286+ # j-th row of the tour's block in `schedules`. SCHEDULE_ID plays no role in the alignment; it is a
287+ # per-call running enumeration used only to look up the chosen row after the simulation.
288+ #
289+ # The per-tour row order is canonical: get_pattern_index_and_arrays sorts each tour's feasible
290+ # windows lexicographically by (main, outbound, inbound) duration via np.unique, independent of
291+ # chunk composition and processing order. Error terms are therefore stable across scenarios for
292+ # every tour whose stop pattern (outbound/inbound) and duration are unchanged. They are NOT aligned
293+ # for a tour whose duration or stop pattern changes: the lexicographic enumeration shifts, so
294+ # position j maps to a different duration triple.
295+ #
296+ # To keep draws aligned across such changes too, key them to a canonical universe of schedule
297+ # patterns -- e.g. all (outbound, inbound) duration pairs up to the maximum time window, with the
298+ # main leg implied by the tour duration; for 30min intervals that is 1225 stable IDs, reasonable
299+ # memory-wise for random numbers, and a duration change then keeps the error terms of unchanged
300+ # (outbound, inbound) allocations. This would mean making SCHEDULE_ID that stable pattern ID and
301+ # passing an alts_context (see the alt_nrs_df machinery in _interaction_sample_simulate); the
302+ # post-simulation lookup below would then need to match on (tour_id, SCHEDULE_ID) pairs since IDs
303+ # would repeat across tours.
290304
291305 schedules = generate_schedule_alternatives (choosers ).sort_index ()
292306
0 commit comments