Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joint Tour Participation - Optimize Two Person Households #289

Open
danielsclint opened this issue Dec 28, 2019 · 1 comment
Open

Joint Tour Participation - Optimize Two Person Households #289

danielsclint opened this issue Dec 28, 2019 · 1 comment
Labels
First Contribution These are good first issues for people wanting to dive into the ASIM software. Performance Changes that improve performance

Comments

@danielsclint
Copy link

Disclaimer: This is feature enhancement request. If I understand the code correctly, this should save some time while not impacting the results of the model. If my understanding of the code is incorrect, disregard. This came out of investigating #288.

If a two person household has been chosen to participate in a joint tour, it doesn't seem necessary to send the two person household participants through the Monte Carlo simulation. If the two-person household has already been determined to participate in a joint tour, the Monte Carlo simulation is going to iterate until both participants have been chosen. It would seem easier to process two person household in a deterministic manner and only use the Monte Carlo simulation to determine participants in households with three or more people.

def participants_chooser(probs, choosers, spec, trace_label):
"""
custom alternative to logit.make_choices for simulate.simple_simulate
Choosing participants for mixed tours is trickier than adult or child tours becuase we
need at least one adult and one child participant in a mixed tour. We call logit.make_choices
and then check to see if the tour statisfies this requirement, and rechoose for any that
fail until all are satisfied.
In principal, this shold always occur eventually, but we fail after MAX_ITERATIONS,
just in case there is some failure in program logic (haven't seen this occur.)
Parameters
----------
probs : pandas.DataFrame
Rows for choosers and columns for the alternatives from which they
are choosing. Values are expected to be valid probabilities across
each row, e.g. they should sum to 1.
choosers : pandas.dataframe
simple_simulate choosers df
spec : pandas.DataFrame
simple_simulate spec df
We only need spec so we can know the column index of the 'participate' alternative
indicating that the participant has been chosen to participate in the tour
trace_label : str
Returns - same as logit.make_choices
-------
choices, rands
choices, rands as returned by logit.make_choices (in same order as probs)
"""
assert probs.index.equals(choosers.index)
# choice is boolean (participate or not)
model_settings = config.read_model_settings('joint_tour_participation.yaml')
choice_col = model_settings.get('participation_choice', 'participate')
assert choice_col in spec.columns, \
"couldn't find participation choice column '%s' in spec"
PARTICIPATE_CHOICE = spec.columns.get_loc(choice_col)
MAX_ITERATIONS = model_settings.get('max_participation_choice_iterations', 5000)
trace_label = tracing.extend_trace_label(trace_label, 'participants_chooser')
candidates = choosers.copy()
choices_list = []
rands_list = []
num_tours_remaining = len(candidates.tour_id.unique())
logger.info('%s %s joint tours to satisfy.', trace_label, num_tours_remaining,)
iter = 0
while candidates.shape[0] > 0:
iter += 1
if iter > MAX_ITERATIONS:
logger.warning('%s max iterations exceeded (%s).', trace_label, MAX_ITERATIONS)
diagnostic_cols = ['tour_id', 'household_id', 'composition', 'adult']
unsatisfied_candidates = candidates[diagnostic_cols].join(probs)
tracing.write_csv(unsatisfied_candidates,
file_name='%s.UNSATISFIED' % trace_label, transpose=False)
print(unsatisfied_candidates.head(20))
assert False
choices, rands = logit.make_choices(probs, trace_label=trace_label, trace_choosers=choosers)
participate = (choices == PARTICIPATE_CHOICE)
# satisfaction indexed by tour_id
tour_satisfaction = get_tour_satisfaction(candidates, participate)
num_tours_satisfied_this_iter = tour_satisfaction.sum()
if num_tours_satisfied_this_iter > 0:
num_tours_remaining -= num_tours_satisfied_this_iter
satisfied = reindex(tour_satisfaction, candidates.tour_id)
choices_list.append(choices[satisfied])
rands_list.append(rands[satisfied])
# remove candidates of satisfied tours
probs = probs[~satisfied]
candidates = candidates[~satisfied]
logger.info('%s iteration %s : %s joint tours satisfied %s remaining' %
(trace_label, iter, num_tours_satisfied_this_iter, num_tours_remaining,))
choices = pd.concat(choices_list)
rands = pd.concat(rands_list).reindex(choosers.index)
# reindex choices and rands to match probs and v index
choices = choices.reindex(choosers.index)
rands = rands.reindex(choosers.index)
assert choices.index.equals(choosers.index)
assert rands.index.equals(choosers.index)
logger.info('%s %s iterations to satisfy all joint tours.', trace_label, iter,)
return choices, rands

@danielsclint danielsclint added First Contribution These are good first issues for people wanting to dive into the ASIM software. Performance Changes that improve performance labels Dec 16, 2021
@dhensle
Copy link
Contributor

dhensle commented Oct 1, 2024

#569

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
First Contribution These are good first issues for people wanting to dive into the ASIM software. Performance Changes that improve performance
Projects
None yet
Development

No branches or pull requests

2 participants