diff --git a/HOW_TO_RELEASE.md b/HOW_TO_RELEASE.md index fdfc60719..237d7e414 100644 --- a/HOW_TO_RELEASE.md +++ b/HOW_TO_RELEASE.md @@ -42,15 +42,16 @@ 00. Run black to ensure that the codebase passes all style checks. This check should only take a few seconds. These checks are also done on - Travis and are platform independent, so they should not be necessary to + GitHub Actions and are platform independent, so they should not be necessary to replicate locally, but are listed here for completeness. ```sh black --check --diff . ``` -00. Run the regular test suite on Windows. Travis tests are done on Linux, - but most users are on Windows, and the test suite should also be run - on Windows to ensure that it works on that platform as well. If you +00. Run the regular test suite on Windows. Most GitHub Actions tests are done on Linux, + Linux (it's faster to start up and run a new clean VM for testing) but most + users are on Windows, and the test suite should also be run on Windows to + ensure that it works on that platform as well. If you are not preparing this release on Windows, you should be sure to run at least through this step on a Windows machine before finalizing a release. @@ -135,6 +136,10 @@ ```sh gh release create v1.2.3 ``` + The process of creating and tagging a release will automatically + trigger various GitHub Actions scripts to build, test, and publish the + new release to PyPI and conda forge, assuming there are no errors. + For a development pre-release, include the `--prerelease` argument. As the project's policy is that only formally released code is merged to the main branch, any pre-release should also be built against a diff --git a/activitysim/abm/models/__init__.py b/activitysim/abm/models/__init__.py index 91b802d76..1c288f8c4 100644 --- a/activitysim/abm/models/__init__.py +++ b/activitysim/abm/models/__init__.py @@ -20,6 +20,7 @@ joint_tour_frequency, joint_tour_participation, joint_tour_scheduling, + joint_tour_frequency_composition, location_choice, mandatory_scheduling, mandatory_tour_frequency, diff --git a/activitysim/abm/models/cdap.py b/activitysim/abm/models/cdap.py index b37cf8a9a..f7da93687 100644 --- a/activitysim/abm/models/cdap.py +++ b/activitysim/abm/models/cdap.py @@ -78,6 +78,17 @@ def cdap_simulate(persons_merged, persons, households, chunk_size, trace_hh_id): file_name=model_settings["FIXED_RELATIVE_PROPORTIONS_SPEC"] ) + add_joint_tour_utility = model_settings.get("ADD_JOINT_TOUR_UTILITY", False) + + if add_joint_tour_utility: + # Rules and coefficients for generating cdap joint tour specs for different household sizes + joint_tour_coefficients_file_name = model_settings.get( + "JOINT_TOUR_COEFFICIENTS", "cdap_joint_tour_coefficients.csv" + ) + cdap_joint_tour_coefficients = pd.read_csv( + config.config_file_path(joint_tour_coefficients_file_name), comment="#" + ) + persons_merged = persons_merged.to_frame() # add tour-based chunk_id so we can chunk all trips in tour together @@ -101,11 +112,27 @@ def cdap_simulate(persons_merged, persons, households, chunk_size, trace_hh_id): # (also when multiprocessing locutor might not see all household sizes) logger.info("Pre-building cdap specs") for hhsize in range(2, cdap.MAX_HHSIZE + 1): - spec = cdap.build_cdap_spec(cdap_interaction_coefficients, hhsize, cache=True) + spec = cdap.build_cdap_spec( + cdap_interaction_coefficients, + hhsize, + cache=True, + joint_tour_alt=add_joint_tour_utility, + ) if inject.get_injectable("locutor", False): spec.to_csv( config.output_file_path("cdap_spec_%s.csv" % hhsize), index=True ) + if add_joint_tour_utility: + # build cdap joint tour spec + # joint_spec_dependency = spec.loc[[c for c in spec.index if c.startswith(('M_p', 'N_p', 'H_p'))]] + joint_spec = cdap.build_cdap_joint_spec( + cdap_joint_tour_coefficients, hhsize, cache=True + ) + if inject.get_injectable("locutor", False): + joint_spec.to_csv( + config.output_file_path("cdap_joint_spec_%s.csv" % hhsize), + index=True, + ) if estimator: estimator.write_model_settings(model_settings, "cdap.yaml") @@ -127,17 +154,32 @@ def cdap_simulate(persons_merged, persons, households, chunk_size, trace_hh_id): logger.info("Running cdap_simulate with %d persons", len(persons_merged.index)) - choices = cdap.run_cdap( - persons=persons_merged, - person_type_map=person_type_map, - cdap_indiv_spec=cdap_indiv_spec, - cdap_interaction_coefficients=cdap_interaction_coefficients, - cdap_fixed_relative_proportions=cdap_fixed_relative_proportions, - locals_d=constants, - chunk_size=chunk_size, - trace_hh_id=trace_hh_id, - trace_label=trace_label, - ) + if add_joint_tour_utility: + choices, hh_joint = cdap.run_cdap( + persons=persons_merged, + person_type_map=person_type_map, + cdap_indiv_spec=cdap_indiv_spec, + cdap_interaction_coefficients=cdap_interaction_coefficients, + cdap_fixed_relative_proportions=cdap_fixed_relative_proportions, + locals_d=constants, + chunk_size=chunk_size, + trace_hh_id=trace_hh_id, + trace_label=trace_label, + add_joint_tour_utility=add_joint_tour_utility, + ) + else: + choices = cdap.run_cdap( + persons=persons_merged, + person_type_map=person_type_map, + cdap_indiv_spec=cdap_indiv_spec, + cdap_interaction_coefficients=cdap_interaction_coefficients, + cdap_fixed_relative_proportions=cdap_fixed_relative_proportions, + locals_d=constants, + chunk_size=chunk_size, + trace_hh_id=trace_hh_id, + trace_label=trace_label, + add_joint_tour_utility=add_joint_tour_utility, + ) if estimator: estimator.write_choices(choices) @@ -161,6 +203,11 @@ def cdap_simulate(persons_merged, persons, households, chunk_size, trace_hh_id): # - annotate households table households = households.to_frame() + + if add_joint_tour_utility: + hh_joint = hh_joint.reindex(households.index) + households["has_joint_tour"] = hh_joint + expressions.assign_columns( df=households, model_settings=model_settings.get("annotate_households"), diff --git a/activitysim/abm/models/joint_tour_frequency_composition.py b/activitysim/abm/models/joint_tour_frequency_composition.py new file mode 100644 index 000000000..3e52d27fa --- /dev/null +++ b/activitysim/abm/models/joint_tour_frequency_composition.py @@ -0,0 +1,204 @@ +# ActivitySim +# See full license in LICENSE.txt. +import logging + +import numpy as np +import pandas as pd +import os +from activitysim.core.interaction_simulate import interaction_simulate + +from activitysim.core import simulate +from activitysim.core import tracing +from activitysim.core import pipeline +from activitysim.core import config +from activitysim.core import inject +from activitysim.core import expressions + +from .util import estimation + +from .util.overlap import hh_time_window_overlap +from .util.tour_frequency import process_joint_tours_frequency_composition + +logger = logging.getLogger(__name__) + + +@inject.step() +def joint_tour_frequency_composition( + households_merged, persons, chunk_size, trace_hh_id +): + """ + This model predicts the frequency and composition of fully joint tours. + """ + + trace_label = "joint_tour_frequency_composition" + model_settings_file_name = "joint_tour_frequency_composition.yaml" + + model_settings = config.read_model_settings(model_settings_file_name) + + alt_tdd = simulate.read_model_alts( + "joint_tour_frequency_composition_alternatives.csv", set_index="alt" + ) + + # - only interested in households with more than one cdap travel_active person and + # - at least one non-preschooler + households_merged = households_merged.to_frame() + choosers = households_merged[households_merged.participates_in_jtf_model].copy() + + # - only interested in persons in choosers households + persons = persons.to_frame() + persons = persons[persons.household_id.isin(choosers.index)] + + logger.info("Running %s with %d households", trace_label, len(choosers)) + + # alt preprocessor + alt_preprocessor_settings = model_settings.get("ALTS_PREPROCESSOR", None) + if alt_preprocessor_settings: + + locals_dict = {} + + alt_tdd = alt_tdd.copy() + + expressions.assign_columns( + df=alt_tdd, + model_settings=alt_preprocessor_settings, + locals_dict=locals_dict, + trace_label=trace_label, + ) + + # - preprocessor + preprocessor_settings = model_settings.get("preprocessor", None) + if preprocessor_settings: + + locals_dict = { + "persons": persons, + "hh_time_window_overlap": hh_time_window_overlap, + } + + expressions.assign_columns( + df=choosers, + model_settings=preprocessor_settings, + locals_dict=locals_dict, + trace_label=trace_label, + ) + + estimator = estimation.manager.begin_estimation("joint_tour_frequency_composition") + + model_spec = simulate.read_model_spec(file_name=model_settings["SPEC"]) + coefficients_df = simulate.read_model_coefficients(model_settings) + model_spec = simulate.eval_coefficients(model_spec, coefficients_df, estimator) + + constants = config.get_model_constants(model_settings) + + if estimator: + estimator.write_spec(model_settings) + estimator.write_model_settings(model_settings, model_settings_file_name) + estimator.write_coefficients(coefficients_df, model_settings) + estimator.write_choosers(choosers) + estimator.write_alternatives(alts) + + assert choosers.index.name == "household_id" + assert "household_id" not in choosers.columns + choosers["household_id"] = choosers.index + + estimator.set_chooser_id(choosers.index.name) + + # The choice value 'joint_tour_frequency_composition' assigned by interaction_simulate + # is the index value of the chosen alternative in the alternatives table. + choices = interaction_simulate( + choosers=choosers, + alternatives=alt_tdd, + spec=model_spec, + locals_d=constants, + chunk_size=chunk_size, + trace_label=trace_label, + trace_choice_name=trace_label, + estimator=estimator, + ) + + if estimator: + estimator.write_choices(choices) + choices = estimator.get_survey_values( + choices, "households", "joint_tour_frequency_composition" + ) + estimator.write_override_choices(choices) + estimator.end_estimation() + + # add joint tour frequency composition column to household table + households_merged["joint_tour_frequency_composition"] = choices.reindex( + households_merged.index + ).fillna(0) + + # - create joint_tours based on choices + + # - we need a person_id in order to generate the tour index (and for register_traceable_table) + # - but we don't know the tour participants yet + # - so we arbitrarily choose the first person in the household + # - to be point person for the purpose of generating an index and setting origin + temp_point_persons = persons.loc[persons.PNUM == 1] + temp_point_persons["person_id"] = temp_point_persons.index + temp_point_persons = temp_point_persons.set_index("household_id") + temp_point_persons = temp_point_persons[["person_id", "home_zone_id"]] + + # create a tours table of tour_category "joint" and different tour_types (e.g. shopping, eat) + # and add the composition column (adults or children or mixed) to the tour + + # Choices + # hhid choice + # 11111 1 + # 22222 2 + # 33333 3 + + # Alts + # alt purpose1 purpose2 party1 party2 eat shop + # 1 5 0 3 0 1 0 + # 2 5 6 1 3 1 1 + # 3 6 0 1 0 0 1 + + # Joint Tours + # hhid type category composition + # 11111 eat joint mixed + # 22222 eat joint adults + # 22222 shop joint mixed + # 33333 shop joint adults + + joint_tours = process_joint_tours_frequency_composition( + choices, alt_tdd, temp_point_persons + ) + + tours = pipeline.extend_table("tours", joint_tours) + + tracing.register_traceable_table("tours", joint_tours) + pipeline.get_rn_generator().add_channel("tours", joint_tours) + + # we expect there to be an alt with no tours - which we can use to backfill non-travelers + no_tours_alt = 0 + households_merged["joint_tour_frequency_composition"] = ( + choices.reindex(households_merged.index).fillna(no_tours_alt).astype(str) + ) + + households_merged["num_hh_joint_tours"] = ( + joint_tours.groupby("household_id") + .size() + .reindex(households_merged.index) + .fillna(0) + .astype(np.int8) + ) + + pipeline.replace_table("households", households_merged) + + tracing.print_summary( + "joint_tour_frequency_composition", + households_merged.joint_tour_frequency_composition, + value_counts=True, + ) + + if trace_hh_id: + tracing.trace_df( + households_merged, label="joint_tour_frequency_composition.households" + ) + + tracing.trace_df( + joint_tours, + label="joint_tour_frequency_composition.joint_tours", + slicer="household_id", + ) diff --git a/activitysim/abm/models/joint_tour_participation.py b/activitysim/abm/models/joint_tour_participation.py index 939d9fedd..ee8658ae5 100644 --- a/activitysim/abm/models/joint_tour_participation.py +++ b/activitysim/abm/models/joint_tour_participation.py @@ -3,6 +3,7 @@ import logging import pandas as pd +import numpy as np from activitysim.abm.models.util.canonical_ids import MAX_PARTICIPANT_PNUM from activitysim.core import ( @@ -57,7 +58,7 @@ def joint_tour_participation_candidates(joint_tours, persons_merged): # - stable (predictable) index # if this happens, participant_id may not be unique - # channel random seeds will overlap at MAX_PARTICIPANT_PNUM (not probably a big deal) + # channel random seeds will overlap at MAX_PARTICIPANT_PNUM (probably not a big deal) # and estimation infer will fail assert ( candidates.PNUM.max() < MAX_PARTICIPANT_PNUM @@ -65,6 +66,7 @@ def joint_tour_participation_candidates(joint_tours, persons_merged): candidates["participant_id"] = ( candidates[joint_tours.index.name] * MAX_PARTICIPANT_PNUM ) + candidates.PNUM + candidates["participant_id"] = candidates["participant_id"].astype(np.uint64) candidates.set_index( "participant_id", drop=True, inplace=True, verify_integrity=True ) @@ -198,7 +200,19 @@ def participants_chooser(probs, choosers, spec, trace_label): transpose=False, ) print(unsatisfied_candidates.head(20)) - assert False + + if model_settings.get("FORCE_PARTICIPATION", False): + logger.warning( + f"Forcing joint tour participation for {num_tours_remaining} tours." + ) + # anybody with probability > 0 is forced to join the joint tour + probs[choice_col] = np.where(probs[choice_col] > 0, 1, 0) + non_choice_col = [col for col in probs.columns if col != choice_col][0] + probs[non_choice_col] = 1 - probs[choice_col] + else: + raise RuntimeError( + f"{num_tours_remaining} tours could not be satisfied after {iter} iterations" + ) choices, rands = logit.make_choices( probs, trace_label=trace_label, trace_choosers=choosers @@ -209,6 +223,13 @@ def participants_chooser(probs, choosers, spec, trace_label): tour_satisfaction = get_tour_satisfaction(candidates, participate) num_tours_satisfied_this_iter = tour_satisfaction.sum() + if (iter > MAX_ITERATIONS) & ( + num_tours_remaining != num_tours_satisfied_this_iter + ): + logger.error( + f"Still do not satisfy participation for {num_tours_remaining - num_tours_satisfied_this_iter} tours." + ) + if num_tours_satisfied_this_iter > 0: num_tours_remaining -= num_tours_satisfied_this_iter diff --git a/activitysim/abm/models/location_choice.py b/activitysim/abm/models/location_choice.py index 1a7564942..dd5e279b3 100644 --- a/activitysim/abm/models/location_choice.py +++ b/activitysim/abm/models/location_choice.py @@ -426,6 +426,8 @@ def run_location_sample( ) dest_size_terms = dest_size_terms[dest_size_terms.size_term > 0] + assert len(dest_size_terms) > 0, "No destination with available size terms" + # by default, enable presampling for multizone systems, unless they disable it in settings file pre_sample_taz = not (network_los.zone_system == los.ONE_ZONE) if pre_sample_taz and not config.setting("want_dest_choice_presampling", True): diff --git a/activitysim/abm/models/non_mandatory_tour_frequency.py b/activitysim/abm/models/non_mandatory_tour_frequency.py index 93b36b2f4..521f49c47 100644 --- a/activitysim/abm/models/non_mandatory_tour_frequency.py +++ b/activitysim/abm/models/non_mandatory_tour_frequency.py @@ -271,7 +271,7 @@ def non_mandatory_tour_frequency(persons, persons_merged, chunk_size, trace_hh_i no_tours_alt = (alternatives.sum(axis=1) == 0).index[0] # need to reindex as we only handled persons with cdap_activity in ['M', 'N'] persons["non_mandatory_tour_frequency"] = ( - choices.reindex(persons.index).fillna(no_tours_alt).astype(np.int8) + choices.reindex(persons.index).fillna(no_tours_alt).astype(np.int16) ) """ diff --git a/activitysim/abm/models/parking_location_choice.py b/activitysim/abm/models/parking_location_choice.py index 3b10f32b4..a87703b8b 100644 --- a/activitysim/abm/models/parking_location_choice.py +++ b/activitysim/abm/models/parking_location_choice.py @@ -232,7 +232,6 @@ def run_parking_destination( alt_column_filter_name = model_settings.get("ALTERNATIVE_FILTER_COLUMN_NAME") alternatives = land_use[land_use[alt_column_filter_name]] - alternatives.index.name = parking_location_column_name choices_list = [] diff --git a/activitysim/abm/models/telecommute_frequency.py b/activitysim/abm/models/telecommute_frequency.py index cc1eec489..4596a8911 100755 --- a/activitysim/abm/models/telecommute_frequency.py +++ b/activitysim/abm/models/telecommute_frequency.py @@ -57,7 +57,7 @@ def telecommute_frequency(persons_merged, persons, chunk_size, trace_hh_id): if estimator: estimator.write_model_settings(model_settings, model_settings_file_name) estimator.write_spec(model_settings) - estimator.write_coefficients(coefficients_df) + estimator.write_coefficients(coefficients_df, model_settings) estimator.write_choosers(choosers) choices = simulate.simple_simulate( diff --git a/activitysim/abm/models/transit_pass_ownership.py b/activitysim/abm/models/transit_pass_ownership.py index 6507ab825..92d97080f 100644 --- a/activitysim/abm/models/transit_pass_ownership.py +++ b/activitysim/abm/models/transit_pass_ownership.py @@ -51,7 +51,7 @@ def transit_pass_ownership(persons_merged, persons, chunk_size, trace_hh_id): if estimator: estimator.write_model_settings(model_settings, model_settings_file_name) estimator.write_spec(model_settings) - estimator.write_coefficients(coefficients_df) + estimator.write_coefficients(coefficients_df, model_settings) estimator.write_choosers(choosers) choices = simulate.simple_simulate( diff --git a/activitysim/abm/models/transit_pass_subsidy.py b/activitysim/abm/models/transit_pass_subsidy.py index 4e513a661..45a118fda 100644 --- a/activitysim/abm/models/transit_pass_subsidy.py +++ b/activitysim/abm/models/transit_pass_subsidy.py @@ -51,7 +51,7 @@ def transit_pass_subsidy(persons_merged, persons, chunk_size, trace_hh_id): if estimator: estimator.write_model_settings(model_settings, model_settings_file_name) estimator.write_spec(model_settings) - estimator.write_coefficients(coefficients_df) + estimator.write_coefficients(coefficients_df, model_settings) estimator.write_choosers(choosers) choices = simulate.simple_simulate( diff --git a/activitysim/abm/models/trip_mode_choice.py b/activitysim/abm/models/trip_mode_choice.py index 54586a448..e7bb200e4 100644 --- a/activitysim/abm/models/trip_mode_choice.py +++ b/activitysim/abm/models/trip_mode_choice.py @@ -164,8 +164,10 @@ def trip_mode_choice(trips, network_los, chunk_size, trace_hh_id): model_spec = simulate.read_model_spec(file_name=model_settings["SPEC"]) nest_spec = config.get_logit_model_settings(model_settings) + cols_to_keep = model_settings.get("CHOOSER_COLS_TO_KEEP", None) choices_list = [] + cols_to_keep_list = [] for primary_purpose, trips_segment in trips_merged.groupby("primary_purpose"): segment_trace_label = tracing.extend_trace_label(trace_label, primary_purpose) @@ -250,6 +252,14 @@ def trip_mode_choice(trips, network_los, chunk_size, trace_hh_id): ) choices_list.append(choices) + if cols_to_keep: + cols_not_in_choosers = [ + col for col in cols_to_keep if col not in trips_segment.columns + ] + assert ( + len(cols_not_in_choosers) == 0 + ), "{cols_not_in_choosers} from CHOOSER_COLS_TO_KEEP is not in the choosers dataframe" + cols_to_keep_list.append(trips_segment[cols_to_keep]) choices_df = pd.concat(choices_list) @@ -279,6 +289,12 @@ def trip_mode_choice(trips, network_los, chunk_size, trace_hh_id): estimator.write_override_choices(choices_df.trip_mode) estimator.end_estimation() trips_df = trips.to_frame() + + # adding columns from the chooser table to include in final output + if len(cols_to_keep_list) > 0: + cols_to_keep_df = pd.concat(cols_to_keep_list) + choices_df = pd.concat([choices_df, cols_to_keep_df], axis=1) + assign_in_place(trips_df, choices_df) if pipeline.is_table("school_escort_tours") & model_settings.get( @@ -301,7 +317,7 @@ def trip_mode_choice(trips, network_los, chunk_size, trace_hh_id): pipeline.replace_table("trips", trips_df) if model_settings.get("annotate_trips"): - annotate.annotate_trips(model_settings, trace_label) + annotate.annotate_trips(model_settings, trace_label, locals_dict) if trace_hh_id: tracing.trace_df( diff --git a/activitysim/abm/models/trip_scheduling.py b/activitysim/abm/models/trip_scheduling.py index f8345650d..54c3eb201 100644 --- a/activitysim/abm/models/trip_scheduling.py +++ b/activitysim/abm/models/trip_scheduling.py @@ -1,6 +1,7 @@ # ActivitySim # See full license in LICENSE.txt. import logging +import warnings from builtins import range import numpy as np @@ -8,11 +9,11 @@ from activitysim.abm.models.util import estimation from activitysim.abm.models.util.trip import cleanup_failed_trips, failed_trip_cohorts -from activitysim.core import chunk, config, inject, logit, pipeline, tracing +from activitysim.core import chunk, config, expressions, inject, pipeline, tracing from activitysim.core.util import reindex -from .util.school_escort_tours_trips import split_out_school_escorting_trips from .util import probabilistic_scheduling as ps +from .util.school_escort_tours_trips import split_out_school_escorting_trips logger = logging.getLogger(__name__) @@ -36,6 +37,7 @@ DEPARTURE_MODE = "departure" DURATION_MODE = "stop_duration" +RELATIVE_MODE = "relative" PROBS_JOIN_COLUMNS_DEPARTURE_BASED = [ "primary_purpose", "outbound", @@ -43,6 +45,23 @@ "trip_num", ] PROBS_JOIN_COLUMNS_DURATION_BASED = ["outbound", "stop_num"] +PROBS_JOIN_COLUMNS_RELATIVE_BASED = ["outbound", "periods_left"] + + +def _logic_version(model_settings): + logic_version = model_settings.get("logic_version", None) + if logic_version is None: + warnings.warn( + "The trip_scheduling component now has a logic_version setting " + "to control how the scheduling rules are applied. The default " + "logic_version is currently set at `1` but may be moved up in " + "the future. Explicitly set `logic_version` to 2 in the model " + "settings to upgrade your model logic now, or set it to 1 to " + "suppress this message.", + FutureWarning, + ) + logic_version = 1 + return logic_version def set_tour_hour(trips, tours): @@ -106,7 +125,7 @@ def set_stop_num(trips): trips["stop_num"] = trips.stop_num.where(trips["outbound"], trips["trip_num"]) -def update_tour_earliest(trips, outbound_choices): +def update_tour_earliest(trips, outbound_choices, logic_version: int): """ Updates "earliest" column for inbound trips based on the maximum outbound trip departure time of the tour. @@ -119,6 +138,14 @@ def update_tour_earliest(trips, outbound_choices): outbound_choices: pd.Series time periods depart choices, one per trip (except for trips with zero probs) + logic_version : int + Logic version 1 is the original ActivitySim implementation, which + sets the "earliest" value to the max outbound departure for all + inbound trips, regardless of what that max outbound departure value + is (even if it is NA). Logic version 2 introduces a change whereby + that assignment is only made if the max outbound departure value is + not NA. + Returns ------- modifies trips in place @@ -142,9 +169,19 @@ def update_tour_earliest(trips, outbound_choices): # set the trips "earliest" column equal to the max outbound departure # time for all inbound trips. preserve values that were used for outbound trips - tmp_trips["earliest"] = tmp_trips["earliest"].where( - tmp_trips["outbound"], tmp_trips["max_outbound_departure"] - ) + # FIXME - extra logic added because max_outbound_departure can be NA if previous failed trip was removed + if logic_version == 1: + tmp_trips["earliest"] = tmp_trips["earliest"].where( + tmp_trips["outbound"], tmp_trips["max_outbound_departure"] + ) + elif logic_version > 1: + tmp_trips["earliest"] = np.where( + ~tmp_trips["outbound"] & ~tmp_trips["max_outbound_departure"].isna(), + tmp_trips["max_outbound_departure"], + tmp_trips["earliest"], + ) + else: + raise ValueError(f"bad logic_version: {logic_version}") trips["earliest"] = tmp_trips["earliest"].reindex(trips.index) @@ -181,6 +218,7 @@ def schedule_trips_in_leg( failfix = model_settings.get(FAILFIX, FAILFIX_DEFAULT) depart_alt_base = model_settings.get("DEPART_ALT_BASE", 0) scheduling_mode = model_settings.get("scheduling_mode", "departure") + preprocessor_settings = model_settings.get("preprocessor", None) if scheduling_mode == "departure": probs_join_cols = model_settings.get( @@ -190,10 +228,14 @@ def schedule_trips_in_leg( probs_join_cols = model_settings.get( "probs_join_cols", PROBS_JOIN_COLUMNS_DURATION_BASED ) + elif scheduling_mode == "relative": + probs_join_cols = model_settings.get( + "probs_join_cols", PROBS_JOIN_COLUMNS_RELATIVE_BASED + ) else: logger.error( "Invalid scheduling mode specified: {0}.".format(scheduling_mode), - "Please select one of ['departure', 'stop_duration'] and try again.", + "Please select one of ['departure', 'stop_duration', 'relative'] and try again.", ) # logger.debug("%s scheduling %s trips" % (trace_label, trips.shape[0])) @@ -232,18 +274,34 @@ def schedule_trips_in_leg( ADJUST_NEXT_DEPART_COL = "latest" trips.next_trip_id = trips.next_trip_id.where(~is_final, NO_TRIP_ID) + network_los = inject.get_injectable("network_los") + locals_dict = {"network_los": network_los} + locals_dict.update(config.get_model_constants(model_settings)) + first_trip_in_leg = True for i in range(trips.trip_num.min(), trips.trip_num.max() + 1): + nth_trace_label = tracing.extend_trace_label(trace_label, "num_%s" % i) - if outbound or scheduling_mode == DURATION_MODE: + # - annotate trips + if preprocessor_settings: + expressions.assign_columns( + df=trips, + model_settings=preprocessor_settings, + locals_dict=locals_dict, + trace_label=nth_trace_label, + ) + + if ( + outbound + or (scheduling_mode == DURATION_MODE) + or (scheduling_mode == RELATIVE_MODE) + ): # iterate in ascending trip_num order nth_trips = trips[trips.trip_num == i] else: # iterate over inbound trips in descending trip_num order, skipping the final trip nth_trips = trips[trips.trip_num == trips.trip_count - i] - nth_trace_label = tracing.extend_trace_label(trace_label, "num_%s" % i) - choices = ps.make_scheduling_choices( nth_trips, scheduling_mode, @@ -265,6 +323,17 @@ def schedule_trips_in_leg( ) choices = choices.fillna(trips[ADJUST_NEXT_DEPART_COL]) + if scheduling_mode == RELATIVE_MODE: + # choices are relative to the previous departure time + choices = nth_trips.earliest + choices + # need to update the departure time based on the choice + logic_version = _logic_version(model_settings) + if logic_version == 1: + raise ValueError( + "cannot use logic version 1 with 'relative' scheduling mode" + ) + update_tour_earliest(trips, choices, logic_version) + # adjust allowed depart range of next trip has_next_trip = nth_trips.next_trip_id != NO_TRIP_ID if has_next_trip.any(): @@ -299,7 +368,6 @@ def run_trip_scheduling( trace_hh_id, trace_label, ): - set_tour_hour(trips_chunk, tours) set_stop_num(trips_chunk) @@ -328,7 +396,7 @@ def run_trip_scheduling( # departure time of last outbound trips must constrain # departure times for initial inbound trips - update_tour_earliest(trips_chunk, choices) + update_tour_earliest(trips_chunk, choices, _logic_version(model_settings)) if (~trips_chunk.outbound).any(): leg_chunk = trips_chunk[~trips_chunk.outbound] @@ -353,7 +421,6 @@ def run_trip_scheduling( @inject.step() def trip_scheduling(trips, tours, chunk_size, trace_hh_id): - """ Trip scheduling assigns depart times for trips within the start, end limits of the tour. @@ -437,9 +504,9 @@ def trip_scheduling(trips, tours, chunk_size, trace_hh_id): ] estimator.write_choosers(trips_df[chooser_cols_for_estimation]) - probs_spec = pd.read_csv( - config.config_file_path("trip_scheduling_probs.csv"), comment="#" - ) + probs_spec_file = model_settings.get("PROBS_SPEC", "trip_scheduling_probs.csv") + logger.debug(f"probs_spec_file: {config.config_file_path(probs_spec_file)}") + probs_spec = pd.read_csv(config.config_file_path(probs_spec_file), comment="#") # FIXME for now, not really doing estimation for probabilistic model - just overwriting choices # besides, it isn't clear that named coefficients would be helpful if we had some form of estimation # coefficients_df = simulate.read_model_coefficients(model_settings) @@ -465,13 +532,10 @@ def trip_scheduling(trips, tours, chunk_size, trace_hh_id): ) in chunk.adaptive_chunked_choosers_by_chunk_id( trips_df, chunk_size, trace_label, trace_label ): - i = 0 while (i < max_iterations) and not trips_chunk.empty: - # only chunk log first iteration since memory use declines with each iteration with chunk.chunk_log(trace_label) if i == 0 else chunk.chunk_log_skip(): - i += 1 is_last_iteration = i == max_iterations @@ -499,6 +563,11 @@ def trip_scheduling(trips, tours, chunk_size, trace_hh_id): failed = choices.reindex(trips_chunk.index).isnull() logger.info("%s %s failed", trace_label_i, failed.sum()) + if (failed.sum() > 0) & ( + model_settings.get("scheduling_mode") == "relative" + ): + raise RuntimeError("failed trips with relative scheduling mode") + if not is_last_iteration: # boolean series of trips whose leg scheduling failed failed_cohorts = failed_trip_cohorts(trips_chunk, failed) diff --git a/activitysim/abm/models/util/annotate.py b/activitysim/abm/models/util/annotate.py index a7ef4f54c..e50519b38 100644 --- a/activitysim/abm/models/util/annotate.py +++ b/activitysim/abm/models/util/annotate.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) -def annotate_tours(model_settings, trace_label): +def annotate_tours(model_settings, trace_label, locals_dict={}): """ Add columns to the tours table in the pipeline according to spec. @@ -28,12 +28,13 @@ def annotate_tours(model_settings, trace_label): expressions.assign_columns( df=tours, model_settings=model_settings.get("annotate_tours"), + locals_dict=locals_dict, trace_label=tracing.extend_trace_label(trace_label, "annotate_tours"), ) pipeline.replace_table("tours", tours) -def annotate_trips(model_settings, trace_label): +def annotate_trips(model_settings, trace_label, locals_dict={}): """ Add columns to the trips table in the pipeline according to spec. @@ -46,6 +47,7 @@ def annotate_trips(model_settings, trace_label): expressions.assign_columns( df=trips, model_settings=model_settings.get("annotate_trips"), + locals_dict=locals_dict, trace_label=tracing.extend_trace_label(trace_label, "annotate_trips"), ) pipeline.replace_table("trips", trips) diff --git a/activitysim/abm/models/util/cdap.py b/activitysim/abm/models/util/cdap.py index 7e0f55186..b71d5128a 100644 --- a/activitysim/abm/models/util/cdap.py +++ b/activitysim/abm/models/util/cdap.py @@ -195,6 +195,12 @@ def individual_utilities( useful_columns = [_hh_id_, _ptype_, "cdap_rank", _hh_size_] indiv_utils[useful_columns] = persons[useful_columns] + # add attributes for joint tour utility + model_settings = config.read_model_settings("cdap.yaml") + additional_useful_columns = model_settings.get("JOINT_TOUR_USEFUL_COLUMNS", None) + if additional_useful_columns is not None: + indiv_utils[additional_useful_columns] = persons[additional_useful_columns] + if trace_hh_id: tracing.trace_df( indiv_utils, @@ -259,6 +265,10 @@ def cached_spec_name(hhsize): return "cdap_spec_%s" % hhsize +def cached_joint_spec_name(hhsize): + return "cdap_joint_spec_%s" % hhsize + + def get_cached_spec(hhsize): spec_name = cached_spec_name(hhsize) @@ -281,14 +291,39 @@ def get_cached_spec(hhsize): return None +def get_cached_joint_spec(hhsize): + + spec_name = cached_joint_spec_name(hhsize) + + spec = inject.get_injectable(spec_name, None) + if spec is not None: + logger.debug( + "build_cdap_joint_spec returning cached injectable spec %s", spec_name + ) + return spec + + return None + + def cache_spec(hhsize, spec): spec_name = cached_spec_name(hhsize) # cache as injectable inject.add_injectable(spec_name, spec) +def cache_joint_spec(hhsize, spec): + spec_name = cached_joint_spec_name(hhsize) + # cache as injectable + inject.add_injectable(spec_name, spec) + + def build_cdap_spec( - interaction_coefficients, hhsize, trace_spec=False, trace_label=None, cache=True + interaction_coefficients, + hhsize, + trace_spec=False, + trace_label=None, + cache=True, + joint_tour_alt=False, ): """ Build a spec file for computing utilities of alternative household member interaction patterns @@ -355,6 +390,14 @@ def build_cdap_spec( # e.g. ['HH', 'HM', 'HN', 'MH', 'MM', 'MN', 'NH', 'NM', 'NN'] for hhsize=2 alternatives = ["".join(tup) for tup in itertools.product("HMN", repeat=hhsize)] + if joint_tour_alt: + joint_alternatives = [ + "".join(tup) + "J" + for tup in itertools.product("HMN", repeat=hhsize) + if tup.count("M") + tup.count("N") >= 2 + ] + alternatives = alternatives + joint_alternatives + # spec df has expression column plus a column for each alternative spec = pd.DataFrame(columns=[expression_name] + alternatives) @@ -482,6 +525,207 @@ def build_cdap_spec( return spec +def build_cdap_joint_spec( + joint_tour_coefficients, hhsize, trace_spec=False, trace_label=None, cache=True +): + """ + Build a spec file for computing joint tour utilities of alternative household member for households of specified size. + We generate this spec automatically from a table of rules and coefficients because the + interaction rules are fairly simple and can be expressed compactly whereas + there is a lot of redundancy between the spec files for different household sizes, as well as + in the vectorized expression of the interaction alternatives within the spec file itself + joint_tour_coefficients has five columns: + label + label of the expression + description + description of the expression + dependency + if the expression is dependent on alternative, and which alternative is it dependent on + (e.g. M_px, N_px, H_px) + expression + expression of the utility term + coefficient + The coefficient to apply for the alternative + The generated spec will have the eval expression in the index, and a utility column for each + alternative (e.g. ['HH', 'HM', 'HN', 'MH', 'MM', 'MN', 'NH', 'NM', 'NN', 'MMJ', 'MNJ', 'NMJ', 'NNJ'] for hhsize 2 with joint alts) + Parameters + ---------- + joint_tour_coefficients : pandas.DataFrame + Rules and coefficients for generating joint tour specs for different household sizes + hhsize : int + household size for which the spec should be built. + Returns + ------- + spec: pandas.DataFrame + """ + + t0 = tracing.print_elapsed_time() + + # cdap joint spec is same for all households of MAX_HHSIZE and greater + hhsize = min(hhsize, MAX_HHSIZE) + + if cache: + spec = get_cached_joint_spec(hhsize) + if spec is not None: + return spec + + expression_name = "Expression" + + # generate a list of activity pattern alternatives for this hhsize + # e.g. ['HH', 'HM', 'HN', 'MH', 'MM', 'MN', 'NH', 'NM', 'NN'] for hhsize=2 + alternatives = ["".join(tup) for tup in itertools.product("HMN", repeat=hhsize)] + + joint_alternatives = [ + "".join(tup) + "J" + for tup in itertools.product("HMN", repeat=hhsize) + if tup.count("M") + tup.count("N") >= 2 + ] + alternatives = alternatives + joint_alternatives + + # spec df has expression column plus a column for each alternative + spec = pd.DataFrame(columns=[expression_name] + alternatives) + + # Before processing the interaction_coefficients, we add add rows to the spec to carry + # the alternative utilities previously computed for each individual into all hh alternative + # columns in which the individual assigned that alternative. The Expression column contains + # the name of the choosers column with that individuals utility for the individual alternative + # and the hh alternative columns that should receive that utility are given a value of 1 + # e.g. M_p1 is a column in choosers with the individual utility to person p1 of alternative M + # Expression MM MN MH NM NN NH HM HN HH + # M_p1 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 + # N_p1 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 + for pnum in range(1, hhsize + 1): + for activity in ["M", "N", "H"]: + + new_row_index = len(spec) + spec.loc[new_row_index, expression_name] = add_pn(activity, pnum) + + # list of alternative columns where person pnum has expression activity + # e.g. for M_p1 we want the columns where activity M is in position p1 + alternative_columns = [ + alt for alt in alternatives if alt[pnum - 1] == activity + ] + spec.loc[new_row_index, alternative_columns] = 1 + + # for each row in the joint util table + for row in joint_tour_coefficients.itertuples(): + + # if there is no dependencies + if row.dependency is np.nan: + expression = row.Expression + # add a new row to spec + new_row_index = len(spec) + spec.loc[new_row_index, expression_name] = expression + spec.loc[new_row_index, alternatives] = row.coefficient + # if there is dependencies + else: + dependency_name = row.dependency + expression = row.Expression + coefficient = row.coefficient + if dependency_name in ["M_px", "N_px", "H_px"]: + if "_pxprod" in expression: + prod_conds = row.Expression.split("|") + expanded_expressions = [ + tup + for tup in itertools.product( + range(len(prod_conds)), repeat=hhsize + ) + ] + for expression_tup in expanded_expressions: + expression_list = [] + dependency_list = [] + for counter in range(len(expression_tup)): + expression_list.append( + prod_conds[expression_tup[counter]].replace( + "xprod", str(counter + 1) + ) + ) + if expression_tup[counter] == 0: + dependency_list.append( + dependency_name.replace("x", str(counter + 1)) + ) + + expression_value = "&".join(expression_list) + dependency_value = pd.Series( + np.ones(len(alternatives)), index=alternatives + ) + if len(dependency_list) > 0: + for dependency in dependency_list: + # temp = spec.loc[spec[expression_name]==dependency, alternatives].squeeze().fillna(0) + dependency_value *= ( + spec.loc[ + spec[expression_name] == dependency, + alternatives, + ] + .squeeze() + .fillna(0) + ) + + # add a new row to spec + new_row_index = len(spec) + spec.loc[new_row_index] = dependency_value + spec.loc[new_row_index, expression_name] = expression_value + spec.loc[new_row_index, alternatives] = ( + spec.loc[new_row_index, alternatives] * coefficient + ) + + elif "_px" in expression: + for pnum in range(1, hhsize + 1): + dependency_name = row.dependency.replace("x", str(pnum)) + expression = row.Expression.replace("x", str(pnum)) + + # add a new row to spec + new_row_index = len(spec) + spec.loc[new_row_index] = spec.loc[ + spec[expression_name] == dependency_name + ].squeeze() + spec.loc[new_row_index, expression_name] = expression + spec.loc[new_row_index, alternatives] = ( + spec.loc[new_row_index, alternatives] * coefficient + ) + + # drop dependency rows + spec = spec[~spec[expression_name].str.startswith(("M_p", "N_p", "H_p"))] + + # eval expression goes in the index + spec.set_index(expression_name, inplace=True) + + for c in spec.columns: + spec[c] = spec[c].fillna(0) + + simulate.uniquify_spec_index(spec) + + # make non-joint alts 0 + for c in alternatives: + if c.endswith("J"): + continue + else: + spec[c] = 0 + + if trace_spec: + tracing.trace_df( + spec, + "%s.hhsize%d_joint_spec" % (trace_label, hhsize), + transpose=False, + slicer="NONE", + ) + + if trace_spec: + tracing.trace_df( + spec, + "%s.hhsize%d_joint_spec_patched" % (trace_label, hhsize), + transpose=False, + slicer="NONE", + ) + + if cache: + cache_joint_spec(hhsize, spec) + + t0 = tracing.print_elapsed_time("build_cdap_joint_spec hh_size %s" % hhsize, t0) + + return spec + + def add_interaction_column(choosers, p_tup): """ Add an interaction column in place to choosers, listing the ptypes of the persons in p_tup @@ -578,6 +822,12 @@ def hh_choosers(indiv_utils, hhsize): # we want to merge the ptype and M, N, and H utilities for each individual in the household merge_cols = [_hh_id_, _ptype_, "M", "N", "H"] + # add attributes for joint tour utility + model_settings = config.read_model_settings("cdap.yaml") + additional_merge_cols = model_settings.get("JOINT_TOUR_USEFUL_COLUMNS", None) + if additional_merge_cols is not None: + merge_cols.extend(additional_merge_cols) + if hhsize > MAX_HHSIZE: raise RuntimeError("hh_choosers hhsize > MAX_HHSIZE") @@ -620,11 +870,19 @@ def hh_choosers(indiv_utils, hhsize): for tup in itertools.combinations(list(range(1, hhsize + 1)), i): add_interaction_column(choosers, tup) + # add hhsize + choosers["hhsize"] = hhsize + return choosers def household_activity_choices( - indiv_utils, interaction_coefficients, hhsize, trace_hh_id=None, trace_label=None + indiv_utils, + interaction_coefficients, + hhsize, + trace_hh_id=None, + trace_label=None, + add_joint_tour_utility=False, ): """ Calculate household utilities for each activity pattern alternative for households of hhsize @@ -669,6 +927,7 @@ def household_activity_choices( hhsize, trace_spec=(trace_hh_id in choosers.index), trace_label=trace_label, + joint_tour_alt=add_joint_tour_utility, ) utils = simulate.eval_utilities(spec, choosers, trace_label=trace_label) @@ -676,6 +935,23 @@ def household_activity_choices( if len(utils.index) == 0: return pd.Series(dtype="float64") + # calculate joint tour utility + if add_joint_tour_utility & (hhsize > 1): + # calculate joint utils + joint_tour_spec = build_cdap_joint_spec( + interaction_coefficients, + hhsize, + trace_spec=(trace_hh_id in choosers.index), + trace_label=trace_label, + ) + + joint_tour_utils = simulate.eval_utilities( + joint_tour_spec, choosers, trace_label=trace_label + ) + + # add joint util to util + utils = utils.add(joint_tour_utils) + probs = logit.utils_to_probs(utils, trace_label=trace_label) # select an activity pattern alternative for each household based on probability @@ -867,6 +1143,7 @@ def _run_cdap( locals_d, trace_hh_id, trace_label, + add_joint_tour_utility, ): """ Implements core run_cdap functionality on persons df (or chunked subset thereof) @@ -909,6 +1186,7 @@ def _run_cdap( hhsize=hhsize, trace_hh_id=trace_hh_id, trace_label=trace_label, + add_joint_tour_utility=add_joint_tour_utility, ) hh_choices_list.append(choices) @@ -940,6 +1218,13 @@ def _run_cdap( persons["cdap_activity"] = person_choices chunk.log_df(trace_label, "persons", persons) + # return household joint tour flag + if add_joint_tour_utility: + hh_activity_choices = hh_activity_choices.to_frame(name="hh_choices") + hh_activity_choices["has_joint_tour"] = hh_activity_choices["hh_choices"].apply( + lambda x: 1 if "J" in x else 0 + ) + # if DUMP: # tracing.trace_df(hh_activity_choices, '%s.DUMP.hh_activity_choices' % trace_label, # transpose=False, slicer='NONE') @@ -951,7 +1236,10 @@ def _run_cdap( del persons chunk.log_df(trace_label, "persons", None) - return result + if add_joint_tour_utility: + return result, hh_activity_choices["has_joint_tour"] + else: + return result def run_cdap( @@ -964,6 +1252,7 @@ def run_cdap( chunk_size=0, trace_hh_id=None, trace_label=None, + add_joint_tour_utility=False, ): """ Choose individual activity patterns for persons. @@ -990,6 +1279,8 @@ def run_cdap( hh_id to trace or None if no hh tracing trace_label : str label for tracing or None if no tracing + add_joint_tour_utility : Bool + cdap model include joint tour utility or not Returns ------- @@ -1011,16 +1302,30 @@ def run_cdap( chunk_trace_label, ) in chunk.adaptive_chunked_choosers_by_chunk_id(persons, chunk_size, trace_label): - cdap_results = _run_cdap( - persons_chunk, - person_type_map, - cdap_indiv_spec, - cdap_interaction_coefficients, - cdap_fixed_relative_proportions, - locals_d, - trace_hh_id, - chunk_trace_label, - ) + if add_joint_tour_utility: + cdap_results, hh_choice_results = _run_cdap( + persons_chunk, + person_type_map, + cdap_indiv_spec, + cdap_interaction_coefficients, + cdap_fixed_relative_proportions, + locals_d, + trace_hh_id, + chunk_trace_label, + add_joint_tour_utility, + ) + else: + cdap_results = _run_cdap( + persons_chunk, + person_type_map, + cdap_indiv_spec, + cdap_interaction_coefficients, + cdap_fixed_relative_proportions, + locals_d, + trace_hh_id, + chunk_trace_label, + add_joint_tour_utility, + ) result_list.append(cdap_results) @@ -1042,4 +1347,8 @@ def run_cdap( ) # return choices column as series - return cdap_results["cdap_activity"] + if add_joint_tour_utility: + return cdap_results["cdap_activity"], hh_choice_results + else: + # return choices column as series + return cdap_results["cdap_activity"] diff --git a/activitysim/abm/models/util/probabilistic_scheduling.py b/activitysim/abm/models/util/probabilistic_scheduling.py index aab2e8d70..6fc7689a6 100644 --- a/activitysim/abm/models/util/probabilistic_scheduling.py +++ b/activitysim/abm/models/util/probabilistic_scheduling.py @@ -172,10 +172,22 @@ def _preprocess_scheduling_probs( ) elif scheduling_mode == "stop_duration": chooser_probs = _preprocess_stop_duration_probs(choosers) + elif scheduling_mode == "relative": + # creating a dataframe with just the trip_id as index and alternatives as columns + probs_cols = [ + c + for c in probs_spec.columns + if ((c not in probs_join_cols) & (c.isnumeric())) + ] + chooser_probs = choosers.loc[:, probs_cols] + chooser_probs = chooser_probs.div(chooser_probs.sum(axis=1), axis=0) + assert ( + ~chooser_probs.isna().values.any() + ), f"Missing probabilities for trips \n {chooser_probs[chooser_probs.isna().any(axis=1)].index}" else: logger.error( "Invalid scheduling mode specified: {0}.".format(scheduling_mode), - "Please select one of ['departure', 'stop_duration'] and try again.", + "Please select one of ['departure', 'stop_duration', 'relative'] and try again.", ) # probs should sum to 1 with residual probs resulting in choice of 'fail' @@ -196,6 +208,12 @@ def _postprocess_scheduling_choices( # convert alt choice index to depart time (setting failed choices to -1) failed = choices == choice_cols.get_loc("fail") + if scheduling_mode == "relative": + if failed.any(): + RuntimeError( + f"Failed trips in realtive mode for {failed.sum()} trips: {choosers[failed]}" + ) + # For the stop duration-based probabilities, the alternatives are offsets that # get applied to trip-specific departure and arrival times, so depart_alt_base # is a column/series rather than a scalar. @@ -334,7 +352,11 @@ def make_scheduling_choices( if failed.any(): choices = choices[~failed] - if all([check_col in choosers_df.columns for check_col in ["earliest", "latest"]]): + if all( + [check_col in choosers_df.columns for check_col in ["earliest", "latest"]] + ) & (scheduling_mode != "relative"): + # check to make sure choice does not come before previously scheduled trip or after end of tour + # does not apply if choices are relative to previous trip depart assert (choices >= choosers_df.earliest[~failed]).all() assert (choices <= choosers_df.latest[~failed]).all() diff --git a/activitysim/abm/models/util/tour_frequency.py b/activitysim/abm/models/util/tour_frequency.py index 37108b564..a73482fe5 100644 --- a/activitysim/abm/models/util/tour_frequency.py +++ b/activitysim/abm/models/util/tour_frequency.py @@ -5,6 +5,7 @@ import numpy as np import pandas as pd +from activitysim.core import config from activitysim.abm.models.util.canonical_ids import set_tour_index from activitysim.core.util import reindex @@ -459,3 +460,283 @@ def process_joint_tours(joint_tour_frequency, joint_tour_frequency_alts, point_p 17978574 joint 4 5143198 """ return tours + + +def process_joint_tours_frequency_composition( + joint_tour_frequency_composition, + joint_tour_frequency_composition_alts, + point_persons, +): + """ + This method processes the joint_tour_frequency_composition column that comes out of + the model of the same name and turns into a DataFrame that represents the + joint tours that were generated + + Parameters + ---------- + joint_tour_frequency_composition : pandas.Series + household joint_tour_frequency_composition (which came out of the joint tour frequency composition model) + indexed by household_id + joint_tour_frequency_composition_alts: DataFrame + A DataFrame which has as a unique index with joint_tour_frequency_composition values + and frequency counts for the tours to be generated for that choice + point_persons : pandas DataFrame + table with columns for (at least) person_ids and home_zone_id indexed by household_id + + Returns + ------- + tours : DataFrame + An example of a tours DataFrame is supplied as a comment in the + source code - it has an index which is a tour identifier, a household_id + column, a tour_type column, composition column and tour_type_num and tour_num columns + which is set to 1 or 2 depending whether it is the first or second joint tour + made by the household. + """ + + assert not joint_tour_frequency_composition.isnull().any() + + tours = process_tours_frequency_composition( + joint_tour_frequency_composition.dropna(), + joint_tour_frequency_composition_alts, + tour_category="joint", + parent_col="household_id", + ) + + assert not tours.index.duplicated().any() + assert point_persons.index.name == "household_id" + + # - assign a temp point person to tour so we can create stable index + tours["person_id"] = reindex(point_persons.person_id, tours.household_id) + tours["origin"] = reindex(point_persons.home_zone_id, tours.household_id) + + # assign stable (predictable) tour_id + set_tour_index(tours, is_joint=True) + + """ + household_id tour_type tour_type_count tour_type_num tour_num tour_count + tour_id + 3209530 320953 disc 1 1 1 2 + 3209531 320953 disc 2 2 2 2 + 23267026 2326702 shop 1 1 1 1 + 17978574 1797857 main 1 1 1 1 + + tour_category tour_category_id person_id + 3209530 joint 4 577234 + 3209531 joint 4 577234 + 23267026 joint 4 1742708 + 17978574 joint 4 5143198 + """ + return tours + + +def process_tours_frequency_composition( + joint_tour_frequency_composition, + joint_tour_frequency_composition_alts, + tour_category, + parent_col="person_id", +): + """ + This method processes the joint_tour_frequency_composition column that comes + out of the model of the same name and turns into a DataFrame that + represents the tours that were generated + + Parameters + ---------- + joint_tour_frequency_composition: Series + A series which has as the index and the chosen alternative + index as the value + joint_tour_frequency_composition_alts: DataFrame + A DataFrame which has as a unique index which relates to the values + in the series above typically includes columns which are named for trip + purposes with values which are counts for that trip purpose, and tour composition. Example + trip purposes include escort, shopping, othmaint, othdiscr, eatout, + social, etc. Tour composition includes adults, children, and mixed. + A row would be an alternative which might be to take + one shopping trip in a adult-only tour and zero trips of other purposes, etc. + tour_category : str + one of 'mandatory', 'non_mandatory', 'atwork', or 'joint' + parent_col: str + the name of the index (parent_tour_id for atwork subtours, otherwise person_id) + + Returns + ------- + tours : pandas.DataFrame + An example of a tours DataFrame is supplied as a comment in the + source code - it has an index which is a unique tour identifier, + a person_id column, and a tour type column which comes from the + column names of the alternatives DataFrame supplied above. + + tours.tour_type - tour type (e.g. school, work, shopping, eat) + tours.composition - tour composition (e.g. adults, children, mixed) + tours.tour_type_num - if there are two 'school' type tours, they will be numbered 1 and 2 + tours.tour_type_count - number of tours of tour_type parent has (parent's max tour_type_num) + tours.tour_num - index of tour (of any type) for parent + tours.tour_count - number of tours of any type) for parent (parent's max tour_num) + tours.tour_category - one of 'mandatory', 'non_mandatory', 'atwork', or 'joint' + """ + + # get the actual alternatives for each person - have to go back to the + # non_mandatory_tour_frequency_alts dataframe to get this - the choice + # above just stored the index values for the chosen alts + tour_counts = joint_tour_frequency_composition_alts.loc[ + joint_tour_frequency_composition + ] + + # assign person ids to the index + tour_counts.index = joint_tour_frequency_composition.index + + """ + alt1 alt2 alt3 + + 2588676 2 0 0 + 2588677 1 1 0 + """ + + tours = create_joint_tours(tour_counts, tour_category, parent_col) + + return tours + + +def create_joint_tours(tour_counts, tour_category, parent_col="person_id"): + """ + This method processes the tour_frequency column that comes + out of the model of the same name and turns into a DataFrame that + represents the tours that were generated + + Parameters + ---------- + tour_counts: DataFrame + table specifying how many tours of each type to create + one row per person (or parent_tour for atwork subtours) + one (int) column per tour_type, with number of tours to create + tour_category : str + one of 'mandatory', 'non_mandatory', 'atwork', or 'joint' + + Returns + ------- + tours : pandas.DataFrame + An example of a tours DataFrame is supplied as a comment in the + source code - it has an index which is a unique tour identifier, + a person_id column, and a tour type column which comes from the + column names of the alternatives DataFrame supplied above. + + tours.tour_type - tour type (e.g. school, work, shopping, eat) + tours.composition - tour composition (e.g. adults, children, mixed) + tours.tour_type_num - if there are two 'school' type tours, they will be numbered 1 and 2 + tours.tour_type_count - number of tours of tour_type parent has (parent's max tour_type_num) + tours.tour_num - index of tour (of any type) for parent + tours.tour_count - number of tours of any type) for parent (parent's max tour_num) + tours.tour_category - one of 'mandatory', 'non_mandatory', 'atwork', or 'joint' + """ + + # FIXME - document requirement to ensure adjacent tour_type_nums in tour_num order + + """ + alt1 alt2 alt3 + + 2588676 2 0 0 + 2588677 1 1 0 + """ + model_settings_file_name = "joint_tour_frequency_composition.yaml" + + model_settings = config.read_model_settings(model_settings_file_name) + + alts_table_structure = model_settings.get("ALTS_TABLE_STRUCTURE", None) + assert ( + alts_table_structure is not None + ), f"Expected to find ALTS_TABLE_STRUCTURE setting in joint_tour_frequency_composition.yaml" + + tour_type_dict = alts_table_structure.get("PURPOSE", None).get("VALUE_MAP", None) + assert ( + tour_type_dict is not None + ), f"Expected to find PURPOSE.VALUE_MAP setting in ALTS_TABLE_STRUCTURE" + + tour_type_cols = alts_table_structure.get("PURPOSE", None).get("COLUMNS", None) + assert ( + tour_type_cols is not None + ), f"Expected to find PURPOSE.COLUMNS setting in ALTS_TABLE_STRUCTURE" + + tour_comp_dict = alts_table_structure.get("COMPOSITION", None).get( + "VALUE_MAP", None + ) + assert ( + tour_comp_dict is not None + ), f"Expected to find COMPOSITION.VALUE_MAP setting in ALTS_TABLE_STRUCTURE" + + tour_comp_cols = alts_table_structure.get("COMPOSITION", None).get("COLUMNS", None) + assert ( + tour_comp_cols is not None + ), f"Expected to find COMPOSITION.COLUMNS setting in ALTS_TABLE_STRUCTURE" + + # reformat with the columns given below + tours_purp = tour_counts[tour_type_cols].stack().reset_index() + tours_purp.columns = [parent_col, "tour_id_temp", "tour_type"] + tours_purp["tour_id_temp"] = range(1, 1 + len(tours_purp)) + tours_purp["tour_type"] = tours_purp["tour_type"].map(tour_type_dict) + + """ + tour_id_temp tour_type + 0 2588676 purpose1 5 + 1 2588676 purpose2 0 + 2 2588677 purpose1 5 + 3 2588677 purpose2 5 + 4 2588678 purpose1 6 + 5 2588678 purpose2 7 + + parent_col is the index from non_mandatory_tour_frequency + tour_type is the column name from non_mandatory_tour_frequency_alts + tour_type_count is the count value of the tour's chosen alt's tour_type from alts table + """ + tours_comp = tour_counts[tour_comp_cols].stack().reset_index() + tours_comp.columns = [parent_col, "tour_id_temp", "composition"] + tours_comp["tour_id_temp"] = range(1, 1 + len(tours_comp)) + tours_comp["composition"] = tours_comp["composition"].map(tour_comp_dict) + + """ + tour_id_temp tour_composition + 0 2588676 party1 1 + 1 2588676 party2 0 + 2 2588677 party1 1 + 3 2588677 party2 1 + 4 2588678 party1 1 + 5 2588678 party2 2 + + parent_col is the index from non_mandatory_tour_frequency + tour_type is the column name from non_mandatory_tour_frequency_alts + tour_type_count is the count value of the tour's chosen alt's tour_type from alts table + """ + tours = pd.merge( + tours_purp, tours_comp, how="left", on=[parent_col, "tour_id_temp"] + ) + + tours = tours[(tours.tour_type.notnull()) & (tours.tour_type.notnull())] + + grouped = tours.groupby([parent_col, "tour_type"]) + tours["tour_type_num"] = grouped.cumcount() + 1 + tours["tour_type_count"] = tours["tour_type_num"] + grouped.cumcount( + ascending=False + ) + + grouped = tours.groupby(parent_col) + tours["tour_num"] = grouped.cumcount() + 1 + tours["tour_count"] = tours["tour_num"] + grouped.cumcount(ascending=False) + + """ + tour_type tour_type_num tour_type_count tour_num tour_count + 0 2588676 alt1 1 2 1 4 + 0 2588676 alt1 2 2 2 4 + 0 2588676 alt2 1 1 3 4 + 0 2588676 alt3 1 1 4 4 + """ + + # set these here to ensure consistency across different tour categories + assert tour_category in ["mandatory", "non_mandatory", "atwork", "joint"] + tours["tour_category"] = tour_category + + # for joint tours, the correct number will be filled in after participation step + tours["number_of_participants"] = 1 + + # index is arbitrary but don't want any duplicates in index + tours.reset_index(drop=True, inplace=True) + + return tours diff --git a/activitysim/abm/models/vehicle_type_choice.py b/activitysim/abm/models/vehicle_type_choice.py index 95723eb9d..324e505dd 100644 --- a/activitysim/abm/models/vehicle_type_choice.py +++ b/activitysim/abm/models/vehicle_type_choice.py @@ -124,7 +124,7 @@ def annotate_vehicle_type_choice_persons(model_settings, trace_label): model_settings=model_settings.get("annotate_persons"), trace_label=tracing.extend_trace_label(trace_label, "annotate_persons"), ) - pipeline.replace_table("persons", households) + pipeline.replace_table("persons", persons) def annotate_vehicle_type_choice_vehicles(model_settings, trace_label): @@ -214,9 +214,14 @@ def construct_model_alternatives(model_settings, alts_cats_dict, vehicle_type_da alts_wide._merge == "left_only", ["body_type", "fuel_type", "age"] ] - assert ( - len(missing_alts) == 0 - ), f"missing vehicle data for alternatives:\n {missing_alts}" + if model_settings.get("REQUIRE_DATA_FOR_ALL_ALTS", False): + # fail if alternative does not have an associated record in the data + assert ( + len(missing_alts) == 0 + ), f"missing vehicle data for alternatives:\n {missing_alts}" + else: + # eliminate alternatives if no vehicle type data + alts_wide = alts_wide[alts_wide._merge != "left_only"] alts_wide.drop(columns="_merge", inplace=True) # converting age to integer to allow interactions in utilities diff --git a/activitysim/abm/models/work_from_home.py b/activitysim/abm/models/work_from_home.py index 97a80d301..043264000 100755 --- a/activitysim/abm/models/work_from_home.py +++ b/activitysim/abm/models/work_from_home.py @@ -58,7 +58,7 @@ def work_from_home(persons_merged, persons, chunk_size, trace_hh_id): if estimator: estimator.write_model_settings(model_settings, model_settings_file_name) estimator.write_spec(model_settings) - estimator.write_coefficients(coefficients_df) + estimator.write_coefficients(coefficients_df, model_settings) estimator.write_choosers(choosers) # - iterative single process what-if adjustment if specified diff --git a/activitysim/abm/tables/shadow_pricing.py b/activitysim/abm/tables/shadow_pricing.py index 3a3ba7f56..396cf7c56 100644 --- a/activitysim/abm/tables/shadow_pricing.py +++ b/activitysim/abm/tables/shadow_pricing.py @@ -61,6 +61,12 @@ "workplace": "income_segment", } +default_segment_to_name_dict = { + # model_selector : persons_segment_name + "school": "school_segment", + "workplace": "income_segment", +} + def size_table_name(model_selector): """ diff --git a/activitysim/cli/create.py b/activitysim/cli/create.py index ec545d378..7cd8d218c 100644 --- a/activitysim/cli/create.py +++ b/activitysim/cli/create.py @@ -123,7 +123,7 @@ def get_example( Files downloaded via http pointers will be cached in this location. If a path is not given but just a truthy value, then a cache directory is created using in a location - selected by the appdirs library (or, if not installed, + selected by the platformdirs library (or, if not installed, linking is skipped.) """ if example_name not in EXAMPLES: @@ -200,11 +200,11 @@ def download_asset(url, target_path, sha256=None, link=True): if link: if not isinstance(link, (str, Path)): try: - import appdirs + import platformdirs except ImportError: link = False else: - link = appdirs.user_data_dir("ActivitySim") + link = platformdirs.user_data_dir("ActivitySim") original_target_path = target_path target_path = os.path.join(link, target_path) os.makedirs(os.path.dirname(target_path), exist_ok=True) diff --git a/activitysim/core/config.py b/activitysim/core/config.py index 7024d0512..aaa7ed2fb 100644 --- a/activitysim/core/config.py +++ b/activitysim/core/config.py @@ -750,6 +750,14 @@ def filter_warnings(): else: warnings.filterwarnings("default", category=CacheMissWarning) + # beginning from PR #660 (after 1.2.0), a FutureWarning is emitted when the trip + # scheduling component lacks a logic_version setting + warnings.filterwarnings( + "ignore", + category=FutureWarning, + message="The trip_scheduling component now has a logic_version setting.*", + ) + def handle_standard_args(parser=None): diff --git a/activitysim/core/configuration.py b/activitysim/core/configuration.py new file mode 100644 index 000000000..3174653b2 --- /dev/null +++ b/activitysim/core/configuration.py @@ -0,0 +1,291 @@ +from typing import Union + +try: + from pydantic import BaseModel as PydanticBase +except ModuleNotFoundError: + + class PydanticBase: + pass + + +class InputTable(PydanticBase): + """ + The features that define an input table to be read by ActivitySim. + """ + + tablename: str + """Name of the injected table""" + + filename: str = None + """ + Name of the CSV or HDF5 file to read. + + If not provided, defaults to `input_store` + """ + + index_col: str = None + """table column to use for the index""" + + rename_columns: dict[str, str] = None + """dictionary of column name mappings""" + + keep_columns: list[str] = None + """ + columns to keep once read in to memory. + + Save only the columns needed for modeling or analysis to save on memory + and file I/O + """ + + h5_tablename: str = None + """table name if reading from HDF5 and different from `tablename`""" + + +class Settings(PydanticBase): + """ + The overall settings for the ActivitySim model system. + + The input for these settings is typically stored in one main YAML file, + usually called ``settings.yaml``. + + Note that this implementation is presently used only for generating + documentation, but future work may migrate the settings implementation to + actually use this pydantic code to validate the settings before running + the model. + """ + + models: list[str] + """ + list of model steps to run - auto ownership, tour frequency, etc. + + See :ref:`model_steps` for more details about each step. + """ + + resume_after: str = None + """to resume running the data pipeline after the last successful checkpoint""" + + input_table_list: list[InputTable] + """list of table names, indices, and column re-maps for each table in `input_store`""" + + input_store: str = None + """HDF5 inputs file""" + + create_input_store: bool = False + """ + Write the inputs as read in back to an HDF5 store. + + If enabled, this writes the store to the outputs folder to use for subsequent + model runs, as reading HDF5 can be faster than reading CSV files.""" + + households_sample_size: int = None + """ + Number of households to sample and simulate + + If omitted or set to 0, ActivitySim will simulate all households. + """ + trace_hh_id: Union[int, list] = None + """ + Trace household id(s) + + If omitted, no tracing is written out + """ + + trace_od: list[int] = None + """ + Trace origin, destination pair in accessibility calculation + + If omitted, no tracing is written out. + """ + + chunk_training_mode: str = None + """ + The method to use for chunk training. + + Valid values include {disabled, training, production, adaptive}. + See :ref:`chunk_size` for more details. + """ + + chunk_size: int = None + """ + Approximate amount of RAM to allocate to ActivitySim for batch processing. + + See :ref:`chunk_size` for more details. + """ + + chunk_method: str = None + """ + Memory use measure to use for chunking. + + See :ref:`chunk_size`. + """ + + checkpoints: Union[bool, list] = True + """ + When to write checkpoint (intermediate table states) to disk. + + If True, checkpoints are written at each step. If False, no intermediate + checkpoints will be written before the end of run. Or, provide an explicit + list of models to checkpoint. + """ + + check_for_variability: bool = False + """ + Debugging feature to find broken model specifications. + + Enabling this check does not alter valid results but slows down model runs. + """ + + log_alt_losers: bool = False + """ + Write out expressions when all alternatives are unavailable. + + This can be useful for model development to catch errors in specifications. + Enabling this check does not alter valid results but slows down model runs. + """ + + use_shadow_pricing: bool = False + """turn shadow_pricing on and off for work and school location""" + + output_tables: list[str] = None + """list of output tables to write to CSV or HDF5""" + + want_dest_choice_sample_tables: bool = False + """turn writing of sample_tables on and off for all models""" + + cleanup_pipeline_after_run: bool = False + """ + Cleans up pipeline after successful run. + + This will clean up pipeline only after successful runs, by creating a + single-checkpoint pipeline file, and deleting any subprocess pipelines. + """ + + sharrow: Union[bool, str] = False + """ + Set the sharrow operating mode. + + .. versionadded:: 1.2 + + * `false` - Do not use sharrow. This is the default if no value is given. + * `true` - Use sharrow optimizations when possible, but fall back to + legacy `pandas.eval` systems when any error is encountered. This is the + preferred mode for running with sharrow if reliability is more important + than performance. + * `require` - Use sharrow optimizations, and raise an error if they fail + unexpectedly. This is the preferred mode for running with sharrow + if performance is a concern. + * `test` - Run every relevant calculation using both sharrow and legacy + systems, and compare them to ensure the results match. This is the slowest + mode of operation, but useful for development and debugging. + """ + + +class ZarrDigitalEncoding(PydanticBase): + """Digital encoding instructions for skim tables. + + .. versionadded:: 1.2 + """ + + regex: str + """A regular expression for matching skim matrix names. + + All skims with names that match under typical regular expression rules + for Python will be processed together. + """ + + joint_dict: str + """The name of the joint dictionary for this group. + + This must be a unique name for this set of skims, and a new array + will be added to the Dataset with this name. It will be an integer- + type array indicating the position of each element in the jointly + encoded dictionary.""" + + +class TAZ_Settings(PydanticBase): + """ + Complex settings for TAZ skims that are not just OMX file(s). + + .. versionadded:: 1.2 + """ + + omx: str = None + """The filename of the data stored in OMX format. + + This is treated as a fallback for the raw input data, if ZARR format data + is not available. + """ + + zarr: str = None + """The filename of the data stored in ZARR format. + + Reading ZARR data can be much faster than reading OMX format data, so if + this filename is given, the ZARR file format is preferred if it exists. If + it does not exist, then OMX data is read in and then ZARR data is written + out for future usage. + + .. versionadded:: 1.2 + """ + + zarr_digital_encoding: list[ZarrDigitalEncoding] = None + """ + A list of encodings to apply before saving skims in ZARR format. + + .. versionadded:: 1.2 + """ + + +class NetworkSettings(PydanticBase): + """ + Network level of service and skims settings + + The input for these settings is typically stored in one YAML file, + usually called ``network_los.yaml``. + """ + + zone_system: int + """Which zone system type is used. + + * 1 - TAZ only. + * 2 - MAZ and TAZ. + * 3 - MAZ, TAZ, and TAP + """ + + taz_skims: Union[str, TAZ_Settings] = None + """Instructions for how to load and pre-process skim matrices. + + If given as a string, it is interpreted as the location for OMX file(s), + either as a single file or as a glob-matching pattern for multiple files. + The time period for the matrix must be represented at the end of the matrix + name and be seperated by a double_underscore (e.g. `BUS_IVT__AM` indicates base + skim BUS_IVT with a time period of AM. + + Alternatively, this can be given as a nested dictionary defined via the + TAZ_Settings class, which allows for ZARR transformation and pre-processing. + """ + + skim_time_periods: dict + """time period upper bound values and labels + + * ``time_window`` - total duration (in minutes) of the modeled time span (Default: 1440 minutes (24 hours)) + * ``period_minutes`` - length of time (in minutes) each model time period represents. Must be whole factor of ``time_window``. (Default: 60 minutes) + * ``periods`` - Breakpoints that define the aggregate periods for skims and assignment + * ``labels`` - Labels to define names for aggregate periods for skims and assignment + """ + + read_skim_cache: bool = False + """Read cached skims (using numpy memmap) from output directory. + + Reading from memmap is much faster than omx, but the memmap is a huge + uncompressed file. + """ + + write_skim_cache: bool = False + """Write memmapped cached skims to output directory. + + This is needed if you want to use the cached skims to speed up subsequent + runs. + """ + + cache_dir: str = None + """alternate dir to read/write cache files (defaults to output_dir)""" diff --git a/activitysim/core/los.py b/activitysim/core/los.py index e69ed587f..c1c3a8451 100644 --- a/activitysim/core/los.py +++ b/activitysim/core/los.py @@ -2,6 +2,7 @@ # See full license in LICENSE.txt. import logging +import os import warnings import numpy as np diff --git a/activitysim/core/pathbuilder_cache.py b/activitysim/core/pathbuilder_cache.py index 1bd219693..5153cf160 100644 --- a/activitysim/core/pathbuilder_cache.py +++ b/activitysim/core/pathbuilder_cache.py @@ -9,6 +9,7 @@ import numpy as np import pandas as pd +import psutil from activitysim.core import config, inject, simulate, util diff --git a/activitysim/examples/prototype_mtc_extended/test/output/cache/.gitignore b/activitysim/examples/prototype_mtc_extended/test/output/cache/.gitignore index 1d085cacc..3dd2e62f9 100644 --- a/activitysim/examples/prototype_mtc_extended/test/output/cache/.gitignore +++ b/activitysim/examples/prototype_mtc_extended/test/output/cache/.gitignore @@ -1 +1,2 @@ -** +*.mmap +*.feather diff --git a/activitysim/examples/prototype_mwcog/configs/trip_destination_annotate_trips_preprocessor.csv b/activitysim/examples/prototype_mwcog/configs/trip_destination_annotate_trips_preprocessor.csv old mode 100644 new mode 100755 diff --git a/activitysim/examples/prototype_mwcog/configs/trip_scheduling_preprocessor.csv b/activitysim/examples/prototype_mwcog/configs/trip_scheduling_preprocessor.csv new file mode 100644 index 000000000..732a58d47 --- /dev/null +++ b/activitysim/examples/prototype_mwcog/configs/trip_scheduling_preprocessor.csv @@ -0,0 +1,8 @@ +Description,Target,Expression +,periods_left,(df.latest - df.earliest) +# binning the periods differently for inbound and outbound +,periods_left_min,"np.where(df['outbound'], periods_left.clip(upper=25), periods_left.clip(upper=34))" +,periods_left_max,"np.where(((periods_left >= 25) & (df['outbound'])) | ((periods_left >= 34) & (~df['outbound'])), 47, periods_left)" +,tour_purpose,"reindex(tours.tour_type, df.tour_id)" +,tour_purpose_grouped,"np.where(tour_purpose.isin(['work','school','univ']), 'mand', 'non_mand')" +,half_tour_stops_remaining_grouped,(df.trip_count - df.trip_num).clip(upper=1) \ No newline at end of file diff --git a/activitysim/examples/prototype_mwcog/configs/trip_scheduling_probs_purpose_stops.csv b/activitysim/examples/prototype_mwcog/configs/trip_scheduling_probs_purpose_stops.csv new file mode 100644 index 000000000..411be00eb --- /dev/null +++ b/activitysim/examples/prototype_mwcog/configs/trip_scheduling_probs_purpose_stops.csv @@ -0,0 +1,245 @@ +periods_left_min,periods_left_max,outbound,tour_purpose_grouped,half_tour_stops_remaining_grouped,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,All +0,0,True,non_mand,0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,True,non_mand,1,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,True,mand,0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,True,mand,1,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,True,non_mand,0,0.8189802736716861,0.18101972632831478,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,True,non_mand,1,0.7721889137040513,0.22781108629594915,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,True,mand,0,0.7471719634686398,0.2528280365313602,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,True,mand,1,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,True,non_mand,0,0.5313044094657583,0.46665243420937097,0.00204315632485774,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,True,non_mand,1,0.7175829817374099,0.2807545194400709,0.0016624988225180234,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,True,mand,0,0.5035022647690804,0.49649773523092017,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,True,mand,1,0.8745153839084898,0.12548461609151035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,True,non_mand,0,0.3871957673026593,0.5842636573575687,0.027848779906802835,0.0006917954329635533,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,True,non_mand,1,0.5010068584030869,0.4944859928509608,0.004507148745955219,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,True,mand,0,0.47374691698873894,0.48185051672462087,0.04440256628664039,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,True,mand,1,0.4975171975856041,0.4834274927388484,0.019055309675547517,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,True,non_mand,0,0.3000152058882846,0.5523183073306172,0.13664303181097184,0.011023454970117077,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,True,non_mand,1,0.3743770992053098,0.5727827563748306,0.05252770967230497,0.00031243474755708465,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,True,mand,0,0.4391344468565407,0.4730858153439597,0.08579467818492309,0.001985059614577168,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,True,mand,1,0.17374342144703583,0.705501446138433,0.12075513241453113,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,True,non_mand,0,0.24443687276143128,0.48727017005994244,0.24105582258752195,0.027237134591092966,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,True,non_mand,1,0.3498737043600855,0.5468850124616544,0.0957015471401984,0.002142098611144654,0.0053976374269204585,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,True,mand,0,0.4140440879091029,0.4627566659226456,0.10589932963919767,0.014346985277468863,0.0029529312515844176,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,True,mand,1,0.5359817354115067,0.40328213098074,0.037043756388711026,0.023692377219042413,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,True,non_mand,0,0.2243718573226493,0.4740049987478467,0.2185942840913799,0.07387248869388857,0.008608771317053272,0.0005475998271755717,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,True,non_mand,1,0.2947249323070468,0.520484919863231,0.16267063104650237,0.021821311374649363,0.00029820540857341003,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,True,mand,0,0.34571265959006825,0.45183505047762074,0.11547038429330879,0.08043856620520728,0.006543339433795003,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,True,mand,1,0.46036107799104353,0.3701917482866324,0.14122662957933466,0.028220544142989194,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,True,non_mand,0,0.227621158038117,0.417953229518577,0.19141787402389457,0.12197351063472531,0.024548137961874116,0.016486089822811145,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,True,non_mand,1,0.2832486215408319,0.5166096440702325,0.14826728166817885,0.03482546263765433,0.017048990083102438,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,True,mand,0,0.361803588610528,0.418900938560931,0.14154525076540292,0.06743958274104898,0.006099978058599388,0.004210661263489495,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,True,mand,1,0.4127559556392927,0.4462328382983683,0.1195063008397756,0.012231152152406215,0.009273753070157131,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,True,non_mand,0,0.19426921480484255,0.40592917871708584,0.19011533368438208,0.15982429426585337,0.040643179164081826,0.006644362842185375,0.002011822208828069,0.0005626143127424159,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,True,non_mand,1,0.23006768855966434,0.4951325777522361,0.16375321837246617,0.09014636059161886,0.012948244048729797,0.007951910675286304,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,True,mand,0,0.3404793706490589,0.4564428277054562,0.14909890279509022,0.024535359848871188,0.007981254754395728,0.020513594855995246,0.0,0.0009486893911321145,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,True,mand,1,0.399341249303726,0.41517942529414553,0.1028491817940402,0.04745891472898081,0.03517122887910787,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,True,non_mand,0,0.19874760126421334,0.3630228482412267,0.1444748881448116,0.16435014395285896,0.10036289384754772,0.017397511428007644,0.008202316900872985,0.0031073806650114963,0.0003344155554514234,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,True,non_mand,1,0.22748125907091696,0.4891138773218324,0.21855171544454474,0.04724707111068227,0.016939736746825574,0.00045246712463884055,0.000213873180559771,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,True,mand,0,0.37368001529264117,0.40060534327725444,0.11191565670765437,0.06782772701563022,0.03125402744106718,0.011589870883400537,0.001558362508815955,0.0015689968735345759,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,True,mand,1,0.2567315234988767,0.5572074890664362,0.10628235358815401,0.07427082306966946,0.002083433027377295,0.003424377749486876,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,True,non_mand,0,0.18414136513468135,0.3197692844976048,0.19719338356553304,0.16620135022943144,0.06960029735040153,0.03703358451667586,0.014494298970866393,0.0068016927998264445,0.004764742934979405,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,True,non_mand,1,0.22820299437971506,0.48795761528080067,0.1549340394408621,0.09519810801564392,0.02664096931437101,0.0038191046031214,0.0027576448173758537,0.0004895241481095858,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,True,mand,0,0.2924258078226892,0.46366769271762154,0.11886521424960046,0.06217986582313677,0.025764091367057613,0.016078005167636363,0.0017215479420771597,0.019297774910179692,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,True,mand,1,0.22445327282351105,0.3869668718823247,0.18146111316276614,0.1899539000261889,0.016646553939701842,0.0,0.0005182881655077271,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,True,non_mand,0,0.1838047344313972,0.4451769992587658,0.152991609518764,0.10039166250104836,0.06367584589757627,0.03151581147531881,0.008585327734442478,0.009924884136955484,0.0012902203336801305,0.00251568701530955,0.00012721769674307987,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,True,non_mand,1,0.22323053576220492,0.43792687319101775,0.17149150600844593,0.08992672587419363,0.06021379863217045,0.011341895844761014,0.002924004745341519,0.0029446599418644186,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,True,mand,0,0.2549729920032347,0.3846638483858408,0.1585996489799274,0.07048148043675959,0.0610612844984867,0.02950967271600184,0.009390882720852532,0.019671473627125007,0.011648716631770929,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,True,mand,1,0.31950618996163216,0.370416105116807,0.12957808333436566,0.038771889005981476,0.07973400907657878,0.008259064901326241,0.04502512717413414,0.0,0.0,0.00870953142917452,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,True,non_mand,0,0.15538064701402524,0.34010855114672783,0.15756329624436757,0.130761080225149,0.08058876296099016,0.037166670112688684,0.05321282457870319,0.011684514315131676,0.008420820875982287,0.022760982646872548,0.002351849879359441,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,True,non_mand,1,0.18615603339448467,0.4442747128851546,0.16119531212501342,0.1660481650340877,0.01822419609095152,0.014405133011713384,0.0012287665864568532,0.00810044705472734,0.0,0.00036723381740970943,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,True,mand,0,0.2833186435388759,0.4473279201816816,0.0839513747492686,0.08780578472571127,0.048675906218727354,0.018950473118234137,0.029969897467500405,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,True,mand,1,0.3716081395440234,0.24335198225727428,0.15817450794815305,0.1152128686656522,0.09842277539670218,0.0,0.012825429182031002,0.0,0.0004042970061645304,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,True,non_mand,0,0.1280486077306424,0.39007727678250526,0.14429472032308305,0.12987881052290906,0.05673434374115411,0.04374230904631316,0.03370924463183397,0.022796437331145697,0.005698472187466286,0.03744492108087016,0.007574856622076875,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,True,non_mand,1,0.16420817620589498,0.3959652826942212,0.21269414158675182,0.10510649107393175,0.062059223793042705,0.03832758967086638,0.01031829635321654,0.007272614386214486,0.0038487289764247883,0.00019945525943466293,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,True,mand,0,0.2833739707820797,0.3472246351141721,0.12472684460184481,0.1087803737635112,0.04158238860256562,0.02102549542839796,0.004873270302794455,0.05209115241161954,0.0,0.0,0.01632186899301426,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,True,mand,1,0.20066138301721598,0.3252681760134406,0.06612907451937301,0.1197886582841732,0.22936068409786692,0.03448374665640273,0.0068774276923423625,0.0007760790887603079,0.016654770630425347,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,True,non_mand,0,0.21736634651976025,0.2911804898239222,0.14177795654611225,0.07388892050301235,0.08781548032944456,0.044928908010177494,0.0792545723131907,0.021645018917800064,0.02019552748207418,0.009467311676119831,0.004536650962516739,0.007398198338740162,0.0005446185771287058,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,True,non_mand,1,0.2343054288430577,0.3037047693015579,0.18586258067809125,0.14484685683240442,0.06798436270712183,0.04598952809490658,0.00407148418725873,0.003288198365222629,0.0,0.0018933319504502446,0.007492591087270938,0.0005608679526570394,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,True,mand,0,0.3454886512576222,0.38014428702430497,0.13782651573334836,0.044263018546040186,0.055676392088022865,0.010906524177868795,0.0072979890708083925,0.007361983152376035,0.0,0.001430578916990835,0.009604060032617677,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,True,mand,1,0.4852409017501698,0.2684239060123367,0.15637469849088115,0.04917106696035559,0.01712199313248224,0.014788285966204288,0.0066105570512929685,0.0,0.0022685906362778065,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,True,non_mand,0,0.25269778070190596,0.2968540782999024,0.11023455674822831,0.05623827230855225,0.06597186788243106,0.1253009893013266,0.01271029987709566,0.052921232042414855,0.006233945238574574,0.0012759056875845305,0.01162477209683355,0.0037846301847631685,0.0020877532596896746,0.00206391637069746,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,True,non_mand,1,0.17865337321760114,0.49598387546653,0.17985004316104092,0.0834123491136488,0.02861982991731569,0.01507389127479415,0.0019319769530352945,0.015088099515112047,0.0,0.0,0.0013865613809220093,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,True,mand,0,0.5092314635021563,0.2909852832285074,0.1007263601936202,0.05369042418623467,0.015831820236393533,0.00696398701811726,0.009594759834484176,0.005897226236671945,0.0016561807514684653,0.0028240915770827166,0.0025984032352619696,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,True,mand,1,0.3065494168965283,0.3171690632857757,0.15389037912080228,0.08157827533204816,0.05578445762327045,0.025762048043104755,0.024355412276719727,0.0021433410196588184,0.004404725115949303,0.0,0.0,0.028362881286142977,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,True,non_mand,0,0.23933291204976098,0.33470032117477017,0.16347743110076973,0.07443734333026066,0.03793288215034974,0.057132956981553754,0.005334799175762797,0.01899323978978337,0.00043592297563987335,0.03487186028711262,0.01541730805407518,0.010943184082674567,0.0015278355776893143,0.005462003269796668,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,True,non_mand,1,0.16005321326665203,0.37632691905494753,0.15394957154631203,0.1304548210249311,0.10940790296800768,0.02500721732909631,0.013135655612855335,0.017070125977595278,0.0007067958022550534,0.013887777417347766,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,True,mand,0,0.3848194266722145,0.37134484471331375,0.0850662068736148,0.05017749283620628,0.017003906169515512,0.021747227413822744,0.008386061255936564,0.011286918024608511,0.010448753616855348,0.0,0.0,0.0012353190869387998,0.0016269833209067346,0.0,0.036856860016065106,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,True,mand,1,0.2275194752607601,0.25017235420678974,0.11692008159168814,0.2070096816790754,0.14023010283480625,0.009814183791811608,0.01979234880065379,0.0,0.009783746942694935,0.0,0.016295555427818544,0.0024624694639021833,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,True,non_mand,0,0.2526702328957933,0.27447465838212554,0.09213362766425133,0.21312793523475992,0.06524452915763224,0.026394837256766328,0.028183453538624264,0.00591378437050656,0.016211185354215143,0.0013689285176775245,0.0024881369773125427,0.0,0.011475536248101093,0.003433553098931867,0.0040596569100583325,0.0028199443932443616,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,True,non_mand,1,0.17523974786396865,0.3585193462713332,0.2049836229835515,0.050516166565969176,0.07709240067318539,0.08181910721392045,0.012684940794303552,0.013453983030564066,0.003034514575602301,0.020700169867956354,0.0019560001596443948,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,True,mand,0,0.4114491047000963,0.4134305296546959,0.06043576184993309,0.05546620254054133,0.014232550856757764,0.009566984849911121,0.010921244427410532,0.0065069883496819666,0.005398249675380565,0.00545950083354648,0.006220799751873012,0.0003236540673956202,0.0,0.0,0.000588428442776014,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,True,mand,1,0.29483908954012533,0.4126571783996355,0.1282010951680747,0.07767698088397365,0.03921799675702734,0.009704164761495144,0.016349316407632902,0.01982939678355619,0.0,0.0,0.0,0.001524781298478771,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,True,non_mand,0,0.23734082671976767,0.3050705316929325,0.07789215339238303,0.1368917708633237,0.04187179834207113,0.033981947159287984,0.06554042288542364,0.022664102297987824,0.0298455093855354,0.012412943716680362,0.019932736861367033,0.0,0.013004164316165131,0.00021200801979027862,0.002179329872955506,0.001159754474329442,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,True,non_mand,1,0.13913077114477862,0.34815770585582523,0.23520811083080348,0.08246456459530692,0.0821646726705314,0.06163170546693259,0.029090075742036436,0.012357830239898176,0.0033727865960344024,0.0064217768578526,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,True,mand,0,0.5028117748095691,0.350811002436585,0.06094068744196811,0.025138559142886138,0.013313948517148913,0.010443856162040044,0.012709166980486838,0.0103699428446387,0.0024898484271303474,0.003108631861406074,0.0,0.0,0.007862581376140397,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,True,mand,1,0.41324485045768594,0.28488516180866524,0.09899198705298416,0.1046574784011423,0.01481702835528995,0.04219034266694274,0.023047590271449092,0.01246376876040535,0.004803638903289208,0.0,0.00041287271562461545,0.00048528060652142086,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,True,non_mand,0,0.3017565747841334,0.3141421626967243,0.13897942362878032,0.07953424716467176,0.04789339041763478,0.029590309407092362,0.005483011799124794,0.04033077361125482,0.00831325910282016,0.020194011839126474,0.006281678832042689,0.005532634472438549,0.0,0.0,0.0019685222441560013,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,True,non_mand,1,0.17072663057970913,0.3548023964811101,0.17539393090627897,0.08487984563776048,0.03603542807021147,0.029090578331425573,0.04430798127122374,0.022003753637441455,0.0586663427539483,0.0012850338963282585,0.0,0.022808078434562406,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,True,mand,0,0.44131354765837166,0.4047130846841438,0.06864755834098452,0.025515466907659275,0.03423311148754811,0.007825267364543038,0.0034266911596967154,0.001956863696708489,0.005495386233444543,0.0032524374925951157,0.0,0.0014950458806589127,0.0008607604468698304,0.0,0.0,0.0,0.0005059114587113161,0.000758867188066974,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,True,mand,1,0.3385595402274405,0.3560802991655533,0.10715183692502118,0.030544747048605964,0.02707302813897836,0.023694134679513583,0.0385475571963037,0.00874147499353564,0.007208544430021171,0.02225451532998375,0.0036500124100919736,0.036494309454951385,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,True,non_mand,0,0.32840582877506,0.3239718725548607,0.09724592373395033,0.07933000984262077,0.016521588382256296,0.04110087420857762,0.03800046003709891,0.003630837851231657,0.001650395338610952,0.009947579789589194,0.0012276885608375706,0.0,0.0189480649672734,0.0034287444577843222,0.0,0.013266834107749372,0.001229054205963644,0.004036575372647966,0.0,0.0180576678138876,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,True,non_mand,1,0.2568109508347746,0.2643209479779701,0.09125414821459571,0.08639034986642669,0.13646840347881434,0.033677709597699536,0.03132989171946656,0.051938714190768176,0.020333452242512175,0.008060014807481985,0.0,0.0,0.0183356907222172,0.001079726347272931,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,True,mand,0,0.36112165984167366,0.4511281799953402,0.09754378504634288,0.03354921807753693,0.017356046010882212,0.003213813405431729,0.006258373471072896,0.0017575825135433373,0.0013827505776258344,0.00722334238502016,0.012338623470051404,0.004703819134656911,0.0003803283546665727,0.0003357851615107776,0.00011032650304917473,0.0,0.001596366051596955,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,True,mand,1,0.3816459372615953,0.3945478121020502,0.08524720483157228,0.019855043064103323,0.0074712757278695115,0.03363691799725278,0.017751306835856975,0.03862113193829549,0.004935331469569992,0.006864838362616386,0.0012543850194759146,0.0032942666931832206,0.0003260156090476146,0.0,0.0,0.004548533087511939,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,True,non_mand,0,0.2690669634726405,0.3723736827575617,0.16325508608213551,0.046694971020562734,0.03464559409802502,0.006355678854842793,0.019497487360188612,0.015508631840764652,0.016240893261411725,0.01731097729494585,0.0,0.006288442421438049,0.029035866448718573,0.0,0.0,0.001410473914972469,0.0,0.0023152511717912405,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,True,non_mand,1,0.27352491172131355,0.2737010895683116,0.17663919029561195,0.08789123960664523,0.04435910718967327,0.02244206741473184,0.040466404405768486,0.029759664134995787,0.027277248413337063,0.019021056437541865,0.003827918738164591,0.0,0.0007187057625978561,0.0,0.0,0.0,0.0003713963113067903,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,True,mand,0,0.3421767930625402,0.4583821797125419,0.10184422751171661,0.043339296331545055,0.021807383888143045,0.014121841670799959,0.002249176990388862,0.004344863694448759,0.0,0.0061059831791194395,0.00100140175966159,0.002998017787369841,0.0,0.0,0.0007177609921813928,0.0,0.0,0.0009110734195443683,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,True,mand,1,0.3852523661677553,0.34324948914400705,0.0993124798614889,0.06979577858677936,0.021741120873680984,0.01640646685815812,0.023385459240988556,0.02215392910226852,0.01010099940923899,0.00680351262199579,0.0013969836073747422,0.0,0.0004014145262633554,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,True,non_mand,0,0.25477183402553005,0.3694056597934993,0.2006597726876724,0.06851248067274086,0.01934086312579471,0.004994729796151471,0.01937602523742874,0.012662439857387622,0.003988019894474462,0.013846794085397778,0.01975152051420429,0.005486164422143218,0.0,0.00163458835254345,0.0,0.0,0.001773014020379506,0.0,0.0004898851159845548,0.0016801531321044578,0.0016260552665631272,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,True,non_mand,1,0.17874304652108153,0.35419753445154684,0.18606966793109989,0.0679875784765435,0.07473717670265836,0.013330369529280333,0.062252982464887155,0.0030528728703864876,0.03374293988005319,0.01823048784918307,0.0016485884402127082,0.0,0.0,0.006006754883067085,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,True,mand,0,0.3231040937789736,0.37783574056416336,0.11282585788818966,0.07473591438427163,0.030714524374384062,0.03129122706779622,0.010073667114053839,0.003029764662524868,0.01521408011270044,0.0004846653635579069,0.005193560580841647,0.004988236597648051,0.0012611246538849238,0.001782874677601488,0.0016885630090716064,0.0,0.0,0.0,0.0013615559937593246,0.004414549176577772,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,True,mand,1,0.34319991902948516,0.4202126831088522,0.1434568705706193,0.031395328956467086,0.02396133543507801,0.006830826629039821,0.011093288892382156,0.0046681244828163555,0.013376849364490588,0.0,0.0,0.0,0.00180477353076914,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,True,non_mand,0,0.22315237915937625,0.3585126730950114,0.15086660734461227,0.04003015806055507,0.010704597553027875,0.09504534327523127,0.015536044412849838,0.0071776156811848395,0.008975199943097508,0.05273738326518863,0.012890327924280074,0.0,0.0,0.0022834622424379057,0.0,0.0,0.0,0.0,0.005300151960071576,0.0,0.016788056083075552,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,True,non_mand,1,0.21054648561134698,0.4204533340822677,0.12412795180540473,0.052446732470240245,0.05766140062618662,0.03186729787989351,0.031306696755072604,0.016898810441317264,0.04640595053614962,0.0017567169982827672,0.006528622793838264,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,True,mand,0,0.2810588064052126,0.4291299040354918,0.1375500150736873,0.052474912378944125,0.03169969809125566,0.014285807975679484,0.0075344484834238105,0.006051070026925496,0.025439860854126622,0.0007661398331433164,0.002275597986726701,0.003361411279311516,0.0011638133306478963,0.0,0.0059455309394979075,0.001262983305926154,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,True,mand,1,0.2671172269866584,0.4800696157756553,0.058539868244201876,0.022576969912060492,0.06015500872112822,0.050180520674440884,0.011310032497415629,0.020806824086393293,0.017236264656944254,0.0012034744362839894,0.0,0.0,0.0,0.004303496983961252,0.0,0.004541549584258667,0.0,0.001959147440598433,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,True,non_mand,0,0.17801854764023076,0.33530679714265477,0.13348963369334507,0.07116283229740007,0.015827338429672495,0.020384755253339402,0.03711544964381847,0.01619478665901007,0.03766780688214263,0.0013021755750721319,0.015663540780604546,0.004615541075489265,0.0,0.055358257663124945,0.0,0.007919781127453444,0.04624612685294099,0.0,0.0,0.0,0.02372662928370056,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,True,non_mand,1,0.19883866184802476,0.3989841260454337,0.17440138282205528,0.044915816103523944,0.04686151373319533,0.02531386457905582,0.05162905332411728,0.0,0.012064034831485559,0.019741109148670957,0.0215373403892625,0.0,0.0,0.0,0.005713097175175187,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,True,mand,0,0.2942920558990901,0.4487646399779205,0.09648160648117156,0.060370355912672424,0.04881731825902547,0.009610609195121394,0.0032581874042822206,0.01769742428154386,0.0,0.0010155869912132766,0.0006002352032171769,0.00970870776617855,0.0,0.0,0.0013601793728941043,0.0,0.002532808926316935,0.0,0.00549028432935123,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,True,mand,1,0.36545266921468933,0.3240397115036439,0.06081441358762848,0.06379428134177592,0.0765101482479992,0.0034617820646519197,0.0,0.0007295223052285381,0.005625391544493849,0.006273555830207512,0.023048066936616433,0.0,0.003964139346397377,0.035672397827294935,0.010949931019435805,0.0,0.0196639892299377,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,47,True,non_mand,0,0.16693246482461485,0.27572302183688535,0.06502710270928731,0.14929679299607282,0.098820422219055,0.029690619614459367,0.015539474985465207,0.04220478472089951,0.033834957834988584,0.006362011186128971,0.002397014372466234,0.022849399999460028,0.051225623357771005,0.0,0.0,0.0,0.0,0.00017537708397509532,0.0022893305829807097,0.0014731968865586296,0.0012541062165624093,0.025321621488626295,0.0,0.0,0.006488528654305694,0.0030941484294369514,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,47,True,non_mand,1,0.1616705841202927,0.27191086649507307,0.22021908800051926,0.061561676086117297,0.0765553221187797,0.03446525060143435,0.05702793411636113,0.02174697868721139,0.028611170728552335,0.010330712376886535,0.004658417106272408,0.011249404614325042,0.0010501468268611662,0.021013204209753045,0.0,0.0008565909328864426,0.013060567050533751,0.0019812136574427963,0.0,0.0,0.0,0.0,0.0020308722706966855,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,47,True,mand,0,0.2584666874832539,0.34765150161411806,0.13678525809093164,0.08909913309462639,0.027911554983097473,0.0362446366281597,0.013848854049887283,0.006955248371422206,0.009704937220782311,0.011630127544640762,0.002717838359516249,0.009018580475599182,0.0030351075625971264,0.0004365002979092682,0.009006690059237045,0.00792629402548114,0.009193074656176145,0.004084189558323619,0.009775936550396406,0.0011201519622454656,0.0026830068147981395,0.0,0.0016135722995967666,0.0010911182972038987,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,47,True,mand,1,0.22389052863060707,0.25782744040607447,0.13372069707144552,0.06566376497901984,0.08824743970769301,0.030064755444687695,0.05917317978857198,0.01713691927327129,0.026583876492388636,0.028654351670731135,0.01630714416464881,0.0166703541691361,0.0036689128882868025,0.0016985526894867638,0.00727094746660144,0.0,0.00031387182127881537,0.0,0.0,0.002780583450620694,0.0,0.0,0.0,0.0,0.0,0.020326679885448184,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,False,non_mand,0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,False,non_mand,1,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,False,mand,0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0,False,mand,1,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,False,non_mand,0,0.3085058556833788,0.6914941443165699,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,False,non_mand,1,0.6098957373391095,0.3901042626608902,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,False,mand,0,0.3400196071668157,0.6599803928332094,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +1,1,False,mand,1,0.660646645005993,0.33935335499400854,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,False,non_mand,0,0.01566536243004071,0.5087619037320673,0.47557273383787263,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,False,non_mand,1,0.18601272710111572,0.7362146227370155,0.07777265016188578,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,False,mand,0,0.044693926240483454,0.531858172433529,0.42344790132600213,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +2,2,False,mand,1,0.3010902917833252,0.6463185562492355,0.052591151967433455,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,False,non_mand,0,0.0033046685451080648,0.05265059202234202,0.45906353943154127,0.48498120000099215,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,False,non_mand,1,0.1065693642191575,0.45232960069446004,0.4030101423101475,0.03809089277626278,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,False,mand,0,0.012005726429216724,0.09355702040285643,0.46993124064528696,0.4245060125226436,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +3,3,False,mand,1,0.193873969079137,0.4672563873148181,0.3040892300940505,0.03478041351198802,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,False,non_mand,0,0.0016036671252261981,0.017767458700728957,0.07240919724407537,0.49306198484343444,0.4151576920865569,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,False,non_mand,1,0.07296581099716495,0.23684940936611923,0.3858336032497618,0.2775773381455728,0.02677383824140037,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,False,mand,0,0.00484376576675081,0.030795083592889384,0.07832900933388429,0.48303325553412996,0.40299888577233856,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +4,4,False,mand,1,0.13403842057693022,0.32086007222114277,0.2794636225577261,0.23982956587455542,0.025808318769642357,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,False,non_mand,0,0.0030101669481335555,0.013800918694849406,0.023247493981202575,0.07866283505005688,0.49342482051787834,0.3878537648078958,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,False,non_mand,1,0.04807347591616507,0.16548737528438784,0.25592287500785454,0.33829108226746024,0.17147069374366333,0.020754497780470584,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,False,mand,0,0.0009063314408092798,0.0052896314594121354,0.0183945561751926,0.06237264951046812,0.49556217273496406,0.4174746586791465,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +5,5,False,mand,1,0.09083503923757143,0.23933355378662308,0.21767609914690794,0.23011271637875585,0.20748236078672283,0.014560230663417042,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,False,non_mand,0,0.0006876713822025752,0.006418703163848254,0.00436742804615121,0.014961274075229396,0.13809761892452907,0.49924199681737336,0.33622530759066993,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,False,non_mand,1,0.049436407291043365,0.1441757013954298,0.19441551085983177,0.27100350347421354,0.20939091792785372,0.12366106164989442,0.007916897401727949,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,False,mand,0,0.0003365289460912691,0.0006703870275310202,0.0024224029510688844,0.01995922101616982,0.08602343944230291,0.4723069105203939,0.41828111009643604,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +6,6,False,mand,1,0.12293688899612817,0.1644760974383713,0.15959652963026888,0.21729082638893976,0.1719148596737281,0.1496036101153616,0.014181187757200762,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,False,non_mand,0,0.004203653206945777,0.004945483875130407,0.003598149852488818,0.025428743152195253,0.032497375955108355,0.11302995715962148,0.5062574221068749,0.310039214691625,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,False,non_mand,1,0.04210741577811832,0.1329856811001213,0.14892997819960876,0.21344726065060435,0.20785659810555915,0.16011532545387835,0.08309279020905272,0.011464950503049121,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,False,mand,0,0.0021012824584694017,0.0006672411030797706,0.0038073384134930995,0.0020943505765855424,0.018395846057886776,0.08786950542800698,0.44560625287674727,0.439458183085729,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +7,7,False,mand,1,0.06930725791071919,0.14037653944560585,0.16328177075866776,0.14015853278825197,0.1682047245649486,0.11416334176960255,0.17221930154119275,0.032288531221008276,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,False,non_mand,0,0.0013435715573411012,0.01230029961818488,0.01766638104178269,0.0019936868644967803,0.028005885483463208,0.04584050984339523,0.10480092095098578,0.5050913307173912,0.2829574139229501,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,False,non_mand,1,0.03430095328556757,0.12916553216501875,0.12407144933981593,0.16312580111296485,0.18020781394946458,0.14010974567167578,0.13153685442758237,0.08283058905690686,0.014651260990994843,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,False,mand,0,0.0012067963803153098,0.0002514069487143899,0.0,0.0008964277974523003,0.004972038913820343,0.022714179372248598,0.09553181475594548,0.4764865292981976,0.39794080653330005,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +8,8,False,mand,1,0.05134069912577083,0.16757533120486318,0.09887343956517608,0.0996665505448871,0.12270377398119678,0.13809878378715226,0.15430889460945024,0.15315011536579665,0.01428241181570826,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,False,non_mand,0,0.004559470206999937,0.004018845991368789,0.0007760295232695167,0.006013976920517883,0.008692144860353274,0.012851157374586298,0.03484847907479647,0.14602534703811887,0.4677379005198763,0.31447664849011464,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,False,non_mand,1,0.028970342864014863,0.07961863207288168,0.11747629066979155,0.14769342844102212,0.1523700663239815,0.14685742408550045,0.11570479846319044,0.13517062840604288,0.07389495343362677,0.00224343523994273,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,False,mand,0,0.004929616858539351,0.002514875381848358,0.0003334282185824377,0.0015409839340080169,0.0015902958303687191,0.006426324017008129,0.018789457453368623,0.08983405897399756,0.4658182846410647,0.4082226746912089,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +9,9,False,mand,1,0.061462929439804526,0.15338577649722202,0.08549602573931231,0.09024757684757531,0.07560940237251315,0.09326303621395977,0.11546627424183062,0.17230894469298577,0.13284771441289978,0.01991231954189876,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,False,non_mand,0,0.0004759779923034959,0.0023163479045703685,0.00026078698710457526,0.004038661179580536,0.028045271910474005,0.01765532211958581,0.028880477899209854,0.0595428856116037,0.1640072279689932,0.46701093878322636,0.22776610164335107,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,False,non_mand,1,0.04107841528105521,0.07823770314857553,0.15486523592282003,0.11435853904543723,0.12044817485561693,0.12325800678166501,0.09290194233821064,0.10742004090489292,0.09344368602379595,0.06604282739441104,0.007945428303517193,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,False,mand,0,0.0004494869525118119,0.0008938234818741619,0.0015315361240291418,0.0,0.005334156696620282,0.0017013361802096973,0.005076110634371264,0.03140885294342614,0.12791674700486952,0.456292321441596,0.3693956285404916,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +10,10,False,mand,1,0.06637770734519799,0.1037347269546955,0.04929764211388457,0.08000403089864469,0.05681003466616977,0.0863980114645966,0.10697579974459152,0.10876091580547065,0.19260513160181897,0.12922032129012748,0.01981567811480177,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,False,non_mand,0,0.0009065086990610609,0.006157868401284852,0.0003100705574739186,0.0009706008241725078,0.0003254632163615597,0.003130404315870445,0.020825938868845477,0.0644701163930229,0.04261762461914473,0.16051114862816465,0.43063897518796784,0.26913528028862904,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,False,non_mand,1,0.04473474589816076,0.11766077271535123,0.07177841577666452,0.1131263354696125,0.10758351836461788,0.11696281382247811,0.09159779595421777,0.09281255134137854,0.10160072093522363,0.06838552118110745,0.07099504002390444,0.002761768517284982,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,False,mand,0,0.0024792594597977742,0.0007773309530198535,0.00036874407771155974,0.0010169689392536456,0.0017630528307359774,0.0,0.002174406455855905,0.00701544991066077,0.03893266216208622,0.11181304151582698,0.42621427953007496,0.40744480416497525,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +11,11,False,mand,1,0.04409957471856176,0.12318929881910916,0.07078091352119609,0.06363033511330742,0.06462904930268315,0.06303245399572764,0.06541702315293788,0.0625756694122921,0.1199555634125709,0.17151940594087506,0.11827193197593719,0.032898780634803414,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,False,non_mand,0,0.0020469632772412783,0.005118515335118939,0.0013159156550736598,0.0,0.0007908607181557826,0.021017980277829137,0.004826785690562101,0.004123145950079362,0.05061684195463624,0.11067985112791373,0.14006899854901622,0.4469621846879527,0.2124319567764208,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,False,non_mand,1,0.03070787278819616,0.10748251498391112,0.10529354364329667,0.10498462765101912,0.09891306875650994,0.0664204336491066,0.12088536426440363,0.07410396610101483,0.07939374069499847,0.06628998760178974,0.07867960738818341,0.06259586978835742,0.004249402689215375,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,False,mand,0,0.0006372193853895992,0.0,0.005848074282949092,0.0,0.0,0.0,0.0,0.0010149435014358149,0.004569623704587577,0.028054534250587834,0.11749645384146713,0.4671681855422318,0.3752109654913544,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +12,12,False,mand,1,0.04002187637050176,0.09526836768228618,0.059358519465698846,0.03576047145014369,0.04810390407695772,0.03936412035301255,0.06365899284587356,0.07580805326819011,0.11088995914891119,0.14867772123176348,0.15146074936787685,0.10389289373200306,0.027734371006782478,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,False,non_mand,0,0.010581845746745117,0.02135469078155703,0.0,0.0015680703637736314,0.001832220432725227,0.0015572715675743669,0.004722721405453711,0.0015552119625428912,0.020301595024043714,0.05294252743383133,0.02739040080000406,0.19595135104925895,0.4558594788349525,0.20438261459753626,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,False,non_mand,1,0.08242038012633962,0.11109911021658904,0.0834599922053207,0.10526411307609268,0.09561577758278461,0.08429541153794354,0.06506213952322829,0.09335214637086123,0.051599022262841715,0.07756706269165822,0.083942634322639,0.028698585379787145,0.033703141293734674,0.003920483410179549,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,False,mand,0,0.0002114867555093238,0.0007563718036992013,0.0004421685796641646,0.00036419480365186714,0.0003682920487837825,0.0,0.0,0.0,0.008255277137243444,0.004927956685967232,0.019750154588259843,0.07994274761093642,0.3745235312581257,0.5104578187281599,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +13,13,False,mand,1,0.03460987876574106,0.07894981745463045,0.04589558870888185,0.012970377926487097,0.04808962168469219,0.05549865205893623,0.042534431425930115,0.05818052149874343,0.09295231797485712,0.0877287949553075,0.12566300567166405,0.14963976497245862,0.15526480921105232,0.012022417690619317,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,False,non_mand,0,0.0,0.0006578086994089901,0.01302603786736732,0.0,0.0006592863277712734,0.0008924786174391466,0.0005394873318307191,0.0,0.0041217132854244,0.01522305974266395,0.06622968234414911,0.0483182924082985,0.11981097037630566,0.435989256913797,0.294531926085542,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,False,non_mand,1,0.04340498068238858,0.147951761325986,0.07264071903152215,0.04281460481044742,0.07457928395632307,0.048378295570339784,0.08732960773886839,0.09219930503334722,0.09128470192088546,0.05019019945259609,0.049538071651751434,0.038355555959303296,0.0935002193823536,0.0477720540329725,0.020060639450914765,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,False,mand,0,4.3246973510772455e-05,0.0015216628366039775,0.0003993766367743454,0.0,0.0,0.0004707113297645492,0.0,0.0,0.0008075792765713283,0.0,0.006289172555100225,0.0182123246792965,0.05208444331605652,0.383581731025321,0.5365897513709964,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +14,14,False,mand,1,0.039150747297890164,0.054833142291523404,0.047082873795495445,0.03298477957620137,0.037454014256929555,0.03230432367809892,0.03327697750429275,0.03994444636251793,0.06384435747924255,0.0537960157785593,0.08442279855642591,0.097795432275471,0.14027428653059662,0.21859768986491956,0.02423811475183733,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,False,non_mand,0,0.0044221205692116855,0.0009801923634170041,0.0001427006121181721,0.0,0.000508160548952053,0.0033277464063984417,0.0,0.0028758539422529803,0.0011239627287658995,0.0,0.0025802253117421323,0.024883423167047537,0.07027269844752945,0.13059386627460212,0.5127789792728545,0.24551007035510772,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,False,non_mand,1,0.038287496457294415,0.08476197683093822,0.06360863877583045,0.07199736395846229,0.06787500929314788,0.045702973252856424,0.06344093654945081,0.10512264253660736,0.08156722082324581,0.02108868850056482,0.05209243227673514,0.020772749433657898,0.07156303760819425,0.1015023142209167,0.09097558401325304,0.019640935468845697,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,False,mand,0,0.0,0.0005626759564094324,0.0,0.0,0.0,0.0,0.0,8.384499794164758e-05,0.0,0.0,0.00029977482874100913,0.0017152465912250259,0.006761382428903971,0.03258013271517248,0.4264807243994966,0.5315162180821112,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +15,15,False,mand,1,0.016404579755016607,0.017036582483842596,0.020547731770206346,0.00917552202798977,0.01560367880929944,0.01977799822209969,0.04842708043929425,0.04219496183703155,0.041046119542705914,0.06788772643972953,0.09363143799368517,0.0691600214354772,0.11123370786224275,0.176309953591141,0.2015416109812438,0.05002128680899598,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,False,non_mand,0,0.014050345876972627,0.0,0.002801887663417347,0.0,0.0010050424815216852,0.0,0.006525236517820661,0.0,0.014459325332627424,0.004223443787743102,0.00026919822463454567,0.016861818330387683,0.025649076743019753,0.062346996473496244,0.12918228193997883,0.4133291592237026,0.30929618740467696,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,False,non_mand,1,0.040428321125155216,0.04484592663699025,0.0667567119191192,0.05512837775106797,0.06609770431106861,0.05324636312662705,0.07998282756176713,0.06446811052358363,0.049367380566723996,0.09605046020428629,0.05298377911220337,0.03895563064697063,0.036334009718150394,0.08819297038436848,0.11393408673084879,0.052515331547916544,0.000712008133150821,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,False,mand,0,0.0011212035185111234,0.0018749886523068754,0.0,0.0,0.0,0.00028843066554384513,0.0,9.23311804431816e-05,0.0001326348415503372,9.1982235892906e-05,0.00013827478127552482,0.0003449856980034226,0.0012368236023759876,0.00829463072505366,0.0655618147486044,0.5861877071626057,0.3346341921878303,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +16,16,False,mand,1,0.0027910764821412926,0.008085595626922376,0.011451177472914891,0.0165723647858112,0.03183163392055063,0.020310317987154235,0.01071127840078966,0.021878272658562025,0.02968039103033993,0.03611873034192362,0.03414105914199353,0.07098930728623262,0.07055590437293402,0.0963283759247339,0.18967984147024144,0.2957553527093214,0.053119320387436234,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,False,non_mand,0,0.0,0.023307927168187848,0.004000226473400521,0.0,0.0,0.0,0.0,0.002187330857501246,0.0008700418558189156,0.0009409359675874714,0.001356227280953211,0.0006439923704507155,0.005661031464194419,0.0016356077432996966,0.02249734694057814,0.10096010808314712,0.5461978482479335,0.2897413755469471,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,False,non_mand,1,0.03351833920961381,0.06702818639626788,0.015411469522095775,0.01683881855242247,0.0609874536578672,0.08117313707517244,0.08146730779020327,0.07861338118997839,0.030337000409543846,0.08046451494260316,0.05675737001355755,0.024748398560688913,0.04578173063779357,0.05784910499758113,0.060092288970562395,0.07839474720334631,0.11292168213191822,0.017615068738784326,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,False,mand,0,0.004556971804669404,0.0020384858508298367,0.0005035822947509159,0.0,0.0,0.0,0.0,0.0,0.00011313129719986935,0.0,0.0001060062126540252,0.0022413395351012903,0.0026615457554179586,0.0015649018415282612,0.011185263868029541,0.08327655245403838,0.4951600795598544,0.396592139525925,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +17,17,False,mand,1,0.009271208383827494,0.015623766293825708,0.00399078756047959,0.014380728254660085,0.013752189739450473,0.012552311007141435,0.018669022940268277,0.02643465832301535,0.03576568820355527,0.013812145573082291,0.014192101408299927,0.03495999795980903,0.049688706165011864,0.07343713316418343,0.13137465606423182,0.24570752186370814,0.2327606052799791,0.053626771815473206,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,False,non_mand,0,0.0003349257533891248,0.000455365657052843,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.00399069463959953,0.0,0.004974173476017343,0.011982705042316938,0.0185317456189463,0.014737218095135571,0.10300581741159799,0.4548505022677063,0.38713685203823844,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,False,non_mand,1,0.006645270632043586,0.035268301644150096,0.03719481091514608,0.0764717316909774,0.05084949163665219,0.03072605507879998,0.07965705839179173,0.055852260708506414,0.047504410609469104,0.08789454042394572,0.06391269170038437,0.05820619460013512,0.026307959991774092,0.06833216785600095,0.06690171101883549,0.04184759757726937,0.05794427704574052,0.06842048952190465,0.0400629789564728,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,False,mand,0,0.0,0.0002912943851750418,0.002560390969445633,0.0,0.0,0.0,0.0,0.0,0.0,0.00042881892002179375,3.152485934184723e-05,0.0003200038506389674,0.00010463837912428658,0.003602647489904629,0.00604940434453755,0.019344593434821866,0.1231669898863159,0.4388882258622614,0.40521146761840815,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +18,18,False,mand,1,0.0015729613791709916,0.0017028214683226762,0.00982572710017358,0.008621497005950553,0.009945983398555108,0.006473947115953141,0.010874549986303468,0.013324878858735227,0.013150668336686027,0.016233519607117226,0.030737036541870152,0.022025611353876984,0.025009784539932634,0.05236233697233131,0.12084151446919604,0.13962444085661238,0.22502388956558184,0.26406445999940914,0.028584371444223464,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,False,non_mand,0,0.0002935332102889036,0.005480040918355398,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0008255354694775797,0.0,0.0010193757706574635,0.01160812436454304,0.0,0.018093584424663776,0.036569988013863096,0.02166471490780873,0.10872350649971427,0.4933448848126991,0.302376711607928,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,False,non_mand,1,0.015167393550085784,0.06436767249690344,0.021978022060404466,0.026195047943679668,0.040972730779458254,0.05799364265524419,0.04559663345917261,0.019777271155391924,0.06983518624960366,0.08149142675680957,0.04761440004472914,0.04422216833566978,0.05654170938082257,0.014715748163634008,0.037923688559589344,0.010098284596012719,0.0942210851861242,0.16189816425443762,0.07094096850201331,0.018448755870213534,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,False,mand,0,0.0,0.0013543798954379705,0.0,0.0,2.6913303113467185e-05,0.0,0.0,2.6693623247862424e-05,0.0,0.00019994177268318624,0.0,4.717574041357856e-05,0.0,0.000219271285569539,0.0005387875450895063,0.0052995559256559495,0.018651855117429263,0.09781678251194907,0.561190661360467,0.3146279819189439,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +19,19,False,mand,1,0.00010206219094949653,0.004977279031464755,0.005971108330419951,0.0022948767165544876,0.002164702079430046,0.012235305038568204,0.0030255498152621705,0.010162563640467144,0.011899488070682994,0.017198225268187414,0.019020612349906756,0.009885372430624408,0.008398172853246283,0.03164376570178275,0.05870788437664778,0.07712669939847168,0.15123018866057794,0.2550729981107298,0.301166537224902,0.017716608711121136,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,False,non_mand,0,0.013854594349188058,0.00022662198037211477,0.0014734681064250009,0.0,0.0,0.0,0.0,0.0,0.0004810081741433067,0.001506155068759339,0.0037986706277299245,0.0,0.0,0.0013504265617815643,0.00019385758468053123,0.0,0.011048740598159513,0.0037902611286686387,0.12542702791890903,0.5746262862863871,0.26222288161479496,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,False,non_mand,1,0.021321155768967898,0.05286065953947156,0.024538352225844363,0.016613365222966726,0.0624934231537968,0.016939877445033783,0.007598242289219351,0.034768285328409386,0.046449412738704426,0.05948164439475669,0.039083023097467716,0.024127228159278466,0.009930439541584277,0.042366850927406476,0.06166640455265051,0.08632790082796032,0.06893642092451197,0.08684849677413964,0.13868866936299099,0.09896014772483963,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,False,mand,0,0.0,0.00014387922014249266,0.0,0.0014952956265923143,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.00024498308911677895,0.0007205352484350487,0.003450413811709883,0.030262487258412907,0.19937531244757992,0.5904725869974611,0.17383450630055045,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +20,20,False,mand,1,0.0001016345135907172,0.0013431148166342822,0.0025214057951854748,0.0019538419512949356,0.00031501442240043577,0.002173587504733341,0.01829238124377114,0.008201342197763316,0.006929082902138864,0.015977084047267068,0.013162826759767045,0.024777425980938576,0.012952872970959886,0.019038068519657468,0.0489058827362567,0.08297368096529972,0.0714992700699535,0.13817057595539783,0.268925469755579,0.24201236349724414,0.01977307339416366,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,False,non_mand,0,0.0,0.008080239580408306,0.00653365195023542,0.0,0.0,0.0,0.0017143244078877587,0.0,0.0,0.0,0.02330870782272815,0.0,0.0,0.0,0.0044051113856997766,0.0,0.015877969566220392,0.022756728927372263,0.03840585286610053,0.1768320521108488,0.48564207130797943,0.21644329007451926,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,False,non_mand,1,0.034988652032331806,0.028352557627599802,0.07832671759997871,0.014498479558418625,0.021452446300926627,0.044726196824526186,0.016884880651404977,0.05679465377468503,0.028301309132595515,0.05257766416225226,0.08589905275199353,0.052945334102946294,0.02088040059107313,0.011775113976478898,0.05407441616750971,0.016209732173072304,0.02881556662505882,0.05410314372690426,0.10904287723732753,0.11767750258553024,0.07167330239738584,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,False,mand,0,3.5902246180404136e-05,0.0003287418834560863,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0005844406394864265,0.0011395879163835726,0.002457512684508867,0.011903359512269136,0.058671865569636474,0.2735668072416954,0.48033203705426747,0.17097974525211096,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +21,21,False,mand,1,0.0,0.0010676949867987023,0.0003741642123714111,0.0003392872263632287,0.0019013418573134112,0.005964794433767494,0.004111667621835298,0.009152267167737024,0.009056498033029246,0.009715477313451742,0.007128756442822842,0.019287987286840905,0.008715848337179232,0.018587104375939884,0.025656997065551555,0.06942035498877833,0.0857249089840367,0.11979220774428162,0.19816034939510632,0.2715038243473685,0.12095602829796262,0.013382439881461582,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,False,non_mand,0,0.0,0.002772802942743006,0.0,0.0,0.0,0.00208710133979679,0.0,0.0012133046041248117,0.0,0.0025797578764766168,0.0,0.0,0.001444469515349913,0.0008629555916225466,0.0,0.00307704158343639,0.0,0.002830643430422829,0.01769971550817686,0.085323665686875,0.3241131645539106,0.3352579379799715,0.22073743938709334,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,False,non_mand,1,0.003943202011583586,0.07590482767457281,0.010022084233224371,0.009004346978365886,0.01944597202531891,0.014149940036728577,0.04861335549448911,0.005658799896185953,0.08215714869482671,0.04271279267950798,0.049004045967736616,0.05661020516859074,0.05007057791871834,0.019629252201956937,0.020925406925534316,0.032621056163113483,0.01305643867359321,0.07832145179247733,0.06858371853794595,0.12530957849750027,0.13601874202743744,0.03692457599698219,0.0013124804036092647,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,False,mand,0,0.0033319545069183487,0.00040293376633402495,0.0,4.978674800183608e-05,4.956840826720383e-05,0.0,0.0,0.00048080827168619404,0.0,0.0,0.00037907395233851166,0.0,0.0,0.0,0.0,0.0010411329007553862,0.0006886689934808201,0.0018842792130508302,0.030055426235856154,0.11106661717859341,0.34783111970489866,0.38452147913984164,0.11821715097997308,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +22,22,False,mand,1,0.0,0.0009844126997186388,0.0011967267681276734,0.0019472708709395152,0.00306324636258839,0.005218500288671079,0.008959996278556434,0.013328186876110292,0.01948593457473374,0.0029207397730027914,0.016523202648888523,0.012774503142272065,0.012979848878806757,0.016499438380020322,0.02892590011752825,0.06721987003262893,0.08228486043678297,0.06297809963520319,0.14050401489836273,0.22635805834453743,0.21126684046820765,0.06107107140955881,0.00350927711475168,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,False,non_mand,0,0.020946657824256545,0.0,0.0,0.0,0.0,0.0,0.004711436323343341,0.0,0.0,0.0005332302439481441,0.0,0.0,0.0,0.0,0.0028469849527635485,0.0,0.003752044056675865,0.0060734526097271195,0.005376679727065213,0.018229286160826877,0.0893450127112203,0.1946541464012934,0.3979914205914805,0.25553964839739934,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,False,non_mand,1,0.013495568361334306,0.015067442486257767,0.0,0.01857213338220899,0.011450767637648131,0.01054539852032298,0.0325342310595822,0.014967514051863,0.0600307214086128,0.06913683245424698,0.08408790287712406,0.054831404843056694,0.02182393095144691,0.04507909184868209,0.031070400701647148,0.04154822675716908,0.023259329978976354,0.06718347019519803,0.06520816539610565,0.05050121284258412,0.11023952111018313,0.09952041831559622,0.05696863823292922,0.00287767658722409,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0006021162410303741,0.0,0.0063030418216984685,0.0,0.0,0.0,0.0,0.0,0.00021618365840965026,0.0,0.00033124132710278336,0.0002795232526629928,0.001709205247850362,0.0018169391708012528,0.021116367316931353,0.1734276051812627,0.26303548645617175,0.40599341260436056,0.12516887772171442,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +23,23,False,mand,1,0.0005664297327648591,0.0016667589289531017,0.0017746929301902608,0.004883182110559827,0.0016371396888604573,0.0033712624678077915,0.0,0.0005555037786081591,0.0058865336484199195,0.012019305681875423,0.01002769786944633,0.0038787403968613982,0.007739255591478886,0.030853128423908176,0.022978737087604693,0.06756447135089728,0.06384320606476022,0.07193296371300899,0.14178927759270055,0.1678106068493928,0.18046286971892364,0.15990714563785483,0.03786010827300599,0.0009909824621165745,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,False,non_mand,0,0.001957236455297285,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.002139163740884773,0.0,0.0,0.0,0.0,0.0,0.004861403580473194,0.014696944307544956,0.0,0.006362562379164253,0.0,0.030924532083993154,0.16087761163198888,0.16507515037083167,0.49147707095271914,0.12162832449710316,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,False,non_mand,1,0.004658839008606419,0.031109764265227966,0.0031358654271668065,0.007135974233933102,0.022284415150529348,0.045165743434747045,0.03467575600780006,0.029249486464707687,0.016528250759267955,0.044217071484616434,0.05052768525351878,0.026021451442437685,0.020810508617239865,0.05510583769065272,0.0653719796812064,0.06162011175881972,0.04348047893484723,0.02955610197534336,0.044209350767777114,0.08979342087125931,0.07450566834376521,0.11556001515984184,0.07585893374518235,0.0,0.009417289521505862,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,False,mand,0,0.0,0.0012614821175236817,0.0,0.0009483979593045735,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,9.798584859674903e-05,0.0,0.0007660491638100698,0.0,0.0,0.0019123735615852804,0.0008663669483088619,0.004302987999128094,0.04625657711687475,0.17518637256962677,0.30146158026255426,0.35473324543549245,0.11220658101719452,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +24,24,False,mand,1,0.0004273288234473731,0.00048395960583567954,0.0,0.004412445943197242,0.0013813769998042077,0.0006865842481945973,0.0030763780403890366,0.0010409122039024103,0.003904455225818047,0.007212567117042947,0.02272289997510155,0.006219000048672273,0.012474286827782032,0.01971598808855006,0.03399285316467546,0.03491920715439283,0.03650142127196347,0.06084846208894538,0.13514622420931124,0.13700214086205523,0.15371146352951298,0.17698954947094717,0.10153619524905207,0.043787551002105955,0.0018067488493017003,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,25,False,non_mand,0,0.0,0.026855467767289344,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0051884196592915325,0.0,0.0,0.0,0.0,0.0,0.0,0.01236158321943575,0.0,0.014676963582940926,0.041784470228698634,0.012771413566842436,0.09982169057332398,0.12081608047775094,0.5289034488282967,0.13682046209612983,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,25,False,non_mand,1,0.005205279463922217,0.042238707562628146,0.017900291924254377,0.07230496755756445,0.02750209063570552,0.008254141459919673,0.02685029411104523,0.02129477270095243,0.014820981886008321,0.007442876456201476,0.061368631180781834,0.04859090710876045,0.010779476678561986,0.0021181593731498323,0.04204879677467802,0.018961013921286456,0.00528557522604036,0.0060082585179672375,0.03614187488234714,0.15823571685080345,0.09822016733925946,0.06922820156058726,0.03700690352034442,0.03381012329710709,0.12838179001012345,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,25,False,mand,0,0.0010447700996694333,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0015226397157089662,0.0,0.0,0.0009403214751077665,0.0,0.002731049479785308,0.0,0.001992005134632034,0.004389706257466054,0.011114410719972786,0.1097896710326778,0.17012499798677858,0.24343612562029995,0.33832497455701194,0.11458932792088994,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +25,25,False,mand,1,0.00010113064033479776,0.00010113064033479776,0.0,0.0009593244487670843,0.008620759851692944,0.0,0.008874859291453811,0.003452633512794278,0.0018134409243518086,0.004356931975913798,0.005233383881383854,0.013581909702358333,0.009571366298209278,0.010726786393504573,0.01934779615544867,0.033664487334236076,0.08534550964421805,0.12065718642222509,0.08869241945051536,0.13354844628738305,0.11046731204818085,0.11292664234524964,0.07664839693148495,0.10677927592879725,0.04055021472419117,0.003978655166971246,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +26,26,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.05638197040670044,0.086772396809289,0.12754790024816223,0.12145320114349349,0.4270529910776051,0.18079154031474942,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +26,26,False,non_mand,1,0.0032816541532269144,0.004723626004281977,0.026439011226640424,0.0005880721513242938,0.042172106569430566,0.0007220328446468592,0.012760069622394126,0.022646845870121123,0.0070380593365810444,0.021621077765149294,0.004406268444740761,0.05178888301094209,0.004194300766825882,0.019594593157807948,0.05498509339253303,0.015576055941276168,0.044711322373922974,0.03851088324294953,0.0965578912979413,0.19939592028453582,0.032901430193206405,0.04076944104804929,0.06600611906708521,0.017104172995515886,0.02091244051020818,0.15059262872866347,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +26,26,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0010097336126187006,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.001441050016718605,0.0,0.0,0.0046066100976096145,0.013521444204739937,0.04544363682134943,0.06666196076952169,0.16690657011014065,0.2887578863218669,0.27309966945130104,0.13855143859413344,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +26,26,False,mand,1,0.0,0.00012169349614156285,0.0,0.0,0.0013173695741662316,0.0009265168581856395,0.0031389015898456783,0.0020165199440940257,0.010271836279595626,0.009057459962892419,0.0056692219406281,0.01070424223648886,0.020558169356061695,0.023885629242994217,0.021160318030269843,0.07225119188773171,0.03788655313040271,0.09567453552181272,0.09303908498691627,0.11786802715893488,0.14714781743007943,0.10076138476440295,0.07335439048371141,0.04477248140682615,0.0658474705618937,0.03720864052146022,0.005360543634463427,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +27,27,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.08321242053607554,0.0,0.0,0.0,0.0,0.0,0.0,0.1338447602742628,0.03668550180000455,0.49717047549970805,0.249086841889949,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +27,27,False,non_mand,1,0.0,0.004365998971203495,0.005526284200613821,0.0008911511944426591,0.0011596535370158579,0.003395153940115188,0.04538785874219372,0.0055802080224916385,0.004506717471949083,0.0,0.008296915415056333,0.12606703843688324,0.0033068758467361585,0.0026176551091245783,0.015491058421315896,0.03168870370601159,0.006165764836894523,0.0,0.028471518309172703,0.06427089762850444,0.059166792379607605,0.07619714332429037,0.06634515151233768,0.1665278885843596,0.2437273109787969,0.005253026115539571,0.025593233315344036,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +27,27,False,mand,0,0.0,0.0,0.0,0.0,0.00462768920781746,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0035328639744926383,0.0,0.0,0.0,0.0,0.0,0.0,0.0015195476841073636,0.016350375623336286,0.05513216116239345,0.05024722754740453,0.08374001115365137,0.23742738630739216,0.37190299673247407,0.17551974060693057,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +27,27,False,mand,1,0.0,0.0,0.0030853357555393544,0.0,0.007355900477770891,0.0,0.004476242658243728,0.0,0.002450323584012583,0.003127720585114698,0.0012324417543434169,0.005909487945169219,0.02231052237177983,0.021531899261560544,0.023875777308208983,0.029564153701998417,0.06627080391668981,0.07286626003978702,0.11836336264770164,0.09964250780261288,0.11905552110276761,0.09884716142339667,0.1375407692998142,0.055388982752597564,0.04418894367205662,0.037359235713303,0.024159309154340412,0.001397337071189429,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +28,28,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.005893423084126639,0.0,0.0,0.0,0.0,0.0,0.0,0.06161217745176845,0.012370949015906263,0.054056220103717884,0.6963123577829712,0.1697548725615096,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +28,28,False,non_mand,1,0.005932528749905598,0.009505545485504526,0.008695916728570308,0.009401284500361828,0.02066641400789642,0.051459663047809814,0.04223797307726802,0.0,0.007850433332501685,0.0,0.0069687141103478385,0.0,0.0025233289149239452,0.005679781768764818,0.018155975879139228,0.0,0.1477910941309391,0.0,0.006931105738499081,0.09073055144548066,0.19310915989343444,0.023804251999506372,0.003093163529902435,0.0,0.0,0.15376188747556613,0.12610302068418353,0.06559820549949387,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +28,28,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0008351107514563876,0.012044830966816321,0.02979571436041339,0.02950318899023904,0.08606776129729246,0.10639999593145809,0.2857411728554919,0.393745903142871,0.05586632170396188,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +28,28,False,mand,1,0.0,0.0,0.0,0.0,0.0,0.0019523840336447369,0.0,0.0,0.004671328994893418,0.0029056025069879037,0.028440969718154557,0.01074815253397821,0.0010004579810449796,0.01370332771073568,0.009523342437613025,0.028630559942846363,0.09460687744328454,0.07838474387055222,0.09177519973357763,0.10582855612136319,0.1478180879239831,0.06990112601414306,0.1038704503553094,0.06580411575211609,0.05550725738512009,0.042589253745558386,0.03146743928459926,0.01087076651049371,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +29,29,False,non_mand,0,0.0,0.0,0.04816934499315065,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.018613280602750668,0.0,0.019038253732547417,0.1616884514392184,0.0,0.0,0.03538469184099581,0.002470550707674957,0.12096372328811623,0.25912170627301173,0.3345499971225342,0.0,0.0,0.0,0.0,0.0,1.0 +29,29,False,non_mand,1,0.0,0.0,0.011625503605139476,0.00449176304936865,0.0,0.017260228259021338,0.007694527003352663,0.011835476784643568,0.0,0.30530009965298444,0.0,0.020218763234210593,0.0,0.009332348224563141,0.16159285646221677,0.02292660165756739,0.0,0.06405190543802423,0.11240285054736682,0.03807948441655916,0.17379470427728044,0.00635750952735676,0.004066864440049928,0.003541161546199974,0.016751699114957996,0.0,0.00635750952735676,0.002318143231779766,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +29,29,False,mand,0,0.0,0.0,0.003934712829786398,0.0,0.005495865779772318,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.006241144008995931,0.0,0.0,0.0007979160784828135,0.0,0.0,0.0,0.0,0.0183907917637835,0.04117427671427664,0.015079814294754976,0.1166730947201058,0.19244374077248716,0.45975383301587736,0.1400148100216773,0.0,0.0,0.0,0.0,0.0,1.0 +29,29,False,mand,1,0.0,0.0,0.009577616659769035,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.03749246066899982,0.0,0.009565906440226353,0.017607420525218333,0.010279925578379836,0.06737171658058286,0.057031143230995715,0.04668780808310395,0.10257497787647352,0.1364103583114607,0.12669323680904365,0.0971845822447083,0.06855366388867322,0.05448418300195883,0.02211515686869544,0.013671105485262873,0.04090098427472115,0.04507357237068319,0.03333332875041091,0.0033908523506327596,0.0,0.0,0.0,0.0,0.0,1.0 +30,30,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.061802484025478444,0.0,0.27015710745904653,0.043233624690139666,0.3572952814818533,0.2675115023434822,0.0,0.0,0.0,0.0,1.0 +30,30,False,non_mand,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.012418494674007168,0.0,0.24675165306293573,0.0,0.08617252673192825,0.04363889956401214,0.0,0.0,0.013245525905700285,0.006858576451340298,0.05822476466129167,0.02643379066772429,0.1168462326698982,0.0507176389333524,0.14675829754376166,0.1713043210897166,0.00978849987936505,0.0,0.0,0.0051628226199749655,0.0,0.0,0.005677955544991209,0.0,0.0,0.0,0.0,0.0,1.0 +30,30,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.007547370393836327,0.0,0.015229507359741521,0.11353399101555982,0.10503974728823559,0.22536193435006424,0.39521505871092594,0.1380723908816365,0.0,0.0,0.0,0.0,1.0 +30,30,False,mand,1,0.0,0.0,0.04281100958118251,0.0,0.0,0.0,0.0,0.0017845947566491568,0.014438582121224591,0.0,0.0027362482023577336,0.0,0.007924810335435397,0.014161034730439585,0.010645978191166163,0.015090083084884505,0.10481464461430465,0.04918662684180706,0.08149212883106766,0.02926872033665626,0.19552008579721641,0.12458798679258958,0.05911080652651869,0.033423081415431335,0.02523561789122675,0.0024912639521436444,0.060528357818212065,0.020157276783711174,0.033825970908845975,0.06224870185486725,0.008516388632062234,0.0,0.0,0.0,0.0,1.0 +31,31,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.029977424692256244,0.46967591059198405,0.50034666471576,0.0,0.0,0.0,1.0 +31,31,False,non_mand,1,0.0,0.0,0.0,0.01833810824001649,0.0,0.0,0.0,0.0,0.011516290886021865,0.16308529577680958,0.0,0.0,0.0,0.02547074507105579,0.01652281484738158,0.0,0.04452351185239044,0.009317122261056536,0.19971424002149518,0.013045312623538401,0.0075661778015869464,0.3102328065307183,0.0,0.025003003703219125,0.035055083246462164,0.030069783720618536,0.018526881151892546,0.034928530599363024,0.037084291666373344,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +31,31,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.011660697134411879,0.08359356906747217,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0074351633681512585,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.053515133972031996,0.0,0.046642788537647514,0.06362339255281085,0.004389112388089102,0.04017428022808142,0.4817135990383709,0.20725226371293273,0.0,0.0,0.0,1.0 +31,31,False,mand,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.014153420408759243,0.0,0.0,0.0,0.0,0.023248141345199345,0.008890938931074744,0.05285349575062624,0.04990553163058654,0.16677175839150424,0.11331994669851629,0.1181638409115989,0.07387812106291494,0.15865917983104275,0.031235937800509726,0.06596532918651592,0.035468217376292764,0.013865230438545558,0.033059807910658684,0.03141248412869757,0.006106628878031803,0.003041989318924492,0.0,0.0,0.0,0.0,1.0 +32,32,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.09030713454422928,0.10225330344102772,0.0,0.0,0.0,0.0,0.34201165614137685,0.10656854103943249,0.35885936483393366,0.0,0.0,1.0 +32,32,False,non_mand,1,0.0,0.03615936143527503,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.11870838866384083,0.0,0.0,0.030664587449557346,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.026266199236874226,0.0,0.0,0.08761524377109123,0.0,0.0,0.7005862194433614,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +32,32,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.05789616370086815,0.1344598373883522,0.3375637056076247,0.2230108052807423,0.24706948802241244,0.0,0.0,1.0 +32,32,False,mand,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.009238420497671889,0.0,0.0,0.0,0.0,0.0,0.0,0.027952902624459142,0.004745183696099721,0.041750935844626774,0.03560104623729895,0.019208273165269348,0.039862390831722126,0.2445054537893148,0.1472889280930601,0.10677793164025022,0.07872994398102684,0.04261569901118799,0.005675051098870241,0.0815413323203732,0.019486477408908912,0.0,0.09502002975985951,0.0,0.0,0.0,0.0,0.0,1.0 +33,33,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.3937868145193479,0.4486503063939636,0.15756287908668853,0.0,1.0 +33,33,False,non_mand,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.020230772694571117,0.0,0.13595146003291136,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.09279893744389224,0.0,0.0,0.07918749737876385,0.0,0.0,0.12358922634696451,0.07179448760198139,0.0,0.0,0.1394804713644242,0.0,0.2868037587900601,0.0,0.0,0.05016338834643131,0.0,0.0,1.0 +33,33,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.21087359210326426,0.35509399657354956,0.28936975269124166,0.14466265863194447,0.0,1.0 +33,33,False,mand,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.023247760476100464,0.0,0.024677767802522798,0.0,0.009363181643807422,0.029519156456030052,0.11193010731182607,0.02285317247116739,0.051385963088573655,0.04473753625556975,0.14095762264166245,0.055024985843556244,0.17384148255260748,0.029384651649520036,0.16325933704399054,0.03425760908549876,0.013563487427945331,0.015926159431522906,0.007948502073252565,0.0,0.022039827009254335,0.005005115351559031,0.013479183790602863,0.0,0.007597390593429946,0.0,0.0,1.0 +34,47,False,non_mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.018384368573649112,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.5577089454113409,0.0,0.4239066860150099,1.0 +34,47,False,non_mand,1,0.016657687671303212,0.02183836474581605,0.0,0.021670440655999233,0.0,0.10173930098123364,0.02498724707017388,0.0,0.14226492691657533,0.004760495563960537,0.0,0.0,0.0,0.0,0.0,0.0,0.02638875495711764,0.0,0.0,0.05929170885647927,0.0,0.0,0.0,0.0,0.0,0.008986741490552959,0.0,0.0,0.22252478651398835,0.033523970436925156,0.0,0.010929820731753599,0.017516567897537586,0.28691918551058354,0.0,1.0 +34,47,False,mand,0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0778976250021037,0.030793465479170962,0.0,0.0,0.012379085610171855,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.07427570742104288,0.0,0.0,0.0,0.0,0.10023495355353525,0.26524960444707757,0.1397015192237292,0.29946803926316845,1.0 +34,47,False,mand,1,0.0,0.0,0.0,0.0,0.1018436706346972,0.0,0.0,0.0,0.0,0.002263878168597051,0.0,0.000983293615706626,0.0,0.008218649939220985,0.023737052572553673,0.021264126033222547,0.05518389314660721,0.010993620292826722,0.20415745418381434,0.07475058698068834,0.07116274568401747,0.07424603443354091,0.06495972196633373,0.03217245961981454,0.08352494702875252,0.03514324066332105,0.026534322261271913,0.04879548794140681,0.004334841005982029,0.02812637911830777,0.0,0.0,0.015797438844245334,0.0,0.011806155865071414,1.0 diff --git a/activitysim/examples/prototype_semcog/configs/joint_tour_scheduling.yaml b/activitysim/examples/prototype_semcog/configs/joint_tour_scheduling.yaml old mode 100755 new mode 100644 diff --git a/activitysim/examples/prototype_semcog/configs/logging.yaml b/activitysim/examples/prototype_semcog/configs/logging.yaml old mode 100755 new mode 100644 diff --git a/activitysim/examples/prototype_semcog/configs/tour_scheduling_joint.csv b/activitysim/examples/prototype_semcog/configs/tour_scheduling_joint.csv old mode 100755 new mode 100644 diff --git a/conda-environments/activitysim-dev-base.yml b/conda-environments/activitysim-dev-base.yml index ac061b6ea..1e63b621d 100644 --- a/conda-environments/activitysim-dev-base.yml +++ b/conda-environments/activitysim-dev-base.yml @@ -16,11 +16,11 @@ dependencies: - python=3.9 - pip - asv # for benchmarking -- black +- black >= 22.0,<23 - bump2version # for making a release - coveralls -- cytoolz >= 0.8.1 -- dask +- cytoolz = 0.12.* +- dask = 2023.3.* - descartes - filelock - fsspec @@ -30,44 +30,45 @@ dependencies: - ipykernel # so this env will appear in jupyter as a selection - isort - jupyterlab -- larch >= 5.5.8 +- larch = 5.7.* - matplotlib - myst-parser # allows markdown in sphinx - nbconvert - nbformat -- numba >= 0.55.2 +- numba = 0.56.* - numexpr -- numpy >= 1.16.1,<=1.21 +- numpy = 1.23.* - numpydoc -- openmatrix >= 0.3.4.1 -- orca >= 1.6 -- pandas >= 1.1.0 +- openmatrix = 0.3.* +- orca = 1.8 +- pandas = 1.4.* +- platformdirs = 3.2.* - pre-commit -- psutil >= 4.1 -- pyarrow >= 2.0 +- psutil = 5.9.* +- pyarrow = 11.* - pycodestyle -- pydantic +- pydantic = 1.10.* - pydata-sphinx-theme -- pyinstrument -- pypyr +- pyinstrument = 4.4 +- pypyr = 5.8.* - pytables >=3.5.1,<3.7 -- pytest +- pytest = 7.2.* - pytest-cov - pytest-regressions -- pyyaml >= 5.1 -- requests >= 2.7 -- rich +- pyyaml = 6.* +- requests = 2.28.* +- rich = 13.3.* - ruby # required for benchmarking pre-commit hooks - setuptools_scm -- scikit-learn >= 1.1 +- scikit-learn = 1.2.* - simwrapper > 1.7 - snakeviz # for profiling -- sphinx -- sphinx_rtd_theme -- sphinx-argparse -- xarray >= 0.21 +- sphinx = 6.1.* +- sphinx_rtd_theme = 1.2.* +- sphinx-argparse = 0.4.* +- xarray = 2023.2.* - xmle -- zarr +- zarr = 2.14.* - pip: - autodoc_pydantic diff --git a/conda-environments/activitysim-dev.yml b/conda-environments/activitysim-dev.yml index 40e03ec10..cac073df6 100644 --- a/conda-environments/activitysim-dev.yml +++ b/conda-environments/activitysim-dev.yml @@ -12,11 +12,11 @@ dependencies: - python=3.9 - pip - asv # for benchmarking -- black +- black >= 22.0,<23 - bump2version # for making a release - coveralls -- cytoolz >= 0.8.1 -- dask +- cytoolz = 0.12.* +- dask = 2023.3.* - descartes - filelock - fsspec @@ -26,45 +26,46 @@ dependencies: - ipykernel # so this env will appear in jupyter as a selection - isort - jupyterlab -- larch >= 5.5.8 +- larch = 5.7.* - matplotlib - myst-parser # allows markdown in sphinx - nbconvert - nbformat -- numba >= 0.56.4 +- numba = 0.56.* - numexpr -- numpy >= 1.16.1 +- numpy = 1.23.* - numpydoc -- openmatrix >= 0.3.4.1 -- orca >= 1.6 -- pandas >= 1.1.0 +- openmatrix = 0.3.* +- orca = 1.8 +- pandas = 1.4.* +- platformdirs = 3.2.* - pre-commit -- psutil >= 4.1 -- pyarrow >= 2.0 +- psutil = 5.9.* +- pyarrow = 11.* - pycodestyle -- pydantic +- pydantic = 1.10.* - pydata-sphinx-theme -- pyinstrument -- pypyr +- pyinstrument = 4.4 +- pypyr = 5.8.* - pytables >=3.5.1,<3.7 -- pytest +- pytest = 7.2.* - pytest-cov - pytest-regressions -- pyyaml >= 5.1 -- requests >= 2.7 -- rich +- pyyaml = 6.* +- requests = 2.28.* +- rich = 13.3.* - ruby # required for benchmarking pre-commit hooks - setuptools_scm -- scikit-learn >= 1.1 +- scikit-learn = 1.2.* - sharrow >= 2.5.2 - simwrapper > 1.7 - snakeviz # for profiling -- sphinx -- sphinx_rtd_theme -- sphinx-argparse -- xarray >= 0.21 +- sphinx = 6.1.* +- sphinx_rtd_theme = 1.2.* +- sphinx-argparse = 0.4.* +- xarray = 2023.2.* - xmle -- zarr +- zarr = 2.14.* - pip: - autodoc_pydantic diff --git a/conda-environments/docbuild.yml b/conda-environments/docbuild.yml index 782eff73d..879338d1c 100644 --- a/conda-environments/docbuild.yml +++ b/conda-environments/docbuild.yml @@ -12,7 +12,7 @@ channels: dependencies: - python=3.9 - pip -- black +- black >= 22.0,<23 - bump2version - coveralls - cytoolz >= 0.8.1 diff --git a/conda-environments/github-actions-tests.yml b/conda-environments/github-actions-tests.yml index f94ca7130..28d6c51f8 100644 --- a/conda-environments/github-actions-tests.yml +++ b/conda-environments/github-actions-tests.yml @@ -7,28 +7,29 @@ channels: - conda-forge dependencies: - pip -- black +- black >= 22.0,<23 - coveralls -- cytoolz >= 0.8.1 +- cytoolz = 0.12.* +- dask = 2023.3.* - isort - nbmake -- numba >= 0.56.4 -- numpy >= 1.16.1 -- openmatrix >= 0.3.4.1 -- orca >= 1.6 -- pandas >= 1.1.0 -- psutil >= 4.1 -- pyarrow >= 2.0 -- pypyr >= 5.3 +- numba = 0.56.* +- numpy = 1.23.* +- openmatrix = 0.3.* +- orca = 1.8 +- pandas = 1.4.* +- platformdirs = 3.2.* +- psutil = 5.9.* +- pyarrow = 11.* +- pypyr = 5.8.* - pytables >= 3.5.1,<3.7 # orca's constraint -- pytest +- pytest = 7.2.* - pytest-cov - pytest-regressions -- pyyaml >= 5.1 -- requests >= 2.7 -- scikit-learn >= 1.1 +- pyyaml = 6.* +- requests = 2.28.* +- scikit-learn = 1.2.* - sharrow >= 2.5.2 - simwrapper > 1.7 -- scikit-learn >= 1.1.1 -- xarray >= 0.21 -- zarr +- xarray = 2023.2.* +- zarr = 2.14.* diff --git a/docs/examples.rst b/docs/examples.rst index add56f8b3..0b9634d28 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -290,7 +290,7 @@ After the frequency and time-of-day for work and school tours are determined, th next major model component relates to joint household travel. This component produces a number of joint tours by travel purpose for the entire household, travel party composition in terms of adults and children, and then defines the participation of each household -member in each joint household tour. It is followed by choice of destination and time-ofday. +member in each joint household tour. It is followed by choice of destination and time-of-day. The next stage relates to maintenance and discretionary tours that are modeled at the individual person level. The models include tour frequency, choice of destination and time @@ -513,7 +513,6 @@ Configuration This section has been moved to :ref:`configuration`. - .. _sub-model-spec-files: Sub-Model Specification Files diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index e3eee6088..69ed9392d 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -24,7 +24,7 @@ installs a variety of things on your system, and it is quite likely to be flagge Windows, anti-virus, or institutional IT policies as "unusual" software, which may require special treatment to actually install and use. -Download the installer from GitHub `here `__. It is strongly recommended to choose the option to install "for me only", as this should not require administrator privileges on your machine. Pay attention to the *complete path* of the installation location. You will need to know @@ -190,8 +190,14 @@ ActivitySim includes a :ref:`cli` for creating examples and running the model. To setup and run the primary example (see :ref:`examples`), do the following: * Open a command prompt -* Activate the conda environment with ActivitySim installed (i.e. ``conda activate asim``) -* Type ``activitysim create -e prototype_mtc -d test_prototype_mtc`` to copy the very small prototype_mtc example to a new test_prototype_mtc directory +* If you installed ActivitySim using conda environments, activate the conda + environment with ActivitySim installed (i.e. ``conda activate asim``) +* Or, if you used the :ref:`pre-packaged installer`, + replace all the commands below that call ``activitysim ...`` with the complete + path to your installed location, which is probably something + like ``c:\programdata\activitysim\scripts\activitysim.exe``. +* Type ``activitysim create -e prototype_mtc -d test_prototype_mtc`` to copy + the very small prototype_mtc example to a new test_prototype_mtc directory * Change to the test_prototype_mtc directory * Type ``activitysim run -c configs -o output -d data`` to run the example * Review the outputs in the output directory diff --git a/docs/models.rst b/docs/models.rst index ef79a38cd..d7249a353 100644 --- a/docs/models.rst +++ b/docs/models.rst @@ -1211,8 +1211,8 @@ Core Table: ``trips`` | Result Field: ``purpose, destination`` | Skims Keys: ``o .. _trip_scheduling: -Trip Scheduling (Probablistic) ------------------------------- +Trip Scheduling (Probabilistic) +------------------------------- For each trip, assign a departure hour based on an input lookup table of percents by tour purpose, direction (inbound/outbound), tour hour, and trip index. @@ -1232,6 +1232,41 @@ The trip scheduling model does not use mode choice logsums. Alternatives: Available time periods in the tour window (i.e. tour start and end period). When processing stops on work tours, the available time periods is constrained by the at-work subtour start and end period as well. +In order to avoid trip failing, a new probabilistic trip scheduling mode was developed named "relative". +When setting the _scheduling_mode_ option to relative, trips are scheduled relative to the previously scheduled trips. +The first trip still departs when the tour starts and for every subsequent trip, the choices are selected with respect to +the previous trip depart time. Inbound trips are no longer handled in reverse order. The key to this relative mode is to +index the probabilities based on how much time is remaining on the tour. For tours that include subtours, the time remaining will +be based on the subtour start time for outbound trips and will resume again for inbound trips after the subtour ends. +By indexing the probabilities based on time remaining and scheduling relative to the previous trip, scheduling trips in relative +mode will not fail. Note also that relative scheduling mode requires the use of logic +version 2 (see warning about logic versions, below). + +An example of trip scheduling in relative mode is included in the :ref:`prototype_mwcog` example. In this example, trip +scheduling probabilities are indexed by the following columns: + * periods_left_min: the minimum bin for the number of time periods left on the tour. + * periods_left_max: the maximum bin for the number of time periods left on the tour. This is the same as periods_left_min until the final time period bin. + * outbound: whether the trip occurs on the outbound leg of a tour. + * tour_purpose_grouped: Tour purpose grouped into mandatory and non-mandatory categories + * half_tour_stops_remaining_grouped: The number of stops remaining on the half tour with the categories of 0 and 1+ +Each of these variables are listed as merge columns in the trip_scheduling.yaml file and are declared in the trip scheduling preprocessor. +The variables above attempt to balance the statistics available for probability creation with the amount of segmentation of trip characteristics. + +.. warning:: + + Earlier versions of ActivitySim contained a logic error in this model, whereby + the earliest departure time for inbound legs was bounded by the maximum outbound + departure time, even if there was a scheduling failure for one or more outbound + leg departures and that bound was NA. For continuity, this process has been + retained in this ActivitySim component as *logic_version* 1, and it remains the + default process if the user does not explicitly specify a logic version in the + model settings yaml file. The revised logic includes bounding inbound legs only + when the maximum outbound departure time is well defined. This version of the + model can be used by explicitly setting `logic_version: 2` (or greater) in the + model settings yaml file. It is strongly recommended that all new model + development efforts use logic version 2; a future version of ActivitySim may + make this the default for this component, and/or remove logic version 1 entirely. + The main interface to the trip scheduling model is the :py:func:`~activitysim.abm.models.trip_scheduling.trip_scheduling` function. This function is registered as an Inject step in the example Pipeline. diff --git a/setup.cfg b/setup.cfg index cb3b41388..b2736a99a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,7 +29,7 @@ install_requires = numpy >= 1.16.1 openmatrix >= 0.3.4.1 orca >= 1.6 - pandas >= 1.1.0 + pandas >= 1.4, <2 psutil >= 4.1 pyarrow >= 2.0 pypyr >= 5.3 diff --git a/test/auto_ownership/.gitkeep b/test/auto_ownership/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/auto_ownership/configs/annotate_households.csv b/test/auto_ownership/configs/annotate_households.csv new file mode 100644 index 000000000..ad2c67bab --- /dev/null +++ b/test/auto_ownership/configs/annotate_households.csv @@ -0,0 +1,19 @@ +Description,Target,Expression +#,, annotate households table after import +,_PERSON_COUNT,"lambda query, persons, households: persons.query(query).groupby('household_id').size().reindex(households.index).fillna(0).astype(np.int8)" +number of non_workers,num_non_workers,households.hhsize - households.num_workers +number of drivers,num_drivers,"_PERSON_COUNT('16 <= age', persons, households)" +num_adults,num_adults,"_PERSON_COUNT('adult', persons, households)" +num_children,num_children,"_PERSON_COUNT('~adult', persons, households)" +num_young_children,num_young_children,"_PERSON_COUNT('age <= 5', persons, households)" +num_children_6_to_15,num_children_6_to_15,"_PERSON_COUNT('6 <= age <= 15', persons, households)" +num_children_16_to_17,num_children_16_to_17,"_PERSON_COUNT('16 <= age <= 17', persons, households)" +num_college_age,num_college_age,"_PERSON_COUNT('18 <= age <= 24', persons, households)" +# get definition from travel model two +num_young_adults,num_young_adults,"_PERSON_COUNT('18 <= age <= 24', persons, households)" +num_young_retirees,num_young_retirees,"_PERSON_COUNT('65 <= age <= 79', persons, households)" +num_old_retirees,num_old_retirees,"_PERSON_COUNT('80 <= age', persons, households)" +num_persons_18_to_35,num_persons_18_to_35,"_PERSON_COUNT('18 <= age <= 35', persons, households)" +num_persons_65_plus,num_persons_65_plus,"_PERSON_COUNT('65 <= age', persons, households)" +num_highschool_graduates,num_highschool_graduates,"_PERSON_COUNT('9 <= education_attainment', persons, households)" +#mobility av share, mobility_av_share, setting('mobility_av_share') diff --git a/test/auto_ownership/configs/annotate_landuse.csv b/test/auto_ownership/configs/annotate_landuse.csv new file mode 100644 index 000000000..65237c0ad --- /dev/null +++ b/test/auto_ownership/configs/annotate_landuse.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +#,, annotate landuse table after import +household_density,household_density,land_use.TOTHH / land_use.TOTACRE +employment_density,employment_density,land_use.TOTEMP / land_use.TOTACRE +population_density,population_density,land_use.TOTPOP / land_use.TOTACRE +density_index,density_index,(household_density *employment_density) / (household_density + employment_density).clip(lower=1) \ No newline at end of file diff --git a/test/auto_ownership/configs/annotate_persons.csv b/test/auto_ownership/configs/annotate_persons.csv new file mode 100644 index 000000000..d52946719 --- /dev/null +++ b/test/auto_ownership/configs/annotate_persons.csv @@ -0,0 +1,40 @@ +Description,Target,Expression +#,, annotate persons table after import +age_16_to_19,age_16_to_19,"persons.age.between(16, 19)" +age_16_p,age_16_p,persons.age >= 16 +adult,adult,persons.age >= 18 +male,male,persons.sex == 1 +female,female,persons.sex == 2 +# TODO add ptype annotation +#,ptype, +#presence of non_worker other than self in household,has_non_worker,"other_than(persons.household_id, persons.ptype == PTYPE_NONWORK)" +#presence of retiree other than self in household,has_retiree,"other_than(persons.household_id, persons.ptype == PTYPE_RETIRED)" +#presence of preschooler other than self in household,has_preschool_kid,"other_than(persons.household_id, persons.ptype == PTYPE_PRESCHOOL)" +#presence of driving_kid other than self in household,has_driving_kid,"other_than(persons.household_id, persons.ptype == PTYPE_DRIVING)" +#presence of school_kid other than self in household,has_school_kid,"other_than(persons.household_id, persons.ptype == PTYPE_SCHOOL)" +#presence of full_time worker other than self in household (independent of person type),has_full_time,"other_than(persons.household_id, persons.pemploy==PEMPLOY_FULL)" +#presence of part_time worker other than self in household (independent of person type),has_part_time,"other_than(persons.household_id, persons.pemploy==PEMPLOY_PART)" +#presence of university student other than self in household,has_university,"other_than(persons.household_id, persons.ptype == PTYPE_UNIVERSITY)" +#student_is_employed,student_is_employed,"(persons.ptype.isin([PTYPE_UNIVERSITY, PTYPE_DRIVING]) & persons.pemploy.isin([PEMPLOY_FULL, PEMPLOY_PART]))" +#nonstudent_to_school,nonstudent_to_school,"(persons.ptype.isin([PTYPE_FULL, PTYPE_PART, PTYPE_NONWORK, PTYPE_RETIRED]) & persons.pstudent.isin([PSTUDENT_GRADE_OR_HIGH, PSTUDENT_UNIVERSITY]))" +#,, +#,, FIXME - if person is a university student but has school age student category value then reset student category value +#,pstudent,"persons.pstudent.where(persons.ptype!=PTYPE_UNIVERSITY, PSTUDENT_UNIVERSITY)" +#,, FIXME if person is a student of any kind but has full-time employment status then reset student category value to non-student +#,pstudent,"pstudent.where(persons.ptype!=PTYPE_FULL, PSTUDENT_NOT)" +#,, FIXME if student category is non-student and employment is student then reset student category value to student +#,pstudent,"pstudent.where((persons.ptype!=PTYPE_DRIVING) & (persons.ptype!=PTYPE_SCHOOL), PSTUDENT_GRADE_OR_HIGH)" +#,, +#is_student,is_student,"pstudent.isin([PSTUDENT_GRADE_OR_HIGH, PSTUDENT_UNIVERSITY])" +#preschool age can go to preschool,is_student,"is_student.where(persons.age > GRADE_SCHOOL_MIN_AGE, True)" +#preschool age can go to preschool,pstudent,"pstudent.where(persons.age > GRADE_SCHOOL_MIN_AGE, PSTUDENT_GRADE_OR_HIGH)" +#is_gradeschool,is_gradeschool,(pstudent == PSTUDENT_GRADE_OR_HIGH) & (persons.age <= GRADE_SCHOOL_MAX_AGE) +#is_highschool,is_highschool,(pstudent == PSTUDENT_GRADE_OR_HIGH) & (persons.age > GRADE_SCHOOL_MAX_AGE) +#is_university,is_university,pstudent == PSTUDENT_UNIVERSITY +#school_segment gradeschool,school_segment,"np.where(is_gradeschool, SCHOOL_SEGMENT_GRADE, SCHOOL_SEGMENT_NONE)" +#school_segment highschool,school_segment,"np.where(is_highschool, SCHOOL_SEGMENT_HIGH, school_segment)" +#school_segment university,school_segment,"np.where(is_university, SCHOOL_SEGMENT_UNIV, school_segment).astype(np.int8)" +#,, +#is_worker,is_worker,"persons.pemploy.isin([PEMPLOY_FULL, PEMPLOY_PART])" +#,, +home_zone_id,home_zone_id,"reindex(households.home_zone_id, persons.household_id)" diff --git a/test/auto_ownership/configs/annotate_persons_after_hh.csv b/test/auto_ownership/configs/annotate_persons_after_hh.csv new file mode 100644 index 000000000..0dfa16be6 --- /dev/null +++ b/test/auto_ownership/configs/annotate_persons_after_hh.csv @@ -0,0 +1,5 @@ +Description,Target,Expression +#,, annotate persons table after annotate_households +#,, adults get full hh_value_of_time and children get 60% +,_hh_vot,"reindex(households.hh_value_of_time, persons.household_id)" +,value_of_time,"_hh_vot.where(persons.age>=18, _hh_vot * 0.667)" \ No newline at end of file diff --git a/test/auto_ownership/configs/auto_ownership.csv b/test/auto_ownership/configs/auto_ownership.csv new file mode 100644 index 000000000..4b8abdfa1 --- /dev/null +++ b/test/auto_ownership/configs/auto_ownership.csv @@ -0,0 +1,61 @@ +Label,Description,Expression,0_CARS,1_CAR_1CV,1_CAR_1AV,2_CARS_2CV,2_CARS_2AV,2_CARS_1CV1AV,3_CARS_3CV,3_CARS_3AV,3_CARS_2CV1AV,3_CARS_1CV2AV,4_CARS_4CV +,Boolean indicating that household is in SF county,"@np.where(df.county_id == ID_SAN_FRANCISCO, 1, 0)",coef_boolean_indicating_that_household_is_in_sf_county_0_CARS,,,,,,,,,, +,alternative specific constant for 1 driver household,@df.num_drivers==1,coef_alternative_specific_constant_for_1_driver_household_0_CARS,,,coef_alternative_specific_constant_for_1_driver_household_2_CARS_2CV,coef_alternative_specific_constant_for_1_driver_household_2_CARS_2AV,coef_alternative_specific_constant_for_1_driver_household_2_CARS_1CV1AV,coef_alternative_specific_constant_for_1_driver_household_3_CARS_3CV,coef_alternative_specific_constant_for_1_driver_household_3_CARS_3AV,coef_alternative_specific_constant_for_1_driver_household_3_CARS_2CV1AV,coef_alternative_specific_constant_for_1_driver_household_3_CARS_1CV2AV,coef_alternative_specific_constant_for_1_driver_household_4_CARS_4CV +,alternative specific constant for 2 driver household,@df.num_drivers==2,coef_alternative_specific_constant_for_2_driver_household_0_CARS,coef_alternative_specific_constant_for_2_driver_household_1_CAR_1CV,coef_alternative_specific_constant_for_2_driver_household_1_CAR_1AV,,,,coef_alternative_specific_constant_for_2_driver_household_3_CARS_3CV,coef_alternative_specific_constant_for_2_driver_household_3_CARS_3AV,coef_alternative_specific_constant_for_2_driver_household_3_CARS_2CV1AV,coef_alternative_specific_constant_for_2_driver_household_3_CARS_1CV2AV,coef_alternative_specific_constant_for_2_driver_household_4_CARS_4CV +,alternative specific constant for 3 driver household,@df.num_drivers==3,coef_alternative_specific_constant_for_3_driver_household_0_CARS,coef_alternative_specific_constant_for_3_driver_household_1_CAR_1CV,coef_alternative_specific_constant_for_3_driver_household_1_CAR_1AV,coef_alternative_specific_constant_for_3_driver_household_2_CARS_2CV,coef_alternative_specific_constant_for_3_driver_household_2_CARS_2AV,coef_alternative_specific_constant_for_3_driver_household_2_CARS_1CV1AV,,,,,coef_alternative_specific_constant_for_3_driver_household_4_CARS_4CV +,alternative specific constant for 4+ driver household,@df.num_drivers>=4,coef_alternative_specific_constant_for_4_driver_household_0_CARS,coef_alternative_specific_constant_for_4_driver_household_1_CAR_1CV,coef_alternative_specific_constant_for_4_driver_household_1_CAR_1AV,coef_alternative_specific_constant_for_4_driver_household_2_CARS_2CV,coef_alternative_specific_constant_for_4_driver_household_2_CARS_2AV,coef_alternative_specific_constant_for_4_driver_household_2_CARS_1CV1AV,coef_alternative_specific_constant_for_4_driver_household_3_CARS_3CV,coef_alternative_specific_constant_for_4_driver_household_3_CARS_3AV,coef_alternative_specific_constant_for_4_driver_household_3_CARS_2CV1AV,coef_alternative_specific_constant_for_4_driver_household_3_CARS_1CV2AV, +,workers to drivers ratio for 1 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==1) * (df.num_workers/df.num_drivers), 0)",coef_workers_to_drivers_ratio_for_1_driver_household_0_CARS,,,coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,coef_workers_to_drivers_ratio_for_1_driver_household_4_CARS_4CV +,workers to drivers ratio for 2 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==2) * (df.num_workers/df.num_drivers), 0)",coef_workers_to_drivers_ratio_for_2_driver_household_0_CARS,coef_workers_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,coef_workers_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,,,,coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,coef_workers_to_drivers_ratio_for_2_driver_household_4_CARS_4CV +,workers to drivers ratio for 3 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==3) * (df.num_workers/df.num_drivers), 0)",coef_workers_to_drivers_ratio_for_3_driver_household_0_CARS,coef_workers_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,coef_workers_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,,,,,coef_workers_to_drivers_ratio_for_3_driver_household_4_CARS_4CV +,workers to drivers ratio for 4+ driver household,"@np.where(df.num_drivers > 0, (df.num_drivers>=4) * (df.num_workers/df.num_drivers), 0)",coef_workers_to_drivers_ratio_for_4_driver_household_0_CARS,coef_workers_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,coef_workers_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV, +,young adults to drivers ratio for 1 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==1) * (df.num_young_adults/df.num_drivers), 0)",coef_young_adults_to_drivers_ratio_for_1_driver_household_0_CARS,,,,,,,,,, +,young adults to drivers ratio for 2 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==2) * (df.num_young_adults/df.num_drivers), 0)",coef_young_adults_to_drivers_ratio_for_2_driver_household_0_CARS,coef_young_adults_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,coef_young_adults_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,,,,,,,, +,young adults to drivers ratio for 3 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==3) * (df.num_young_adults/df.num_drivers), 0)",coef_young_adults_to_drivers_ratio_for_3_driver_household_0_CARS,coef_young_adults_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,coef_young_adults_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,,,,, +,young adults to drivers ratio for 4+ driver household,"@np.where(df.num_drivers > 0, (df.num_drivers>=4) * (df.num_young_adults/df.num_drivers), 0)",coef_young_adults_to_drivers_ratio_for_4_driver_household_0_CARS,coef_young_adults_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,coef_young_adults_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV, +,school children to drivers ratio for 1 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==1) * (df.num_children_6_to_15/df.num_drivers), 0)",coef_school_children_to_drivers_ratio_for_1_driver_household_0_CARS,,,coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,coef_school_children_to_drivers_ratio_for_1_driver_household_4_CARS_4CV +,school children to drivers ratio for 2 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==2) * (df.num_children_6_to_15/df.num_drivers), 0)",coef_school_children_to_drivers_ratio_for_2_driver_household_0_CARS,coef_school_children_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,coef_school_children_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,,,,coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,coef_school_children_to_drivers_ratio_for_2_driver_household_4_CARS_4CV +,school children to drivers ratio for 3 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==3) * (df.num_children_6_to_15/df.num_drivers), 0)",coef_school_children_to_drivers_ratio_for_3_driver_household_0_CARS,coef_school_children_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,coef_school_children_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,,,,,coef_school_children_to_drivers_ratio_for_3_driver_household_4_CARS_4CV +,school children to drivers ratio for 4+ driver household,"@np.where(df.num_drivers > 0, (df.num_drivers>=4) * (df.num_children_6_to_15/df.num_drivers), 0)",coef_school_children_to_drivers_ratio_for_4_driver_household_0_CARS,coef_school_children_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,coef_school_children_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV, +,young retirees to drivers ratio for 1 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==1) * (df.num_young_retirees/df.num_drivers), 0)",coef_young_retirees_to_drivers_ratio_for_1_driver_household_0_CARS,,,coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,coef_young_retirees_to_drivers_ratio_for_1_driver_household_4_CARS_4CV +,young retirees to drivers ratio for 2 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==2) * (df.num_young_retirees/df.num_drivers), 0)",coef_young_retirees_to_drivers_ratio_for_2_driver_household_0_CARS,coef_young_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,coef_young_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,,,,coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,coef_young_retirees_to_drivers_ratio_for_2_driver_household_4_CARS_4CV +,young retirees to drivers ratio for 3 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==3) * (df.num_young_retirees/df.num_drivers), 0)",coef_young_retirees_to_drivers_ratio_for_3_driver_household_0_CARS,coef_young_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,coef_young_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,,,,,coef_young_retirees_to_drivers_ratio_for_3_driver_household_4_CARS_4CV +,young retirees to drivers ratio for 4+ driver household,"@np.where(df.num_drivers > 0, (df.num_drivers>=4) * (df.num_young_retirees/df.num_drivers), 0)",coef_young_retirees_to_drivers_ratio_for_4_driver_household_0_CARS,coef_young_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV, +,old retirees to drivers ratio for 1 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==1) * (df.num_old_retirees/df.num_drivers), 0)",coef_old_retirees_to_drivers_ratio_for_1_driver_household_0_CARS,,,coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,coef_old_retirees_to_drivers_ratio_for_1_driver_household_4_CARS_4CV +,old retirees to drivers ratio for 2 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==2) * (df.num_old_retirees/df.num_drivers), 0)",coef_old_retirees_to_drivers_ratio_for_2_driver_household_0_CARS,coef_old_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,coef_old_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,,,,coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,coef_old_retirees_to_drivers_ratio_for_2_driver_household_4_CARS_4CV +,old retirees to drivers ratio for 3 driver household,"@np.where(df.num_drivers > 0, (df.num_drivers==3) * (df.num_old_retirees/df.num_drivers), 0)",coef_old_retirees_to_drivers_ratio_for_3_driver_household_0_CARS,coef_old_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,coef_old_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,,,,,coef_old_retirees_to_drivers_ratio_for_3_driver_household_4_CARS_4CV +,old retirees to drivers ratio for 4+ driver household,"@np.where(df.num_drivers > 0, (df.num_drivers>=4) * (df.num_old_retirees/df.num_drivers), 0)",coef_old_retirees_to_drivers_ratio_for_4_driver_household_0_CARS,coef_old_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV, +,household income <30k,@(df.income<30000),coef_household_income_30k_0_CARS,coef_household_income_30k_1_CAR_1CV,coef_household_income_30k_1_CAR_1AV,,,,coef_household_income_30k_3_CARS_3CV,coef_household_income_30k_3_CARS_3AV,coef_household_income_30k_3_CARS_2CV1AV,coef_household_income_30k_3_CARS_1CV2AV,coef_household_income_30k_4_CARS_4CV +,household income 30-60k,@((df.income>=30000) & (df.income<60000)),coef_household_income_3060k_0_CARS,coef_household_income_3060k_1_CAR_1CV,coef_household_income_3060k_1_CAR_1AV,,,,coef_household_income_3060k_3_CARS_3CV,coef_household_income_3060k_3_CARS_3AV,coef_household_income_3060k_3_CARS_2CV1AV,coef_household_income_3060k_3_CARS_1CV2AV,coef_household_income_3060k_4_CARS_4CV +,household income 100k+,@(df.income>=100000),coef_household_income_100k_0_CARS,coef_household_income_100k_1_CAR_1CV,coef_household_income_100k_1_CAR_1AV,,,,coef_household_income_100k_3_CARS_3CV,coef_household_income_100k_3_CARS_3AV,coef_household_income_100k_3_CARS_2CV1AV,coef_household_income_100k_3_CARS_1CV2AV,coef_household_income_100k_4_CARS_4CV +,low educational level for 1 driver household,@((df.num_drivers==1) & (df.num_highschool_graduates==0)),coef_low_educational_level_for_1_driver_household_0_CARS,,,,,,coef_low_educational_level_for_1_driver_household_3_CARS_3CV,coef_low_educational_level_for_1_driver_household_3_CARS_3AV,coef_low_educational_level_for_1_driver_household_3_CARS_2CV1AV,coef_low_educational_level_for_1_driver_household_3_CARS_1CV2AV,coef_low_educational_level_for_1_driver_household_4_CARS_4CV +,low educational level for 2 driver household,@((df.num_drivers==2) & (df.num_highschool_graduates==0)),coef_low_educational_level_for_2_driver_household_0_CARS,coef_low_educational_level_for_2_driver_household_1_CAR_1CV,coef_low_educational_level_for_2_driver_household_1_CAR_1AV,,,,coef_low_educational_level_for_2_driver_household_3_CARS_3CV,coef_low_educational_level_for_2_driver_household_3_CARS_3AV,coef_low_educational_level_for_2_driver_household_3_CARS_2CV1AV,coef_low_educational_level_for_2_driver_household_3_CARS_1CV2AV,coef_low_educational_level_for_2_driver_household_4_CARS_4CV +,low educational level for 3 driver household,@((df.num_drivers==3) & (df.num_highschool_graduates==0)),coef_low_educational_level_for_3_driver_household_0_CARS,coef_low_educational_level_for_3_driver_household_1_CAR_1CV,coef_low_educational_level_for_3_driver_household_1_CAR_1AV,,,,,,,,coef_low_educational_level_for_3_driver_household_4_CARS_4CV +,low educational level for 4+ driver household,@((df.num_drivers>=4) & (df.num_highschool_graduates==0)),coef_low_educational_level_for_4_driver_household_0_CARS,coef_low_educational_level_for_4_driver_household_1_CAR_1CV,coef_low_educational_level_for_4_driver_household_1_CAR_1AV,,,,coef_low_educational_level_for_4_driver_household_3_CARS_3CV,coef_low_educational_level_for_4_driver_household_3_CARS_3AV,coef_low_educational_level_for_4_driver_household_3_CARS_2CV1AV,coef_low_educational_level_for_4_driver_household_3_CARS_1CV2AV, +,detached single family house,@df.building_size == 2,coef_detached_single_family_house_0_CARS,coef_detached_single_family_house_1_CAR_1CV,coef_detached_single_family_house_1_CAR_1AV,,,,coef_detached_single_family_house_3_CARS_3CV,coef_detached_single_family_house_3_CARS_3AV,coef_detached_single_family_house_3_CARS_2CV1AV,coef_detached_single_family_house_3_CARS_1CV2AV,coef_detached_single_family_house_4_CARS_4CV +,Intersection density,TotInt/502,,,,,,,coef_intersection_density_3_CARS_3CV,coef_intersection_density_3_CARS_3AV,coef_intersection_density_3_CARS_2CV1AV,coef_intersection_density_3_CARS_1CV2AV,coef_intersection_density_4_CARS_4CV +,Population density,PopDen,coef_population_density_0_CARS,coef_population_density_1_CAR_1CV,coef_population_density_1_CAR_1AV,,,,,,,, +,Retail density,RetEmpDen,coef_retail_density_0_CARS,coef_retail_density_1_CAR_1CV,coef_retail_density_1_CAR_1AV,,,,,,,, +,Non-motorized zonal accessbility,@df.nonmandatory_nm_accessibility,coef_nonmotorized_zonal_accessbility_0_CARS,coef_nonmotorized_zonal_accessbility_1_CAR_1CV,coef_nonmotorized_zonal_accessbility_1_CAR_1AV,,,,coef_nonmotorized_zonal_accessbility_3_CARS_3CV,coef_nonmotorized_zonal_accessbility_3_CARS_3AV,coef_nonmotorized_zonal_accessbility_3_CARS_2CV1AV,coef_nonmotorized_zonal_accessbility_3_CARS_1CV2AV,coef_nonmotorized_zonal_accessbility_4_CARS_4CV +,auto-transit zonal accessibility,@(df.nonmandatory_auto_accessibility - df.nonmandatory_transit_accessibility),coef_autotransit_zonal_accessibility_0_CARS,coef_autotransit_zonal_accessibility_1_CAR_1CV,coef_autotransit_zonal_accessibility_1_CAR_1AV,,,,,,,, +#,worker mandatory tour auto dependency,@((setting('use_accessibility') == 1) & (##workersAutoDependency##)),coef_worker_mandatory_tour_auto_dependency_0_CARS,coef_worker_mandatory_tour_auto_dependency_1_CAR_1CV,coef_worker_mandatory_tour_auto_dependency_1_CAR_1AV,,,,coef_worker_mandatory_tour_auto_dependency_3_CARS_3CV,coef_worker_mandatory_tour_auto_dependency_3_CARS_3AV,coef_worker_mandatory_tour_auto_dependency_3_CARS_2CV1AV,coef_worker_mandatory_tour_auto_dependency_3_CARS_1CV2AV,coef_worker_mandatory_tour_auto_dependency_4_CARS_4CV +#,student mandatory tour auto dependency,@((setting('use_accessibility') == 1) & (##studentsAutoDependency##)),coef_student_mandatory_tour_auto_dependency_0_CARS,coef_student_mandatory_tour_auto_dependency_1_CAR_1CV,coef_student_mandatory_tour_auto_dependency_1_CAR_1AV,,,,,,,, +#,worker mandatory tour rail mode portion,@((setting('use_accessibility') == 1) & (##workersRailProportion##)),coef_worker_mandatory_tour_rail_mode_portion_0_CARS,coef_worker_mandatory_tour_rail_mode_portion_1_CAR_1CV,coef_worker_mandatory_tour_rail_mode_portion_1_CAR_1AV,,,,coef_worker_mandatory_tour_rail_mode_portion_3_CARS_3CV,coef_worker_mandatory_tour_rail_mode_portion_3_CARS_3AV,coef_worker_mandatory_tour_rail_mode_portion_3_CARS_2CV1AV,coef_worker_mandatory_tour_rail_mode_portion_3_CARS_1CV2AV,coef_worker_mandatory_tour_rail_mode_portion_4_CARS_4CV +#,student mandatory tour rail mode portion,@((setting('use_accessibility') == 1) & (##studentsRailProportion##)),coef_student_mandatory_tour_rail_mode_portion_0_CARS,coef_student_mandatory_tour_rail_mode_portion_1_CAR_1CV,coef_student_mandatory_tour_rail_mode_portion_1_CAR_1AV,,,,,,,, +,ASC adjustment for non-GQ PRE-AO,@df.hh_unit_type==1,,coef_asc_adjustment_for_nongq_preao_1_CAR_1CV,coef_asc_adjustment_for_nongq_preao_1_CAR_1AV,coef_asc_adjustment_for_nongq_preao_2_CARS_2CV,coef_asc_adjustment_for_nongq_preao_2_CARS_2AV,coef_asc_adjustment_for_nongq_preao_2_CARS_1CV1AV,coef_asc_adjustment_for_nongq_preao_3_CARS_3CV,coef_asc_adjustment_for_nongq_preao_3_CARS_3AV,coef_asc_adjustment_for_nongq_preao_3_CARS_2CV1AV,coef_asc_adjustment_for_nongq_preao_3_CARS_1CV2AV,coef_asc_adjustment_for_nongq_preao_4_CARS_4CV +,ASC adjustment for non-GQ POST-AO,@((df.hh_unit_type==1) & (setting('use_accessibility') == 1)),,coef_asc_adjustment_for_nongq_postao_1_CAR_1CV,coef_asc_adjustment_for_nongq_postao_1_CAR_1AV,coef_asc_adjustment_for_nongq_postao_2_CARS_2CV,coef_asc_adjustment_for_nongq_postao_2_CARS_2AV,coef_asc_adjustment_for_nongq_postao_2_CARS_1CV1AV,coef_asc_adjustment_for_nongq_postao_3_CARS_3CV,coef_asc_adjustment_for_nongq_postao_3_CARS_3AV,coef_asc_adjustment_for_nongq_postao_3_CARS_2CV1AV,coef_asc_adjustment_for_nongq_postao_3_CARS_1CV2AV,coef_asc_adjustment_for_nongq_postao_4_CARS_4CV +,adjustment for 2 workers in non-family 0-car household,@((df.hh_type>3) & (df.num_workers==2)),coef_adjustment_for_2_workers_in_nonfamily_0car_household_0_CARS,,,,,,,,,, +,adjustment for 3 workers in non-family 0-car household,@((df.hh_type>3) & (df.num_workers==3)),coef_adjustment_for_3_workers_in_nonfamily_0car_household_0_CARS,,,,,,,,,, +,adjustment for 4+ workers in non-family 0-car household,@((df.hh_type>3) & (df.num_workers>3)),coef_adjustment_for_4_workers_in_nonfamily_0car_household_0_CARS,,,,,,,,,, +,adjustment for 4+ workers in family 0-car household,@((df.hh_type<=3) & (df.num_workers>3)),coef_adjustment_for_4_workers_in_family_0car_household_0_CARS,,,,,,,,,, +,TM2 Round 2 ASC adjustment for 1 workers in 0-car household,@df.num_workers==1,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_0_CARS,,,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_2CV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_2AV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_1CV1AV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_3CV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_3AV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_2CV1AV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_1CV2AV,coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_4_CARS_4CV +,TM2 Round 2 ASC adjustment for 2 workers in 0-car household,@df.num_workers==2,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_0_CARS,,,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_2CV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_2AV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_1CV1AV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_3CV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_3AV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_2CV1AV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_1CV2AV,coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_4_CARS_4CV +,TM2 Round 2 ASC adjustment for 3+ workers in 0-car household,@df.num_workers>=3,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_0_CARS,,,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_2CV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_2AV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_1CV1AV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_3CV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_3AV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_2CV1AV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_1CV2AV,coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_4_CARS_4CV +,TM2 Round 2 ASC adjustment for non-GQ PRE-AO,@df.hh_unit_type==1,coef_tm2_round_2_asc_adjustment_for_nongq_preao_0_CARS,,,coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_2CV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_2AV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_1CV1AV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_3CV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_3AV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_2CV1AV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_1CV2AV,coef_tm2_round_2_asc_adjustment_for_nongq_preao_4_CARS_4CV +,TM2 Round 2 ASC adjustment for non-GQ POST-AO,@((df.hh_unit_type==1) & (setting('use_accessibility') == 1)),coef_tm2_round_2_asc_adjustment_for_nongq_postao_0_CARS,,,coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_2CV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_2AV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_1CV1AV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_3CV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_3AV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_2CV1AV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_1CV2AV,coef_tm2_round_2_asc_adjustment_for_nongq_postao_4_CARS_4CV +,AV ASC - Household Income under $50k,@df.income<50000,,,coef_av_asc__household_income_under_50k_1_CAR_1AV,,coef_av_asc__household_income_under_50k_2_CARS_2AV,coef_av_asc__household_income_under_50k_2_CARS_1CV1AV,,coef_av_asc__household_income_under_50k_3_CARS_3AV,coef_av_asc__household_income_under_50k_3_CARS_2CV1AV,coef_av_asc__household_income_under_50k_3_CARS_1CV2AV, +,AV ASC - Household Income 100k+,@df.income>=100000,,,coef_av_asc__household_income_100k_1_CAR_1AV,,coef_av_asc__household_income_100k_2_CARS_2AV,coef_av_asc__household_income_100k_2_CARS_1CV1AV,,coef_av_asc__household_income_100k_3_CARS_3AV,coef_av_asc__household_income_100k_3_CARS_2CV1AV,coef_av_asc__household_income_100k_3_CARS_1CV2AV, +,AV ASC - Young household,@(df.num_persons_18_to_35>=df.num_persons_65_plus),,,coef_av_asc__young_household_1_CAR_1AV,,coef_av_asc__young_household_2_CARS_2AV,coef_av_asc__young_household_2_CARS_1CV1AV,,coef_av_asc__young_household_3_CARS_3AV,coef_av_asc__young_household_3_CARS_2CV1AV,coef_av_asc__young_household_3_CARS_1CV2AV, +,AV ASC - Old household,@(df.num_persons_18_to_35 < df.num_persons_65_plus),,,coef_av_asc__old_household_1_CAR_1AV,,coef_av_asc__old_household_2_CARS_2AV,coef_av_asc__old_household_2_CARS_1CV1AV,,coef_av_asc__old_household_3_CARS_3AV,coef_av_asc__old_household_3_CARS_2CV1AV,coef_av_asc__old_household_3_CARS_1CV2AV, +#,"AV Coeff Per Hour of travel by auto for work, summed across all workers in household",@((setting('use_accessibility') == 1) & (##@workAutoTime##)),,,"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_1_CAR_1AV",,"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_2_CARS_2AV","coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_2_CARS_1CV1AV",,"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_3AV","coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_2CV1AV","coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_1CV2AV", +,AV ASC - 100% AV Share,@setting('mobility_av_share')==1.0,,coef_unavailable,,coef_unavailable,,coef_unavailable,coef_unavailable,,coef_unavailable,coef_unavailable,coef_unavailable +,AV ASC - 0% AV Share,@setting('mobility_av_share')==0,,,coef_unavailable,,coef_unavailable,coef_unavailable,,coef_unavailable,coef_unavailable,coef_unavailable, diff --git a/test/auto_ownership/configs/auto_ownership.yaml b/test/auto_ownership/configs/auto_ownership.yaml new file mode 100644 index 000000000..2cdde0464 --- /dev/null +++ b/test/auto_ownership/configs/auto_ownership.yaml @@ -0,0 +1,53 @@ + +SPEC: auto_ownership.csv +COEFFICIENTS: auto_ownership_coefficients.csv + +LOGIT_TYPE: NL + +NESTS: + name: root + coefficient: 1 + alternatives: + - name: own no car + coefficient: 0.668 + alternatives: + - name: zero car + coefficient: 0.3 + alternatives: + - 0_CARS + - name: own cars + coefficient: 0.668 + alternatives: + - name: one car + coefficient: 0.3 + alternatives: + - 1_CAR_1CV + - 1_CAR_1AV + - name: two cars + coefficient: 0.3 + alternatives: + - 2_CARS_2CV + - 2_CARS_2AV + - 2_CARS_1CV1AV + - name: three cars + coefficient: 0.3 + alternatives: + - 3_CARS_3CV + - 3_CARS_3AV + - 3_CARS_2CV1AV + - 3_CARS_1CV2AV + - name: four cars + coefficient: 0.3 + alternatives: + - 4_CARS_4CV + +CONSTANTS: + ID_SAN_FRANCISCO: 1 + ID_SAN_MATEO: 2 + ID_SANTA_CLARA: 3 + ID_ALAMEDA: 4 + ID_CONTRA_COSTA: 5 + ID_SOLANO: 6 + ID_NAPA: 7 + ID_SONOMA: 8 + ID_MARIN: 9 diff --git a/test/auto_ownership/configs/auto_ownership_coefficients.csv b/test/auto_ownership/configs/auto_ownership_coefficients.csv new file mode 100644 index 000000000..1d88703f1 --- /dev/null +++ b/test/auto_ownership/configs/auto_ownership_coefficients.csv @@ -0,0 +1,393 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_boolean_indicating_that_household_is_in_sf_county_0_CARS,1.233276051,F +coef_alternative_specific_constant_for_1_driver_household_0_CARS,-1.920143842,F +coef_alternative_specific_constant_for_2_driver_household_0_CARS,-3.470781624,F +coef_alternative_specific_constant_for_3_driver_household_0_CARS,-3.329633459,F +coef_alternative_specific_constant_for_4_driver_household_0_CARS,-6.111494495,F +coef_workers_to_drivers_ratio_for_1_driver_household_0_CARS,-1.464256557,F +coef_workers_to_drivers_ratio_for_2_driver_household_0_CARS,-1.464256557,F +coef_workers_to_drivers_ratio_for_3_driver_household_0_CARS,-1.464256557,F +coef_workers_to_drivers_ratio_for_4_driver_household_0_CARS,-1.464256557,F +coef_young_adults_to_drivers_ratio_for_1_driver_household_0_CARS,-1.769767608,F +coef_young_adults_to_drivers_ratio_for_2_driver_household_0_CARS,-1.769767608,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_0_CARS,-1.769767608,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_0_CARS,-1.769767608,F +coef_school_children_to_drivers_ratio_for_1_driver_household_0_CARS,-0.346415088,F +coef_school_children_to_drivers_ratio_for_2_driver_household_0_CARS,-0.346415088,F +coef_school_children_to_drivers_ratio_for_3_driver_household_0_CARS,-0.346415088,F +coef_school_children_to_drivers_ratio_for_4_driver_household_0_CARS,-0.346415088,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_0_CARS,-0.38172487,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_0_CARS,-0.38172487,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_0_CARS,-0.38172487,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_0_CARS,-0.38172487,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_0_CARS,0.608700053,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_0_CARS,0.608700053,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_0_CARS,0.608700053,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_0_CARS,0.608700053,F +coef_household_income_30k_0_CARS,2.654926169,F +coef_household_income_3060k_0_CARS,0.918219369,F +coef_household_income_100k_0_CARS,-0.44306913,F +coef_low_educational_level_for_1_driver_household_0_CARS,0.767760942,F +coef_low_educational_level_for_2_driver_household_0_CARS,0.767760942,F +coef_low_educational_level_for_3_driver_household_0_CARS,0.767760942,F +coef_low_educational_level_for_4_driver_household_0_CARS,0.767760942,F +coef_detached_single_family_house_0_CARS,-1.774689947,F +coef_population_density_0_CARS,0.046206562,F +coef_retail_density_0_CARS,0.074563803,F +coef_nonmotorized_zonal_accessbility_0_CARS,0.060875253,F +coef_autotransit_zonal_accessibility_0_CARS,-0.200776981,F +coef_worker_mandatory_tour_auto_dependency_0_CARS,-0.16516642,F +coef_student_mandatory_tour_auto_dependency_0_CARS,-0.04422711,F +coef_worker_mandatory_tour_rail_mode_portion_0_CARS,0.171079447,F +coef_student_mandatory_tour_rail_mode_portion_0_CARS,0.26285636,F +coef_adjustment_for_2_workers_in_nonfamily_0car_household_0_CARS,0.725034403,F +coef_adjustment_for_3_workers_in_nonfamily_0car_household_0_CARS,1.194820674,F +coef_adjustment_for_4_workers_in_nonfamily_0car_household_0_CARS,2.844226409,F +coef_adjustment_for_4_workers_in_family_0car_household_0_CARS,2.116557339,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_0_CARS,1.097234124,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_0_CARS,0.893156568,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_0_CARS,0.937133013,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_0_CARS,-1.511025686,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_0_CARS,-0.115788174,F +coef_alternative_specific_constant_for_2_driver_household_1_CAR_1CV,-2.20339718,F +coef_alternative_specific_constant_for_3_driver_household_1_CAR_1CV,-2.473061365,F +coef_alternative_specific_constant_for_4_driver_household_1_CAR_1CV,-3.983965837,F +coef_workers_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,-0.407798013,F +coef_workers_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,-0.407798013,F +coef_workers_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1CV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1CV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1CV,0.232672708,F +coef_household_income_30k_1_CAR_1CV,0.632172646,F +coef_household_income_3060k_1_CAR_1CV,0.342605571,F +coef_household_income_100k_1_CAR_1CV,-0.44306913,F +coef_low_educational_level_for_2_driver_household_1_CAR_1CV,0.432294097,F +coef_low_educational_level_for_3_driver_household_1_CAR_1CV,0.432294097,F +coef_low_educational_level_for_4_driver_household_1_CAR_1CV,0.432294097,F +coef_detached_single_family_house_1_CAR_1CV,-0.528137281,F +coef_population_density_1_CAR_1CV,0.02268226,F +coef_retail_density_1_CAR_1CV,0.029544267,F +coef_nonmotorized_zonal_accessbility_1_CAR_1CV,0.039970159,F +coef_autotransit_zonal_accessibility_1_CAR_1CV,-0.009060243,F +coef_worker_mandatory_tour_auto_dependency_1_CAR_1CV,-0.16516642,F +coef_student_mandatory_tour_auto_dependency_1_CAR_1CV,-0.04422711,F +coef_worker_mandatory_tour_rail_mode_portion_1_CAR_1CV,0.171079447,F +coef_student_mandatory_tour_rail_mode_portion_1_CAR_1CV,0.26285636,F +coef_asc_adjustment_for_nongq_preao_1_CAR_1CV,0.04582774,F +coef_asc_adjustment_for_nongq_postao_1_CAR_1CV,-0.013942306,F +coef_alternative_specific_constant_for_2_driver_household_1_CAR_1AV,-2.20339718,F +coef_alternative_specific_constant_for_3_driver_household_1_CAR_1AV,-2.473061365,F +coef_alternative_specific_constant_for_4_driver_household_1_CAR_1AV,-3.983965837,F +coef_workers_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,-0.407798013,F +coef_workers_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,-0.407798013,F +coef_workers_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_1_CAR_1AV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_1_CAR_1AV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_1_CAR_1AV,0.232672708,F +coef_household_income_30k_1_CAR_1AV,0.632172646,F +coef_household_income_3060k_1_CAR_1AV,0.342605571,F +coef_household_income_100k_1_CAR_1AV,-0.44306913,F +coef_low_educational_level_for_2_driver_household_1_CAR_1AV,0.432294097,F +coef_low_educational_level_for_3_driver_household_1_CAR_1AV,0.432294097,F +coef_low_educational_level_for_4_driver_household_1_CAR_1AV,0.432294097,F +coef_detached_single_family_house_1_CAR_1AV,-0.528137281,F +coef_population_density_1_CAR_1AV,0.02268226,F +coef_retail_density_1_CAR_1AV,0.029544267,F +coef_nonmotorized_zonal_accessbility_1_CAR_1AV,0.039970159,F +coef_autotransit_zonal_accessibility_1_CAR_1AV,-0.009060243,F +coef_worker_mandatory_tour_auto_dependency_1_CAR_1AV,-0.16516642,F +coef_student_mandatory_tour_auto_dependency_1_CAR_1AV,-0.04422711,F +coef_worker_mandatory_tour_rail_mode_portion_1_CAR_1AV,0.171079447,F +coef_student_mandatory_tour_rail_mode_portion_1_CAR_1AV,0.26285636,F +coef_asc_adjustment_for_nongq_preao_1_CAR_1AV,0.04582774,F +coef_asc_adjustment_for_nongq_postao_1_CAR_1AV,-0.013942306,F +coef_av_asc__household_income_under_50k_1_CAR_1AV,-1,F +coef_av_asc__household_income_100k_1_CAR_1AV,1,F +coef_av_asc__young_household_1_CAR_1AV,0.5,F +coef_av_asc__old_household_1_CAR_1AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_1_CAR_1AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_2_CARS_2CV,-0.934889684,F +coef_alternative_specific_constant_for_3_driver_household_2_CARS_2CV,-0.317496682,F +coef_alternative_specific_constant_for_4_driver_household_2_CARS_2CV,-0.909626603,F +coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,0.474996826,F +coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,-0.407798013,F +coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,0.108758563,F +coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2CV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2CV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2CV,0.232672708,F +coef_asc_adjustment_for_nongq_preao_2_CARS_2CV,-1.602468896,F +coef_asc_adjustment_for_nongq_postao_2_CARS_2CV,-0.132328921,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_2CV,-0.151698573,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_2CV,-0.17099367,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_2CV,-0.553211417,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_2CV,0.723793144,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_2CV,0.16375467,F +coef_alternative_specific_constant_for_1_driver_household_2_CARS_2AV,-0.934889684,F +coef_alternative_specific_constant_for_3_driver_household_2_CARS_2AV,-0.317496682,F +coef_alternative_specific_constant_for_4_driver_household_2_CARS_2AV,-0.909626603,F +coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,0.474996826,F +coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,-0.407798013,F +coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_2AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_2AV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_2AV,0.232672708,F +coef_asc_adjustment_for_nongq_preao_2_CARS_2AV,-1.602468896,F +coef_asc_adjustment_for_nongq_postao_2_CARS_2AV,-0.132328921,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_2AV,-0.151698573,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_2AV,-0.17099367,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_2AV,-0.553211417,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_2AV,0.723793144,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_2AV,0.16375467,F +coef_av_asc__household_income_under_50k_2_CARS_2AV,-1,F +coef_av_asc__household_income_100k_2_CARS_2AV,1,F +coef_av_asc__young_household_2_CARS_2AV,0.5,F +coef_av_asc__old_household_2_CARS_2AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_2_CARS_2AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_2_CARS_1CV1AV,-0.934889684,F +coef_alternative_specific_constant_for_3_driver_household_2_CARS_1CV1AV,-0.317496682,F +coef_alternative_specific_constant_for_4_driver_household_2_CARS_1CV1AV,-0.909626603,F +coef_workers_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,0.474996826,F +coef_workers_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,-0.407798013,F +coef_workers_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,-0.598263093,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,-0.018572553,F +coef_school_children_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,-0.19861915,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_2_CARS_1CV1AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_2_CARS_1CV1AV,0.232672708,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_2_CARS_1CV1AV,0.232672708,F +coef_asc_adjustment_for_nongq_preao_2_CARS_1CV1AV,-1.602468896,F +coef_asc_adjustment_for_nongq_postao_2_CARS_1CV1AV,-0.132328921,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_2_CARS_1CV1AV,-0.151698573,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_2_CARS_1CV1AV,-0.17099367,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_2_CARS_1CV1AV,-0.553211417,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_2_CARS_1CV1AV,0.723793144,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_2_CARS_1CV1AV,0.16375467,F +coef_av_asc__household_income_under_50k_2_CARS_1CV1AV,-1,F +coef_av_asc__household_income_100k_2_CARS_1CV1AV,1,F +coef_av_asc__young_household_2_CARS_1CV1AV,0.5,F +coef_av_asc__old_household_2_CARS_1CV1AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_2_CARS_1CV1AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_3_CARS_3CV,-1.904733531,F +coef_alternative_specific_constant_for_2_driver_household_3_CARS_3CV,-0.829354142,F +coef_alternative_specific_constant_for_4_driver_household_3_CARS_3CV,-0.524427892,F +coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,0.474996826,F +coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,0.474996826,F +coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,0.108758563,F +coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,0.108758563,F +coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3CV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3CV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3CV,0.232672708,F +coef_household_income_30k_3_CARS_3CV,-0.601152419,F +coef_household_income_3060k_3_CARS_3CV,-0.305680609,F +coef_household_income_100k_3_CARS_3CV,0.087029823,F +coef_low_educational_level_for_1_driver_household_3_CARS_3CV,-0.176660377,F +coef_low_educational_level_for_2_driver_household_3_CARS_3CV,-0.176660377,F +coef_low_educational_level_for_4_driver_household_3_CARS_3CV,0.432294097,F +coef_detached_single_family_house_3_CARS_3CV,0.427320086,F +coef_intersection_density_3_CARS_3CV,-0.326525635,F +coef_nonmotorized_zonal_accessbility_3_CARS_3CV,-0.052524462,F +coef_worker_mandatory_tour_auto_dependency_3_CARS_3CV,0.104064535,F +coef_worker_mandatory_tour_rail_mode_portion_3_CARS_3CV,-0.206713378,F +coef_asc_adjustment_for_nongq_preao_3_CARS_3CV,-2.169791463,F +coef_asc_adjustment_for_nongq_postao_3_CARS_3CV,-0.180285245,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_3CV,-0.209786195,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_3CV,-0.382492356,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_3CV,0.065128979,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_3CV,0.617090781,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_3CV,0.222715484,F +coef_alternative_specific_constant_for_1_driver_household_3_CARS_3AV,-1.904733531,F +coef_alternative_specific_constant_for_2_driver_household_3_CARS_3AV,-0.829354142,F +coef_alternative_specific_constant_for_4_driver_household_3_CARS_3AV,-0.524427892,F +coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,0.474996826,F +coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,0.474996826,F +coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_3AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_3AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_3AV,0.232672708,F +coef_household_income_30k_3_CARS_3AV,-0.601152419,F +coef_household_income_3060k_3_CARS_3AV,-0.305680609,F +coef_household_income_100k_3_CARS_3AV,0.087029823,F +coef_low_educational_level_for_1_driver_household_3_CARS_3AV,-0.176660377,F +coef_low_educational_level_for_2_driver_household_3_CARS_3AV,-0.176660377,F +coef_low_educational_level_for_4_driver_household_3_CARS_3AV,0.432294097,F +coef_detached_single_family_house_3_CARS_3AV,0.427320086,F +coef_intersection_density_3_CARS_3AV,-0.326525635,F +coef_nonmotorized_zonal_accessbility_3_CARS_3AV,-0.052524462,F +coef_worker_mandatory_tour_auto_dependency_3_CARS_3AV,0.104064535,F +coef_worker_mandatory_tour_rail_mode_portion_3_CARS_3AV,-0.206713378,F +coef_asc_adjustment_for_nongq_preao_3_CARS_3AV,-2.169791463,F +coef_asc_adjustment_for_nongq_postao_3_CARS_3AV,-0.180285245,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_3AV,-0.209786195,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_3AV,-0.382492356,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_3AV,0.065128979,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_3AV,0.617090781,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_3AV,0.222715484,F +coef_av_asc__household_income_under_50k_3_CARS_3AV,-1,F +coef_av_asc__household_income_100k_3_CARS_3AV,1,F +coef_av_asc__young_household_3_CARS_3AV,0.5,F +coef_av_asc__old_household_3_CARS_3AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_3AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_3_CARS_2CV1AV,-1.904733531,F +coef_alternative_specific_constant_for_2_driver_household_3_CARS_2CV1AV,-0.829354142,F +coef_alternative_specific_constant_for_4_driver_household_3_CARS_2CV1AV,-0.524427892,F +coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,0.474996826,F +coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,0.474996826,F +coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_2CV1AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_2CV1AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_2CV1AV,0.232672708,F +coef_household_income_30k_3_CARS_2CV1AV,-0.601152419,F +coef_household_income_3060k_3_CARS_2CV1AV,-0.305680609,F +coef_household_income_100k_3_CARS_2CV1AV,0.087029823,F +coef_low_educational_level_for_1_driver_household_3_CARS_2CV1AV,-0.176660377,F +coef_low_educational_level_for_2_driver_household_3_CARS_2CV1AV,-0.176660377,F +coef_low_educational_level_for_4_driver_household_3_CARS_2CV1AV,0.432294097,F +coef_detached_single_family_house_3_CARS_2CV1AV,0.427320086,F +coef_intersection_density_3_CARS_2CV1AV,-0.326525635,F +coef_nonmotorized_zonal_accessbility_3_CARS_2CV1AV,-0.052524462,F +coef_worker_mandatory_tour_auto_dependency_3_CARS_2CV1AV,0.104064535,F +coef_worker_mandatory_tour_rail_mode_portion_3_CARS_2CV1AV,-0.206713378,F +coef_asc_adjustment_for_nongq_preao_3_CARS_2CV1AV,-2.169791463,F +coef_asc_adjustment_for_nongq_postao_3_CARS_2CV1AV,-0.180285245,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_2CV1AV,-0.209786195,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_2CV1AV,-0.382492356,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_2CV1AV,0.065128979,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_2CV1AV,0.617090781,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_2CV1AV,0.222715484,F +coef_av_asc__household_income_under_50k_3_CARS_2CV1AV,-1,F +coef_av_asc__household_income_100k_3_CARS_2CV1AV,1,F +coef_av_asc__young_household_3_CARS_2CV1AV,0.5,F +coef_av_asc__old_household_3_CARS_2CV1AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_2CV1AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_3_CARS_1CV2AV,-1.904733531,F +coef_alternative_specific_constant_for_2_driver_household_3_CARS_1CV2AV,-0.829354142,F +coef_alternative_specific_constant_for_4_driver_household_3_CARS_1CV2AV,-0.524427892,F +coef_workers_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,0.474996826,F +coef_workers_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,0.474996826,F +coef_workers_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV,-0.407798013,F +coef_young_adults_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV,-0.598263093,F +coef_school_children_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,0.108758563,F +coef_school_children_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV,-0.018572553,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV,-0.19861915,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_3_CARS_1CV2AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_3_CARS_1CV2AV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_4_driver_household_3_CARS_1CV2AV,0.232672708,F +coef_household_income_30k_3_CARS_1CV2AV,-0.601152419,F +coef_household_income_3060k_3_CARS_1CV2AV,-0.305680609,F +coef_household_income_100k_3_CARS_1CV2AV,0.087029823,F +coef_low_educational_level_for_1_driver_household_3_CARS_1CV2AV,-0.176660377,F +coef_low_educational_level_for_2_driver_household_3_CARS_1CV2AV,-0.176660377,F +coef_low_educational_level_for_4_driver_household_3_CARS_1CV2AV,0.432294097,F +coef_detached_single_family_house_3_CARS_1CV2AV,0.427320086,F +coef_intersection_density_3_CARS_1CV2AV,-0.326525635,F +coef_nonmotorized_zonal_accessbility_3_CARS_1CV2AV,-0.052524462,F +coef_worker_mandatory_tour_auto_dependency_3_CARS_1CV2AV,0.104064535,F +coef_worker_mandatory_tour_rail_mode_portion_3_CARS_1CV2AV,-0.206713378,F +coef_asc_adjustment_for_nongq_preao_3_CARS_1CV2AV,-2.169791463,F +coef_asc_adjustment_for_nongq_postao_3_CARS_1CV2AV,-0.180285245,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_3_CARS_1CV2AV,-0.209786195,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_3_CARS_1CV2AV,-0.382492356,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_3_CARS_1CV2AV,0.065128979,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_3_CARS_1CV2AV,0.617090781,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_3_CARS_1CV2AV,0.222715484,F +coef_av_asc__household_income_under_50k_3_CARS_1CV2AV,-1,F +coef_av_asc__household_income_100k_3_CARS_1CV2AV,1,F +coef_av_asc__young_household_3_CARS_1CV2AV,0.5,F +coef_av_asc__old_household_3_CARS_1CV2AV,-1,F +"coef_av__coeff_per_hour_of_travel_by_auto_for_work,_summed_across_all_workers_in_household_3_CARS_1CV2AV",0.25,F +coef_alternative_specific_constant_for_1_driver_household_4_CARS_4CV,-2.488003709,F +coef_alternative_specific_constant_for_2_driver_household_4_CARS_4CV,-1.778311581,F +coef_alternative_specific_constant_for_3_driver_household_4_CARS_4CV,-0.533915593,F +coef_workers_to_drivers_ratio_for_1_driver_household_4_CARS_4CV,0.474996826,F +coef_workers_to_drivers_ratio_for_2_driver_household_4_CARS_4CV,0.474996826,F +coef_workers_to_drivers_ratio_for_3_driver_household_4_CARS_4CV,0.474996826,F +coef_school_children_to_drivers_ratio_for_1_driver_household_4_CARS_4CV,0.108758563,F +coef_school_children_to_drivers_ratio_for_2_driver_household_4_CARS_4CV,0.108758563,F +coef_school_children_to_drivers_ratio_for_3_driver_household_4_CARS_4CV,0.108758563,F +coef_young_retirees_to_drivers_ratio_for_1_driver_household_4_CARS_4CV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_2_driver_household_4_CARS_4CV,0.28676361,F +coef_young_retirees_to_drivers_ratio_for_3_driver_household_4_CARS_4CV,0.28676361,F +coef_old_retirees_to_drivers_ratio_for_1_driver_household_4_CARS_4CV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_2_driver_household_4_CARS_4CV,-0.901020484,F +coef_old_retirees_to_drivers_ratio_for_3_driver_household_4_CARS_4CV,-0.901020484,F +coef_household_income_30k_4_CARS_4CV,-0.936061162,F +coef_household_income_3060k_4_CARS_4CV,-0.271548734,F +coef_household_income_100k_4_CARS_4CV,0.144123363,F +coef_low_educational_level_for_1_driver_household_4_CARS_4CV,-0.176660377,F +coef_low_educational_level_for_2_driver_household_4_CARS_4CV,-0.176660377,F +coef_low_educational_level_for_3_driver_household_4_CARS_4CV,-0.176660377,F +coef_detached_single_family_house_4_CARS_4CV,0.539511974,F +coef_intersection_density_4_CARS_4CV,-0.326525635,F +coef_nonmotorized_zonal_accessbility_4_CARS_4CV,-0.100612397,F +coef_worker_mandatory_tour_auto_dependency_4_CARS_4CV,0.104064535,F +coef_worker_mandatory_tour_rail_mode_portion_4_CARS_4CV,-0.206713378,F +coef_asc_adjustment_for_nongq_preao_4_CARS_4CV,-2.641133846,F +coef_asc_adjustment_for_nongq_postao_4_CARS_4CV,-0.186095557,F +coef_tm2_round_2_asc_adjustment_for_1_workers_in_0car_household_4_CARS_4CV,-0.308288035,F +coef_tm2_round_2_asc_adjustment_for_2_workers_in_0car_household_4_CARS_4CV,-0.551034746,F +coef_tm2_round_2_asc_adjustment_for_3_workers_in_0car_household_4_CARS_4CV,-0.048670057,F +coef_tm2_round_2_asc_adjustment_for_nongq_preao_4_CARS_4CV,0.69421287,F +coef_tm2_round_2_asc_adjustment_for_nongq_postao_4_CARS_4CV,0.2639107,F diff --git a/test/auto_ownership/configs/constants.yaml b/test/auto_ownership/configs/constants.yaml new file mode 100644 index 000000000..b0bd5a1f3 --- /dev/null +++ b/test/auto_ownership/configs/constants.yaml @@ -0,0 +1,68 @@ +## ActivitySim +## See full license in LICENSE.txt. + + +#HHT_NONE: 0 +#HHT_FAMILY_MARRIED: 1 +#HHT_FAMILY_MALE: 2 +#HHT_FAMILY_FEMALE: 3 +#HHT_NONFAMILY_MALE_ALONE: 4 +#HHT_NONFAMILY_MALE_NOTALONE: 5 +#HHT_NONFAMILY_FEMALE_ALONE: 6 +#HHT_NONFAMILY_FEMALE_NOTALONE: 7 + +# convenience for expression files +HHT_NONFAMILY: [4, 5, 6, 7] +HHT_FAMILY: [1, 2, 3] + +PSTUDENT_GRADE_OR_HIGH: 1 +PSTUDENT_UNIVERSITY: 2 +PSTUDENT_NOT: 3 + +GRADE_SCHOOL_MAX_AGE: 14 +GRADE_SCHOOL_MIN_AGE: 5 + +SCHOOL_SEGMENT_NONE: 0 +SCHOOL_SEGMENT_GRADE: 1 +SCHOOL_SEGMENT_HIGH: 2 +SCHOOL_SEGMENT_UNIV: 3 + +INCOME_SEGMENT_LOW: 1 +INCOME_SEGMENT_MED: 2 +INCOME_SEGMENT_HIGH: 3 +INCOME_SEGMENT_VERYHIGH: 4 + +PEMPLOY_FULL: 1 +PEMPLOY_PART: 2 +PEMPLOY_NOT: 3 +PEMPLOY_CHILD: 4 + +PTYPE_FULL: &ptype_full 1 +PTYPE_PART: &ptype_part 2 +PTYPE_UNIVERSITY: &ptype_university 3 +PTYPE_NONWORK: &ptype_nonwork 4 +PTYPE_RETIRED: &ptype_retired 5 +PTYPE_DRIVING: &ptype_driving 6 +PTYPE_SCHOOL: &ptype_school 7 +PTYPE_PRESCHOOL: &ptype_preschool 8 + +# these appear as column headers in non_mandatory_tour_frequency.csv +PTYPE_NAME: + *ptype_full: PTYPE_FULL + *ptype_part: PTYPE_PART + *ptype_university: PTYPE_UNIVERSITY + *ptype_nonwork: PTYPE_NONWORK + *ptype_retired: PTYPE_RETIRED + *ptype_driving: PTYPE_DRIVING + *ptype_school: PTYPE_SCHOOL + *ptype_preschool: PTYPE_PRESCHOOL + + +CDAP_ACTIVITY_MANDATORY: M +CDAP_ACTIVITY_NONMANDATORY: N +CDAP_ACTIVITY_HOME: H + +# Correction for transit skim expressions +# e.g. MTC transit skims (Cube TRANPLAN skims) use scaled ints and +# therefore need to be divided by the scale factor if used in expressions +TRANSIT_SCALE_FACTOR: 100 diff --git a/test/auto_ownership/configs/initialize_households.yaml b/test/auto_ownership/configs/initialize_households.yaml new file mode 100644 index 000000000..5d98a703d --- /dev/null +++ b/test/auto_ownership/configs/initialize_households.yaml @@ -0,0 +1,37 @@ +annotate_tables: + - tablename: persons + column_map: + HHID: household_id + PERID: person_id + AGEP: age + SEX: sex + SCHL: education_attainment + OCCP: occupation + WKHP: hours_worked + WKW: weeks_worked + EMPLOYED: employment_status + ESR: esr + SCHG: grade_attending + annotate: + SPEC: annotate_persons + DF: persons + TABLES: + - households + - tablename: households + column_map: + HHID: household_id + MAZ: home_zone_id + HHINCADJ: income + NWRKRS_ESR: num_workers + VEH: auto_ownership + NP: hhsize + HHT: hh_type + BLD: building_size + TYPE: hh_unit_type + MTCCountyID: county_id + annotate: + SPEC: annotate_households + DF: households + TABLES: + - persons + - land_use \ No newline at end of file diff --git a/test/auto_ownership/configs/initialize_landuse.yaml b/test/auto_ownership/configs/initialize_landuse.yaml new file mode 100644 index 000000000..7cc1d7e34 --- /dev/null +++ b/test/auto_ownership/configs/initialize_landuse.yaml @@ -0,0 +1,54 @@ +annotate_tables: + - tablename: land_use + column_map: + MAZ_ORIGINAL: zone_id + CountyID: county_id + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + annotate: + SPEC: annotate_landuse + DF: land_use + - tablename: accessibility + column_map: + column_1: nonmandatory_auto_accessibility + column_2: nonmandatory_transit_accessibility + column_3: nonmandatory_nm_accessibility + column_4: nonmandatory_sov0_accessibility + column_5: nonmandatory_sov1_accessibility + column_6: nonmandatory_sov2_accessibility + column_7: nonmandatory_hov0_accessibility + column_8: nonmandatory_hov1_accessibility + column_9: nonmandatory_hov2_accessibility + column_10: shop_hov_insufficient_accessibility + column_11: shop_hov_sufficient_accessibility + column_12: shop_hov_oversufficient_accessibility + column_13: maint_hov_insufficient_accessibility + column_14: maint_hov_sufficient_accessibility + column_15: maint_hov_oversufficient_accessibility + column_16: eat_hov_insufficient_accessibility + column_17: eat_hov_sufficient_accessibility + column_18: eat_hov_oversufficient_accessibility + column_19: visit_hov_insufficient_accessibility + column_20: visit_hov_sufficient_accessibility + column_21: visit_hov_oversufficient_accessibility + column_22: discr_hov_insufficient_accessibility + column_23: discr_hov_sufficient_accessibility + column_24: discr_hov_oversufficient_accessibility + column_25: escort_hov_insufficient_accessibility + column_26: escort_hov_sufficient_accessibility + column_27: escort_hov_oversufficient_accessibility + column_28: shop_sov_insufficient_accessibility + column_29: shop_sov_sufficient_accessibility + column_30: shop_sov_oversufficient_accessibility + column_31: maint_sov_insufficient_accessibility + column_32: maint_sov_sufficient_accessibility + column_33: maint_sov_oversufficient_accessibility + column_40: discr_sov_insufficient_accessibility + column_41: discr_sov_sufficient_accessibility + column_42: discr_sov_oversufficient_accessibility + column_45: total_emp_accessibility + column_47: hh_walktransit_accessibility + mgra : zone_id \ No newline at end of file diff --git a/test/auto_ownership/configs/network_los.yaml b/test/auto_ownership/configs/network_los.yaml new file mode 100644 index 000000000..391125a38 --- /dev/null +++ b/test/auto_ownership/configs/network_los.yaml @@ -0,0 +1,14 @@ +# read cached skims (using numpy memmap) from output directory (memmap is faster than omx ) +read_skim_cache: False +# write memmapped cached skims to output directory after reading from omx, for use in subsequent runs +write_skim_cache: True + +zone_system: 1 + +taz_skims: skims.omx + +skim_time_periods: + time_window: 1440 + period_minutes: 60 + periods: [0, 3, 5, 9, 14, 18, 24] # 3=3:00-3:59, 5=5:00-5:59, 9=9:00-9:59, 14=2:00-2:59, 18=6:00-6:59 + labels: ['EA', 'EA', 'AM', 'MD', 'PM', 'EV'] \ No newline at end of file diff --git a/test/auto_ownership/configs/settings.yaml b/test/auto_ownership/configs/settings.yaml new file mode 100644 index 000000000..ce94eef8e --- /dev/null +++ b/test/auto_ownership/configs/settings.yaml @@ -0,0 +1,65 @@ +# input tables +input_table_list: + - tablename: households + filename: households.csv + index_col: household_id + rename_columns: + unique_hh_id: household_id + NP: hhsize + hh_workers_from_esr: num_workers + VEH: auto_ownership + MAZ: home_zone_id + HINCP: income + keep_columns: + - home_zone_id + - income + - hhsize + - HHT + - auto_ownership + - num_workers + - tablename: persons + filename: persons.csv + index_col: person_id + rename_columns: + unique_hh_id: household_id + AGEP: age + SPORDER: PNUM + SEX: sex + employed: pemploy + student_status: pstudent + person_type: ptype + keep_columns: + - household_id + - age + - PNUM + - sex + - pemploy + - pstudent + - ptype + - tablename: land_use + filename: land_use.csv + index_col: zone_id + rename_columns: + MAZ_ORIGINAL: zone_id + CountyID: county_id + TAZ_ORIGINAL: TAZ + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + keep_columns: + - TAZ + - DISTRICT + - SD + - county_id + - TOTHH + - TOTPOP + - TOTACRE + +#trace_hh_id: 357022 +trace_hh_id: 36 + +use_accessibility: 0 + +mobility_av_share: 0.0 \ No newline at end of file diff --git a/test/auto_ownership/configs/tour_departure_and_duration_alternatives.csv b/test/auto_ownership/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 000000000..bddab06b9 --- /dev/null +++ b/test/auto_ownership/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/test/auto_ownership/data/.gitkeep b/test/auto_ownership/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/auto_ownership/test_auto_ownership.py b/test/auto_ownership/test_auto_ownership.py new file mode 100644 index 000000000..63a49969d --- /dev/null +++ b/test/auto_ownership/test_auto_ownership.py @@ -0,0 +1,434 @@ +import logging +import pytest +import os +import shutil +import pandas as pd +import numpy as np +from numpy import dot +from numpy.linalg import norm +import orca +from numpy.random import randint +import scipy.stats as stats + +# import models is necessary to initalize the model steps with orca +from activitysim.abm import models +from activitysim.core import pipeline, config +from activitysim.core import tracing + +logger = logging.getLogger(__name__) + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def module() -> str: + """ + A pytest fixture that returns the data folder location. + :return: folder location for any necessary data to initialize the tests + """ + return "auto_ownership" + + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def tables(prepare_module_inputs) -> dict[str, str]: + """ + A pytest fixture that returns the "mock" tables to build pipeline dataframes. The + key-value pair is the name of the table and the index column. + :return: dict + """ + return { + "land_use": "MAZ_ORIGINAL", + "persons": "person_id", + "households": "household_id", + "accessibility": "MAZ_ORIGINAL", + } + + +# Used by conftest.py initialize_pipeline method +# Set to true if you need to read skims into the pipeline +@pytest.fixture(scope="module") +def initialize_network_los() -> bool: + """ + A pytest boolean fixture indicating whether network skims should be read from the + fixtures test data folder. + :return: bool + """ + return False + + +# Used by conftest.py reconnect_pipeline method +@pytest.fixture(scope="module") +def load_checkpoint() -> bool: + """ + checkpoint to be loaded from the pipeline when reconnecting. + """ + return "initialize_households" + + +@pytest.mark.skipif( + os.path.isfile("test/auto_ownership/output/pipeline.h5"), + reason="no need to recreate pipeline store if alreayd exist", +) +def test_prepare_input_pipeline(initialize_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["initialize_landuse", "initialize_households"]) + + pipeline.close_pipeline() + + +def test_auto_ownership(reconnect_pipeline: pipeline.Pipeline, caplog): + + caplog.set_level(logging.INFO) + + # run model step + pipeline.run( + models=["auto_ownership_simulate"], resume_after="initialize_households" + ) + + # get the updated pipeline data + household_df = pipeline.get_table("households") + # logger.info("household_df columns: ", household_df.columns.tolist()) + + # target_col = "autos" + target_col = "pre_autos" + choice_col = "auto_ownership" + simulated_col = "autos_model" + + similarity_threshold = 0.99 + + ao_alternatives_df = pd.DataFrame.from_dict( + { + choice_col: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + "auto_choice_label": [ + "0_CARS", + "1_CAR_1CV", + "1_CAR_1AV", + "2_CARS_2CV", + "2_CARS_2AV", + "2_CARS_1CV1AV", + "3_CARS_3CV", + "3_CARS_3AV", + "3_CARS_2CV1AV", + "3_CARS_1CV2AV", + "4_CARS_4CV", + ], + simulated_col: [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4], + } + ) + + household_df = pd.merge(household_df, ao_alternatives_df, how="left", on=choice_col) + + # AO summary from the model + simulated_df = create_summary( + household_df, key=simulated_col, out_col="Simulated_Share" + ) + + # AO summary from the results/target + target_df = create_summary(household_df, key=target_col, out_col="Target_Share") + + merged_df = pd.merge( + target_df, simulated_df, left_on=target_col, right_on=simulated_col, how="outer" + ) + merged_df = merged_df.fillna(0) + + # compare simulated and target results by computing the cosine similarity between them + similarity_value = cosine_similarity( + merged_df["Target_Share"].tolist(), merged_df["Simulated_Share"].tolist() + ) + + # save the results to disk + merged_df.to_csv( + os.path.join("test", "auto_ownership", "output", "ao_test_results.csv"), + index=False, + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + +@pytest.mark.skip +def test_auto_ownership_variation(reconnect_pipeline: pipeline.Pipeline, caplog): + + caplog.set_level(logging.INFO) + + output_file = os.path.join( + "test", "auto_ownership", "output", "ao_results_variation.csv" + ) + + if os.path.isfile(output_file): + out_df = pd.read_csv(output_file) + + pipeline.open_pipeline(resume_after="initialize_households") + + household_df = pipeline.get_table("households") + + else: + target_col = "pre_autos" + choice_col = "auto_ownership" + simulated_col = "autos_model" + + ao_alternatives_df = pd.DataFrame.from_dict( + { + choice_col: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + "auto_choice_label": [ + "0_CARS", + "1_CAR_1CV", + "1_CAR_1AV", + "2_CARS_2CV", + "2_CARS_2AV", + "2_CARS_1CV1AV", + "3_CARS_3CV", + "3_CARS_3AV", + "3_CARS_2CV1AV", + "3_CARS_1CV2AV", + "4_CARS_4CV", + ], + simulated_col: [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4], + } + ) + + NUM_SEEDS = 100 + + for i in range(1, NUM_SEEDS + 1): + base_seed = randint(1, 99999) + orca.add_injectable("rng_base_seed", base_seed) + + # run model step + pipeline.run( + models=["auto_ownership_simulate"], resume_after="initialize_households" + ) + + # get the updated pipeline data + household_df = pipeline.get_table("households") + + household_df = pd.merge( + household_df, ao_alternatives_df, how="left", on=choice_col + ) + + # AO summary from the model + simulated_share_col_name = "simulation_" + str(i) + simulated_df = create_summary( + household_df, key=simulated_col, out_col=simulated_share_col_name + ) + + if i == 1: + out_df = create_summary(household_df, key=target_col, out_col="target") + + out_df = pd.concat( + [out_df, simulated_df[[simulated_share_col_name]]], axis=1 + ) + + # since model_name is used as checkpoint name, the same model can not be run more than once. + # have to close the pipeline before running the same model again. + pipeline.close_pipeline() + + out_df["simulation_min"] = out_df.filter(like="simulation_").min(axis=1) + out_df["simulation_max"] = out_df.filter(like="simulation_").max(axis=1) + out_df["simulation_mean"] = out_df.filter(like="simulation_").mean(axis=1) + + # reorder columns + cols = [ + "pre_autos", + "target", + "simulation_mean", + "simulation_min", + "simulation_max", + ] + cols = cols + [x for x in out_df.columns if x not in cols] + out_df = out_df[cols] + + out_df.to_csv(output_file, index=False) + + # chi-square test + alpha = 0.05 + observed_prob = out_df["simulation_mean"] + expected_prob = out_df["target"] + + num_hh = len(household_df) + + observed = [p * num_hh for p in observed_prob] + expected = [p * num_hh for p in expected_prob] + + observed_sum = sum(observed) + expected_sum = sum(expected) + + # the sum of the observed and expected frequencies must be the same for the test + observed = [f * expected_sum / observed_sum for f in observed] + + chi_square, prob = stats.chisquare(observed, expected) + p_value = 1 - prob + + # Ho: Target and Simulated results are from same distribution and there is no significant difference b/w the two. + # Ha: Target and Simulated results are statistically different. + + conclusion = "Failed to reject the null hypothesis." + if p_value >= alpha: + conclusion = "Null Hypothesis is rejected. Obersved and Simulated results are statistically different." + + logger.info(conclusion) + + # if p-value is less than alpha, then difference between simulated and target results + # are statistically greater than the random variation of the model results + assert p_value < alpha + + +# fetch/prepare existing files for model inputs +# e.g. read accessibilities.csv from ctramp result, rename columns, write out to accessibility.csv which is the input to activitysim +@pytest.fixture(scope="module") +def prepare_module_inputs() -> None: + """ + copy input files from sharepoint into test folder + + create unique person id in person file + + :return: None + """ + # https://wsponlinenam.sharepoint.com/sites/US-TM2ConversionProject/Shared%20Documents/Forms/ + # AllItems.aspx?id=%2Fsites%2FUS%2DTM2ConversionProject%2FShared%20Documents%2FTask%203%20ActivitySim&viewid=7a1eaca7%2D3999%2D4d45%2D9701%2D9943cc3d6ab1 + accessibility_file = os.path.join( + "test", "auto_ownership", "data", "accessibilities.csv" + ) + household_file = os.path.join( + "test", "auto_ownership", "data", "popsyn", "households.csv" + ) + person_file = os.path.join( + "test", "auto_ownership", "data", "popsyn", "persons.csv" + ) + landuse_file = os.path.join( + "test", "auto_ownership", "data", "landuse", "maz_data_withDensity.csv" + ) + + test_dir = os.path.join("test", "auto_ownership", "data") + + shutil.copy(accessibility_file, os.path.join(test_dir, "accessibility.csv")) + shutil.copy(household_file, os.path.join(test_dir, "households.csv")) + shutil.copy(person_file, os.path.join(test_dir, "persons.csv")) + shutil.copy(landuse_file, os.path.join(test_dir, "land_use.csv")) + + # add original maz id to accessibility table + land_use_df = pd.read_csv(os.path.join(test_dir, "land_use.csv")) + + accessibility_df = pd.read_csv(os.path.join(test_dir, "accessibility.csv")) + + accessibility_df = pd.merge( + accessibility_df, + land_use_df[["MAZ", "MAZ_ORIGINAL"]].rename(columns={"MAZ": "mgra"}), + how="left", + on="mgra", + ) + + accessibility_df.to_csv(os.path.join(test_dir, "accessibility.csv"), index=False) + + # currently household file has to have these two columns, even before annotation + # because annotate person happens before household and uses these two columns + # TODO find a way to get around this + #### + + # household file from populationsim + household_df = pd.read_csv(os.path.join(test_dir, "households.csv")) + + household_columns_dict = {"HHID": "household_id", "MAZ": "home_zone_id"} + + household_df.rename(columns=household_columns_dict, inplace=True) + + # get columns from ctramp output + tm2_simulated_household_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "householdData_3.csv") + ) + tm2_simulated_household_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + household_df = pd.merge( + household_df, + tm2_simulated_household_df[ + [ + "household_id", + "autos", + "automated_vehicles", + "transponder", + "cdap_pattern", + "jtf_choice", + ] + ], + how="inner", # tm2 is not 100% sample run + on="household_id", + ) + + tm2_pre_ao_results_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "aoResults_pre.csv") + ) + tm2_pre_ao_results_df.rename( + columns={"HHID": "household_id", "AO": "pre_autos"}, inplace=True + ) + + household_df = pd.merge( + household_df, tm2_pre_ao_results_df, how="inner", on="household_id" + ) + + household_df.to_csv(os.path.join(test_dir, "households.csv"), index=False) + + # person file from populationsim + person_df = pd.read_csv(os.path.join(test_dir, "persons.csv")) + + person_columns_dict = {"HHID": "household_id", "PERID": "person_id"} + + person_df.rename(columns=person_columns_dict, inplace=True) + + # get columns from ctramp result + tm2_simulated_person_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "personData_3.csv") + ) + tm2_simulated_person_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + person_df = pd.merge( + person_df, + tm2_simulated_person_df[ + [ + "household_id", + "person_id", + "type", + "value_of_time", + "activity_pattern", + "imf_choice", + "inmf_choice", + "fp_choice", + "reimb_pct", + "workDCLogsum", + "schoolDCLogsum", + ] + ], + how="inner", # ctramp might not be 100% sample run + on=["household_id", "person_id"], + ) + + person_df.to_csv(os.path.join(test_dir, "persons.csv"), index=False) + + +def create_summary(input_df, key, out_col="Share") -> pd.DataFrame: + """ + Create summary for the input data. + 1. group input data by the "key" column + 2. calculate the percent of input data records in each "key" category. + + :return: pd.DataFrame + """ + + out_df = input_df.groupby(key).size().reset_index(name="Count") + out_df[out_col] = round(out_df["Count"] / out_df["Count"].sum(), 4) + + return out_df[[key, out_col]] + + +def cosine_similarity(a, b): + """ + Computes cosine similarity between two vectors. + + Cosine similarity is used here as a metric to measure similarity between two sequence of numbers. + Two sequence of numbers are represented as vectors (in a multi-dimensional space) and cosine similiarity is defined as the cosine of the angle between them + i.e., dot products of the vectors divided by the product of their lengths. + + :return: + """ + + return dot(a, b) / (norm(a) * norm(b)) diff --git a/test/cdap/.gitkeep b/test/cdap/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/cdap/configs/annotate_households.csv b/test/cdap/configs/annotate_households.csv new file mode 100644 index 000000000..bd6dc6fef --- /dev/null +++ b/test/cdap/configs/annotate_households.csv @@ -0,0 +1,18 @@ +Description,Target,Expression +#,, annotate households table after import +,_PERSON_COUNT,"lambda query, persons, households: persons.query(query).groupby('household_id').size().reindex(households.index).fillna(0).astype(np.int8)" +number of non_workers,num_non_workers,households.hhsize - households.num_workers +number of drivers,num_drivers,"_PERSON_COUNT('16 <= age', persons, households)" +num_adults,num_adults,"_PERSON_COUNT('adult', persons, households)" +num_children,num_children,"_PERSON_COUNT('~adult', persons, households)" +num_young_children,num_young_children,"_PERSON_COUNT('age <= 5', persons, households)" +num_children_6_to_15,num_children_6_to_15,"_PERSON_COUNT('6 <= age <= 15', persons, households)" +num_children_16_to_17,num_children_16_to_17,"_PERSON_COUNT('16 <= age <= 17', persons, households)" +num_college_age,num_college_age,"_PERSON_COUNT('18 <= age <= 24', persons, households)" +# get definition from travel model two +num_young_adults,num_young_adults,"_PERSON_COUNT('18 <= age <= 24', persons, households)" +num_young_retirees,num_young_retirees,"_PERSON_COUNT('65 <= age <= 79', persons, households)" +num_old_retirees,num_old_retirees,"_PERSON_COUNT('80 <= age', persons, households)" +num_persons_18_to_35,num_persons_18_to_35,"_PERSON_COUNT('18 <= age <= 35', persons, households)" +num_persons_65_plus,num_persons_65_plus,"_PERSON_COUNT('65 <= age', persons, households)" +num_highschool_graduates,num_highschool_graduates,"_PERSON_COUNT('9 <= education_attainment', persons, households)" \ No newline at end of file diff --git a/test/cdap/configs/annotate_households_cdap.csv b/test/cdap/configs/annotate_households_cdap.csv new file mode 100644 index 000000000..cd66b1c42 --- /dev/null +++ b/test/cdap/configs/annotate_households_cdap.csv @@ -0,0 +1,11 @@ +Description,Target,Expression +#,, annotate households table after cdap model has run +num_under16_not_at_school,num_under16_not_at_school,persons.under16_not_at_school.astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active,num_travel_active,persons.travel_active.astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active_adults,num_travel_active_adults,(persons.adult & persons.travel_active).astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active_preschoolers,num_travel_active_preschoolers,((persons.ptype == PTYPE_PRESCHOOL) & persons.travel_active).astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active_children,num_travel_active_children,num_travel_active - num_travel_active_adults +num_travel_active_non_preschoolers,num_travel_active_non_preschoolers,num_travel_active - num_travel_active_preschoolers +#participates_in_jtf_model,participates_in_jtf_model,(num_travel_active > 1) & (num_travel_active_non_preschoolers > 0) +participates_in_jtf_model,participates_in_jtf_model,(num_travel_active > 1) +cdap_activity,cdap_activity,"persons.cdap_activity.groupby(persons.household_id).apply(''.join).reindex(households.index).fillna('')" \ No newline at end of file diff --git a/test/cdap/configs/annotate_landuse.csv b/test/cdap/configs/annotate_landuse.csv new file mode 100644 index 000000000..65237c0ad --- /dev/null +++ b/test/cdap/configs/annotate_landuse.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +#,, annotate landuse table after import +household_density,household_density,land_use.TOTHH / land_use.TOTACRE +employment_density,employment_density,land_use.TOTEMP / land_use.TOTACRE +population_density,population_density,land_use.TOTPOP / land_use.TOTACRE +density_index,density_index,(household_density *employment_density) / (household_density + employment_density).clip(lower=1) \ No newline at end of file diff --git a/test/cdap/configs/annotate_persons.csv b/test/cdap/configs/annotate_persons.csv new file mode 100644 index 000000000..0aea67814 --- /dev/null +++ b/test/cdap/configs/annotate_persons.csv @@ -0,0 +1,54 @@ +Description,Target,Expression +#,, annotate persons table after import +age_16_to_19,age_16_to_19,"persons.age.between(16, 19)" +age_16_p,age_16_p,persons.age >= 16 +adult,adult,persons.age >= 18 +male,male,persons.sex == 1 +female,female,persons.sex == 2 +#,, annotate employment category +#employment category - under employment age,empcat, +#employment category - over employment age and not employed,empcat, +#employment category - over employment age and working at least 35 hours a week and 27+ weeks a year,empcat, +#employment category - over employment age and not working at least 35 hours a week and 27+ weeks a year,empcat, +#,,TODO add ptype annotation +,ptype,0 +,ptype,"np.where(persons.type == 'Full-time worker', 1, ptype)" +,ptype,"np.where(persons.type == 'Part-time worker', 2, ptype)" +,ptype,"np.where(persons.type == 'University student', 3, ptype)" +,ptype,"np.where(persons.type == 'Non-worker', 4, ptype)" +,ptype,"np.where(persons.type == 'Retired', 5, ptype)" +,ptype,"np.where(persons.type == 'Student of driving age', 6, ptype)" +,ptype,"np.where(persons.type == 'Student of non-driving age', 7, ptype)" +,ptype,"np.where(persons.type == 'Child too young for school', 8, ptype)" +#full time worker,ptype +#presence of non_worker other than self in household,has_non_worker,"other_than(persons.household_id, persons.ptype == PTYPE_NONWORK)" +#presence of retiree other than self in household,has_retiree,"other_than(persons.household_id, persons.ptype == PTYPE_RETIRED)" +#presence of preschooler other than self in household,has_preschool_kid,"other_than(persons.household_id, persons.ptype == PTYPE_PRESCHOOL)" +#presence of driving_kid other than self in household,has_driving_kid,"other_than(persons.household_id, persons.ptype == PTYPE_DRIVING)" +#presence of school_kid other than self in household,has_school_kid,"other_than(persons.household_id, persons.ptype == PTYPE_SCHOOL)" +#presence of full_time worker other than self in household (independent of person type),has_full_time,"other_than(persons.household_id, persons.pemploy==PEMPLOY_FULL)" +#presence of part_time worker other than self in household (independent of person type),has_part_time,"other_than(persons.household_id, persons.pemploy==PEMPLOY_PART)" +#presence of university student other than self in household,has_university,"other_than(persons.household_id, persons.ptype == PTYPE_UNIVERSITY)" +#student_is_employed,student_is_employed,"(persons.ptype.isin([PTYPE_UNIVERSITY, PTYPE_DRIVING]) & persons.pemploy.isin([PEMPLOY_FULL, PEMPLOY_PART]))" +#nonstudent_to_school,nonstudent_to_school,"(persons.ptype.isin([PTYPE_FULL, PTYPE_PART, PTYPE_NONWORK, PTYPE_RETIRED]) & persons.pstudent.isin([PSTUDENT_GRADE_OR_HIGH, PSTUDENT_UNIVERSITY]))" +#,, +#,, FIXME - if person is a university student but has school age student category value then reset student category value +#,pstudent,"persons.pstudent.where(persons.ptype!=PTYPE_UNIVERSITY, PSTUDENT_UNIVERSITY)" +#,, FIXME if person is a student of any kind but has full-time employment status then reset student category value to non-student +#,pstudent,"pstudent.where(persons.ptype!=PTYPE_FULL, PSTUDENT_NOT)" +#,, FIXME if student category is non-student and employment is student then reset student category value to student +#,pstudent,"pstudent.where((persons.ptype!=PTYPE_DRIVING) & (persons.ptype!=PTYPE_SCHOOL), PSTUDENT_GRADE_OR_HIGH)" +#,, +#is_student,is_student,"pstudent.isin([PSTUDENT_GRADE_OR_HIGH, PSTUDENT_UNIVERSITY])" +#preschool age can go to preschool,is_student,"is_student.where(persons.age > GRADE_SCHOOL_MIN_AGE, True)" +#preschool age can go to preschool,pstudent,"pstudent.where(persons.age > GRADE_SCHOOL_MIN_AGE, PSTUDENT_GRADE_OR_HIGH)" +#is_gradeschool,is_gradeschool,(pstudent == PSTUDENT_GRADE_OR_HIGH) & (persons.age <= GRADE_SCHOOL_MAX_AGE) +#is_highschool,is_highschool,(pstudent == PSTUDENT_GRADE_OR_HIGH) & (persons.age > GRADE_SCHOOL_MAX_AGE) +#is_university,is_university,pstudent == PSTUDENT_UNIVERSITY +#school_segment gradeschool,school_segment,"np.where(is_gradeschool, SCHOOL_SEGMENT_GRADE, SCHOOL_SEGMENT_NONE)" +#school_segment highschool,school_segment,"np.where(is_highschool, SCHOOL_SEGMENT_HIGH, school_segment)" +#school_segment university,school_segment,"np.where(is_university, SCHOOL_SEGMENT_UNIV, school_segment).astype(np.int8)" +#,, +#is_worker,is_worker,"persons.pemploy.isin([PEMPLOY_FULL, PEMPLOY_PART])" +#,, +home_zone_id,home_zone_id,"reindex(households.home_zone_id, persons.household_id)" diff --git a/test/cdap/configs/annotate_persons_after_hh.csv b/test/cdap/configs/annotate_persons_after_hh.csv new file mode 100644 index 000000000..0dfa16be6 --- /dev/null +++ b/test/cdap/configs/annotate_persons_after_hh.csv @@ -0,0 +1,5 @@ +Description,Target,Expression +#,, annotate persons table after annotate_households +#,, adults get full hh_value_of_time and children get 60% +,_hh_vot,"reindex(households.hh_value_of_time, persons.household_id)" +,value_of_time,"_hh_vot.where(persons.age>=18, _hh_vot * 0.667)" \ No newline at end of file diff --git a/test/cdap/configs/annotate_persons_cdap.csv b/test/cdap/configs/annotate_persons_cdap.csv new file mode 100644 index 000000000..2ad5e56a6 --- /dev/null +++ b/test/cdap/configs/annotate_persons_cdap.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +#,, annotate persons table after cdap model has run +travel_active,travel_active,persons.cdap_activity != CDAP_ACTIVITY_HOME +under16_not_at_school,under16_not_at_school,"persons.ptype.isin([PTYPE_SCHOOL, PTYPE_PRESCHOOL]) & persons.cdap_activity.isin(['N', 'H'])" +has_preschool_kid_at_home,has_preschool_kid_at_home,"other_than(persons.household_id, (persons.ptype == PTYPE_PRESCHOOL) & (persons.cdap_activity == 'H'))" +has_school_kid_at_home,has_school_kid_at_home,"other_than(persons.household_id, (persons.ptype == PTYPE_SCHOOL) & (persons.cdap_activity == 'H'))" diff --git a/test/cdap/configs/cdap.yaml b/test/cdap/configs/cdap.yaml new file mode 100644 index 000000000..5758444c2 --- /dev/null +++ b/test/cdap/configs/cdap.yaml @@ -0,0 +1,49 @@ + +INDIV_AND_HHSIZE1_SPEC: cdap_indiv_and_hhsize1.csv +COEFFICIENTS: cdap_coefficients.csv +INTERACTION_COEFFICIENTS: cdap_interaction_coefficients.csv + +FIXED_RELATIVE_PROPORTIONS_SPEC: cdap_fixed_relative_proportions.csv + +# set to True if want to introduce joint tour utility in cdap +# otherwise set to False or comment out, defaulted to False +ADD_JOINT_TOUR_UTILITY: True +JOINT_TOUR_COEFFICIENTS: cdap_joint_tour_coefficients.csv +JOINT_TOUR_USEFUL_COLUMNS: + - autos + - income + - num_workers + - nonmandatory_hov0_accessibility + - nonmandatory_hov1_accessibility + - nonmandatory_hov2_accessibility + - WorkLocationLogsum + +CONSTANTS: + FULL: 1 + PART: 2 + UNIVERSITY: 3 + NONWORK: 4 + RETIRED: 5 + DRIVING: 6 + SCHOOL: 7 + PRESCHOOL: 8 + +PERSON_TYPE_MAP: + WORKER: + - 1 + - 2 + CHILD: + - 6 + - 7 + - 8 + +annotate_persons: + SPEC: annotate_persons_cdap + DF: persons + + +annotate_households: + SPEC: annotate_households_cdap + DF: households + TABLES: + - persons diff --git a/test/cdap/configs/cdap_coefficients.csv b/test/cdap/configs/cdap_coefficients.csv new file mode 100644 index 000000000..110ee2a44 --- /dev/null +++ b/test/cdap/configs/cdap_coefficients.csv @@ -0,0 +1,235 @@ +coefficient_name,value,constrain +coef_UNAVAILABLE,-999,T +coef_full_time_worker_asc_M,2.9114,F +coef_full_time_worker_asc_N,-0.7695,F +coef_part_time_worker_asc_M,2.9274,F +coef_part_time_worker_asc_N,1.3675,F +coef_university_student_asc_M,1.7642,F +coef_university_student_asc_N,-0.3138,F +coef_non_working_adult_asc_M,-3.1521,F +coef_non_working_adult_asc_N,0.513,F +coef_retired_asc_M,-2.7055,F +coef_retired_asc_N,0.9234,F +coef_driving_age_child_who_is_in_school_asc_M,3.2036,F +coef_driving_age_child_who_is_in_school_asc_N,-3.4315,F +coef_pre_driving_age_child_who_is_in_school_asc_M,7.0644,F +coef_pre_driving_age_child_who_is_in_school_asc_N,2.574,F +coef_pre_driving_age_child_who_is_too_young_for_school_asc_M,1.1,F +coef_pre_driving_age_child_who_is_too_young_for_school_asc_N,0.6017,F +#,, +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_0_to_1_M,-1.5151,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_0_to_1_N,0.3702,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_4_to_5_M,3.2965,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_4_to_5_N,1.1392,F +coef_pre_driving_age_child_who_is_in_school_interaction_with_age_13_to_15_M,-0.8582,F +coef_full_time_worker_interaction_with_age_less_than_35_N,-0.145,F +coef_part_time_worker_interaction_with_age_less_than_35_M,-0.7095,F +coef_part_time_worker_interaction_with_age_less_than_35_N,-1.4213,F +#,, +coef_full_time_worker_interaction_with_female_gender_M,0.3032,F +coef_full_time_worker_interaction_with_female_gender_N,0.7718,F +coef_part_time_worker_interaction_with_female_gender_M,0.061,F +coef_part_time_worker_interaction_with_female_gender_N,0.4176,F +coef_university_student_interaction_with_female_gender_M,1.2429,F +coef_university_student_interaction_with_female_gender_N,2.2549,F +coef_non_working_adult_interaction_with_female_gender_N,0.1475,F +coef_retired_interaction_with_female_M,-0.7751,F +coef_retired_interaction_with_female_N,-0.3729,F +coef_driving_age_child_who_is_in_school_interaction_with_female_N,0.7991,F +#,, +coef_full_time_worker_interaction_with_more_cars_than_workers_N,-0.087,F +coef_non_working_adult_interaction_with_more_cars_than_workers_N,0.2122,F +coef_retired_interaction_with_more_cars_than_workers_N,0.8642,F +coef_driving_age_child_who_is_in_school_interaction_with_more_cars_than_workers_M,0.0988,F +coef_full_time_worker_interaction_with_zero_cars_M,-0.3377,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_zero_cars_M,-0.5917,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_zero_cars_N,-1.4389,F +coef_full_time_worker_interaction_with_fewer_cars_than_workers_M,-0.3377,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_fewer_cars_than_workers_M,-0.4778,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_fewer_cars_than_workers_N,-0.5259,F +#,, +coef_full_time_worker_interaction_with_income_less_than_30k_M,-0.7201,F +coef_full_time_worker_interaction_with_income_less_than_30k_H,-0.5331,F +coef_part_time_worker_interaction_with_income_less_than_30k_M,0.1285,F +coef_university_student_interaction_with_income_less_than_30k_M,0.4359,F +coef_university_student_interaction_with_income_between_60k_and_100k_H,0.6352,F +coef_university_student_interaction_with_income_more_than_100k_H,0.6352,F +coef_non_working_adult_interaction_with_income_more_than_100k_H,-0.2468,F +coef_retired_interaction_with_income_more_than_100k_M,-0.1418,F +coef_retired_interaction_with_income_more_than_100k_H,-0.2388,F +coef_pre_driving_age_child_who_is_in_school_interaction_with_income_less_than_30k_M,1.2007,F +coef_pre_driving_age_child_who_is_in_school_interaction_with_income_less_than_30k_H,1.9783,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_income_between_60k_and_100k_M,0.2952,F +coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_income_more_than_100k_M,0.2952,F +#,, +coef_full_time_worker_intraction_with_peak_accessibility_to_all_employment_M,0.1212,F +coef_part_time_worker_interaction_with_peak_accessibility_to_all_employment_M,0.2004,F +coef_non_working_adult_interaction_with_peak_accessibility_to_all_employment_M,0.2314,F +coef_retired_interaction_with_peak_accessibility_to_all_employment_M,0.2792,F +coef_non_working_adult_retired_or_univ_student_interaction_with_off_peak_accessibility_to_all_employment_N,0.0721,F +coef_child_who_is_in_school_or_too_young_for_school_interaction_with_off_peak_accessibility_to_retail_N,0.0823,F +#,, +coef_university_student_interaction_with_school_location_mc_logsum_M,0.0243,F +coef_full_time_worker_interaction_with_usual_work_location_is_home_M,-2.4147,F +coef_part_time_worker_interaction_with_usual_work_location_is_home_M,-2.8801,F +coef_full_time_worker_interaction_with_no_usual_work_location_M,-0.3777,F +coef_part_time_worker_interaction_with_no_usual_work_location_M,-0.6869,F +coef_full_time_worker_asc_adjustment_M,-0.2301,F +coef_part_time_worker_asc_adjustment_M,-0.471,F +coef_university_student_asc_adjustment_M,-0.3361,F +coef_driving_age_child_who_is_in_school_asc_adjustment_M,0.1434,F +coef_pre_driving_age_child_who_is_in_school_asc_adjustment_M,0.4725,F +coef_pre_driving_age_child_who_is_too_young_for_school_asc_adjustment_M,0.5554,F +coef_part_time_worker_asc_adjustment_tm2_calib_M,-0.3499,F +coef_university_student_asc_adjustment_tm2_calib_M,-0.9471,F +coef_non_working_adult_asc_adjustment_tm2_calib_M,0,F +coef_retired_asc_adjustment_tm2_calib_M,0,F +coef_full_time_worker_interaction_with_retail_accessibility_N,0.0445,F +coef_non_working_adult_interaction_with_retail_accessibility_N,0.0069,F +coef_driving_age_child_who_is_in_school_interaction_with_retail_accessibility_N,0.157,F +coef_full_time_worker_interaction_with_usual_work_location_is_home_N,0.87616,F +coef_full_time_worker_asc_adjustment_N,-0.1846,F +coef_part_time_worker_asc_adjustment_N,-0.4229,F +coef_university_student_asc_adjustment_N,0.0325,F +coef_non_working_adult_asc_adjustment_N,0.077,F +coef_retired_asc_adjustment_N,-0.0012,F +coef_driving_age_child_who_is_in_school_asc_adjustment_N,-0.8075,F +coef_pre_driving_age_child_who_is_in_school_asc_adjustment_N,-0.1462,F +coef_pre_driving_age_child_who_is_too_young_for_school_asc_adjustment_N,0.134,F +coef_part_time_worker_asc_adjustment_tm2_calib_N,0.5217,F +coef_university_student_asc_adjustment_tm2_calib_N,-0.6678,F +coef_non_working_adult_asc_adjustment_tm2_calib_N,0.0466,F +coef_retired_asc_adjustment_tm2_calib_N,0.1313,F +coef_full_time_worker_interaction_with_detached_home_H,0.1538,F +coef_part_time_worker_interaction_with_detached_home_H,0.0862,F +coef_retired_interaction_with_detached_home_H,0.7415,F +coef_driving_age_child_who_is_in_school_interaction_with_detached_home_H,2.023,F +#,, +# 2-way interactions,, +coef_H_11,0.7511,F +coef_H_12,0,F +coef_H_13,0,F +coef_H_14,0,F +coef_H_15,0.6692,F +coef_H_16,1.3472,F +coef_H_17,0,F +coef_H_18,0.7797,F +coef_H_22,0.7897,F +coef_H_23,1.617,F +coef_H_24,1.1606,F +coef_H_25,0.7915,F +coef_H_26,0,F +coef_H_27,1.8203,F +coef_H_28,1.7547,F +coef_H_33,0,F +coef_H_34,0.637,F +coef_H_35,0.1955,F +coef_H_36,2.2375,F +coef_H_37,0,F +coef_H_38,1.7118,F +coef_H_44,1.2214,F +coef_H_45,0.8544,F +coef_H_46,1.116,F +coef_H_47,1.974,F +coef_H_48,2.1615,F +coef_H_55,1.0484,F +coef_H_56_57,0,F +coef_H_58,1.9117,F +coef_H_66,3.192,F +coef_H_67,0,F +coef_H_68,0,F +coef_H_77,5.6222,F +coef_H_78,2.8078,F +coef_H_88,3.2327,F +coef_M_11,0,F +coef_M_12,0,F +coef_M_13,0.0627,F +coef_M_16,0,F +coef_M_17,0.1434,F +coef_M_18,0.3851,F +coef_M_22,0,F +coef_M_23,0.5967,F +coef_M_26,0,F +coef_M_27,0.4024,F +coef_M_28,0.4453,F +coef_M_33,0.3881,F +coef_M_36,0,F +coef_M_37,0.2755,F +coef_M_38,0.4148,F +coef_M_66,0.6854,F +coef_M_67,0.3692,F +coef_M_68,0.5467,F +coef_M_77,0.7729,F +coef_M_78,0,F +coef_M_88,0,F +coef_N_11,0.15,F +coef_N_12,0,F +coef_N_13,0,F +coef_N_14,0,F +coef_N_15,0,F +coef_N_16,1.0053,F +coef_N_17,0.3041,F +coef_N_18,0,F +coef_N_22,0,F +coef_N_23,0,F +coef_N_24,0,F +coef_N_25,0,F +coef_N_26,0,F +coef_N_27,0.3248,F +coef_N_28,0.9231,F +coef_N_33,0,F +coef_N_34,0,F +coef_N_35,0.8526,F +coef_N_36,0.9678,F +coef_N_37,0,F +coef_N_38,0.9241,F +coef_N_44,0,F +coef_N_45,0,F +coef_N_46,0.7134,F +coef_N_47,0.8509,F +coef_N_48,1.1721,F +coef_N_55,0,F +coef_N_56_57_58,0,F +coef_N_66,0,F +coef_N_67,1.8265,F +coef_N_68,1.1744,F +coef_N_77,2.5719,F +coef_N_78,0.7036,F +coef_N_88,0.4338,F +# 3-way interactions,, +coef_H_114,1.5072,F +coef_H_117_118,0.8382,F +coef_H_127_128,0.4246,F +coef_H_147_148,0.1548,F +coef_H_177_178_187_188,-0.7547,F +coef_H_277_278_287_288,-2.2535,F +coef_H_447_448,-0.9024,F +coef_H_477_478_487_488,-1.3723,F +coef_H_777_778_788_888,-2.4703,F +coef_M_111,0.298,F +coef_M_112,0.2032,F +coef_M_122,-0.6279,F +coef_M_127_128,-0.0432,F +coef_M_177_178_187_188,-0.1301,F +coef_M_227_228,-0.1524,F +coef_M_277_278_287_288,-0.1259,F +coef_M_777_778_788_888,-0.0112,F +coef_N_117_118,-0.5454,F +coef_N_144,-0.9496,F +coef_N_127_128,-1.7459,F +coef_N_147_148,-0.1659,F +coef_N_177_178_187_188,0.4687,F +coef_N_222,1.8781,F +coef_N_277_278_287_288,-0.6913,F +coef_N_477_478_487_488,-0.4894,F +coef_N_777_778_788_888,-0.0582,F +# cdap_all_people,, +coef_M_xxx,-0.114,F +coef_N_xxx,-0.4673,F +coef_H_xxx,-0.1538,F +coef_M_xxxx,0.4569,F +coef_N_xxxx,-0.4669,F +coef_H_xxxx,-0.4645,F +coef_M_xxxxx,-0.2607,F +coef_N_xxxxx,-1.4859,F +coef_H_xxxxx,-9,F diff --git a/test/cdap/configs/cdap_fixed_relative_proportions.csv b/test/cdap/configs/cdap_fixed_relative_proportions.csv new file mode 100644 index 000000000..788f398b6 --- /dev/null +++ b/test/cdap/configs/cdap_fixed_relative_proportions.csv @@ -0,0 +1,9 @@ +Description,Expression,M,N,H +Full-time worker,ptype == 1,0.79647,0.09368,0.10985 +Part-time worker,ptype == 2,0.61678,0.25757,0.12565 +University student,ptype == 3,0.69229,0.15641,0.1513 +Non-working adult,ptype == 4,0,0.67169,0.32831 +Retired,ptype == 5,0,0.54295,0.45705 +Driving-age child who is in school,ptype == 6,0.77609,0.06004,0.16387 +Pre-driving-age child who is in school,ptype == 7,0.68514,0.09144,0.22342 +Child who is too young for school,ptype == 8,0.14056,0.06512,0.79432 diff --git a/test/cdap/configs/cdap_indiv_and_hhsize1.csv b/test/cdap/configs/cdap_indiv_and_hhsize1.csv new file mode 100644 index 000000000..a5cb0d660 --- /dev/null +++ b/test/cdap/configs/cdap_indiv_and_hhsize1.csv @@ -0,0 +1,81 @@ +Description,Expression,M,N,H +Full-time worker alternative-specific constants,ptype == 1,coef_full_time_worker_asc_M,coef_full_time_worker_asc_N, +Part-time worker alternative-specific constants,ptype == 2,coef_part_time_worker_asc_M,coef_part_time_worker_asc_N, +University student alternative-specific constants,ptype == 3,coef_university_student_asc_M,coef_university_student_asc_N, +Non-working adult alternative-specific constants,ptype == 4,coef_non_working_adult_asc_M,coef_non_working_adult_asc_N, +Retired alternative-specific constants,ptype == 5,coef_retired_asc_M,coef_retired_asc_N, +Driving-age child who is in school alternative-specific constants,ptype == 6,coef_driving_age_child_who_is_in_school_asc_M,coef_driving_age_child_who_is_in_school_asc_N, +Pre-driving-age child who is in school alternative-specific constants,ptype == 7,coef_pre_driving_age_child_who_is_in_school_asc_M,coef_pre_driving_age_child_who_is_in_school_asc_N, +Pre-driving-age child who is too young for school alternative-specific constants,ptype == 8,coef_pre_driving_age_child_who_is_too_young_for_school_asc_M,coef_pre_driving_age_child_who_is_too_young_for_school_asc_N, +#,,,, +Pre-driving-age child who is too young for school interaction with age 0 to 1,(ptype == 8) & (age >= 0) & (age <= 1),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_0_to_1_M,coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_0_to_1_N, +Pre-driving-age child who is too young for school interaction with age 4 to 5,(ptype == 8) & (age >= 4) & (age <= 5),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_4_to_5_M,coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_age_4_to_5_N, +Pre-driving-age child who is in school interaction with age 13 to 15,(ptype == 7) & (age >= 13) & (age <= 15),coef_pre_driving_age_child_who_is_in_school_interaction_with_age_13_to_15_M,, +Full-time worker interaction with age less than 35,(ptype == 1) & (age < 35),,coef_full_time_worker_interaction_with_age_less_than_35_N, +Part-time worker interaction with age less than 35,(ptype == 2) & (age < 35),coef_part_time_worker_interaction_with_age_less_than_35_N,coef_part_time_worker_interaction_with_age_less_than_35_N, +Retired interaction with age more than 80,(ptype == 5) & (age > 80),,, +#,,,, +Full-time worker interaction with female gender,(ptype == 1) & (sex == 2),coef_full_time_worker_interaction_with_female_gender_M,coef_full_time_worker_interaction_with_female_gender_N, +Part-time worker interaction with female gender,(ptype == 2) & (sex == 2),coef_part_time_worker_interaction_with_female_gender_M,coef_part_time_worker_interaction_with_female_gender_N, +University student interaction with female gender,(ptype == 3) & (sex == 2),coef_university_student_interaction_with_female_gender_M,coef_university_student_interaction_with_female_gender_N, +Non-working adult interaction with female gender,(ptype == 4) & (sex == 2),,coef_non_working_adult_interaction_with_female_gender_N, +Retired interaction with female,(ptype == 5) & (sex == 2),coef_retired_interaction_with_female_M,coef_retired_interaction_with_female_N, +Driving-age child interaction with female,(ptype == 6) & (sex == 2),,coef_driving_age_child_who_is_in_school_interaction_with_female_N, +#,,,, +Full-time worker interaction with more cars than workers,(ptype == 1) & (autos > num_workers),,coef_full_time_worker_interaction_with_more_cars_than_workers_N, +Non-working adult interaction with more cars than workers,(ptype == 4) & (autos > num_workers),,coef_non_working_adult_interaction_with_more_cars_than_workers_N, +Retired interaction with more cars than workers,(ptype == 5) & (autos > num_workers),,coef_retired_interaction_with_more_cars_than_workers_N, +Driving-age child who is in school interaction with more cars than workers,(ptype == 6) & (autos > num_workers),coef_driving_age_child_who_is_in_school_interaction_with_more_cars_than_workers_M,, +Full-time worker interaction with zero cars,(ptype == 1) & (autos==0),coef_full_time_worker_interaction_with_zero_cars_M,, +Pre-driving-age child who is too young for school interaction with zero cars,(ptype == 8) & (autos==0),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_zero_cars_M,coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_zero_cars_N, +Full-time worker interaction with fewer cars than workers,(ptype == 1) & (autos < num_workers),coef_full_time_worker_interaction_with_fewer_cars_than_workers_M,, +Pre-driving-age child who is too young for school interaction with fewer cars than workers,(ptype == 8) & (autos < num_workers),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_fewer_cars_than_workers_M,coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_fewer_cars_than_workers_N, +#,,,, +Full-time worker interaction with income less than $30k,(ptype == 1) & (income < 30000),coef_full_time_worker_interaction_with_income_less_than_30k_M,,coef_full_time_worker_interaction_with_income_less_than_30k_H +Part-time worker interaction with income less than $30k,(ptype == 2) & (income < 30000),coef_part_time_worker_interaction_with_income_less_than_30k_M,, +University student interaction with income less than $30k,(ptype == 3) & (income < 30000),coef_university_student_interaction_with_income_less_than_30k_M,, +University student interaction with income between $60k and $100k,(ptype == 3) & (income >= 60000) & (income <= 100000),,,coef_university_student_interaction_with_income_between_60k_and_100k_H +University student interaction with income more than $100k,(ptype == 3) & (income >= 100000),,,coef_university_student_interaction_with_income_more_than_100k_H +Non-working adult interaction with income more than $100k,(ptype == 4) & (income >= 100000),,,coef_non_working_adult_interaction_with_income_more_than_100k_H +Retired interaction with income between $60k and $100k,(ptype == 5) & (income >= 60000) & (income <= 100000),,, +Retired interaction with income more than $100k,(ptype == 5) & (income >= 100000),coef_retired_interaction_with_income_more_than_100k_M,,coef_retired_interaction_with_income_more_than_100k_H +Pre-driving-age child who is in school interaction with income less than $30k,(ptype == 7) & (income < 30000),coef_pre_driving_age_child_who_is_in_school_interaction_with_income_less_than_30k_M,,coef_pre_driving_age_child_who_is_in_school_interaction_with_income_less_than_30k_H +Pre-driving-age child who is too young for school interaction with income between $60k and $100k,(ptype == 8) & (income >= 60000) & (income <= 100000),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_income_between_60k_and_100k_M,, +Pre-driving-age child who is too young for school interaction with income more than $100k,(ptype == 8) & (income >= 100000),coef_pre_driving_age_child_who_is_too_young_for_school_interaction_with_income_more_than_100k_M,, +#,,,, +Uinversity Student interaction with peak accessibility to all employment,(ptype == 3) * SchoolLocationLogsum,coef_university_student_interaction_with_school_location_mc_logsum_M,, +Full-time Worker interaction with accessibility to retail,"@np.where((df.ptype == 1)*(df.autosdf.num_workers),df.nonmandatory_hov2_accessibility,0)",,coef_full_time_worker_interaction_with_retail_accessibility_N, +Non-working adult interaction with accessibility to retail,"@np.where((df.ptype == 4)*(df.autosdf.num_workers),df.nonmandatory_hov2_accessibility,0)",,coef_non_working_adult_interaction_with_retail_accessibility_N, +Driving-age child who is in school interaction with accessibility to retail,"@np.where((df.ptype == 6)*(df.autosdf.num_workers),df.nonmandatory_hov2_accessibility,0)",,coef_driving_age_child_who_is_in_school_interaction_with_retail_accessibility_N, +#,,,, +Full-time worker interaction with usual work location is home,(ptype==1)&(WorkLocation==99999),coef_full_time_worker_interaction_with_usual_work_location_is_home_M,coef_full_time_worker_interaction_with_usual_work_location_is_home_N, +Part-time worker interaction with usual work location is home,(ptype==2)&(WorkLocation==99999),coef_part_time_worker_interaction_with_usual_work_location_is_home_M,, +Full-time worker interaction with no usual work location,(ptype==1)&((WorkLocation==99999)|(WorkLocation<=0)),coef_full_time_worker_interaction_with_no_usual_work_location_M,, +Part-time worker interaction with no usual work location,(ptype==2)&((WorkLocation==99999)|(WorkLocation<=0)),coef_part_time_worker_interaction_with_no_usual_work_location_M,, +#,,,, +Full-time worker interaction with detached house,(ptype==1)&(building_size<3),,,coef_full_time_worker_interaction_with_detached_home_H +Part-time worker interaction with detached house,(ptype==2)&(building_size<3),,,coef_part_time_worker_interaction_with_detached_home_H +Retired interaction with detached house,(ptype==5)&(building_size<3),,,coef_retired_interaction_with_detached_home_H +Pre-driving-age child in School interaction with detached house,(ptype==6)&(building_size<3),,,coef_driving_age_child_who_is_in_school_interaction_with_detached_home_H +#,,,, +Mandatory pattern unavailable for retired person,ptype==5,coef_UNAVAILABLE,, +Mandatory pattern unavailable for nonworking adult person type,ptype==4,coef_UNAVAILABLE,, +#,,,, +Alternative Specific Constant Adjustment for Full-time worker,ptype == 1,coef_full_time_worker_asc_adjustment_M,coef_full_time_worker_asc_adjustment_N, +Alternative Specific Constant Adjustment for Part-time worker,ptype == 2,coef_part_time_worker_asc_adjustment_M,coef_part_time_worker_asc_adjustment_N, +Alternative Specific Constant Adjustment for University student,ptype == 3,coef_university_student_asc_adjustment_M,coef_university_student_asc_adjustment_N, +Alternative Specific Constant Adjustment for Non-working adult,ptype == 4,,coef_non_working_adult_asc_adjustment_N, +Alternative Specific Constant Adjustment for Retired,ptype == 5,,coef_retired_asc_adjustment_N, +Alternative Specific Constant Adjustment for Driving-age child who is in school,ptype == 6,coef_driving_age_child_who_is_in_school_asc_adjustment_M,coef_driving_age_child_who_is_in_school_asc_adjustment_N, +Alternative Specific Constant Adjustment for Pre-driving-age child who is in school,ptype == 7,coef_pre_driving_age_child_who_is_in_school_asc_adjustment_M,coef_pre_driving_age_child_who_is_in_school_asc_adjustment_N, +Alternative Specific Constant Adjustment for Pre-driving-age child who is too young for school,ptype == 8,coef_pre_driving_age_child_who_is_too_young_for_school_asc_adjustment_M,coef_pre_driving_age_child_who_is_too_young_for_school_asc_adjustment_N, +ASC Adjustment for Part-time worker -- TM2 calibration,ptype == 2,coef_part_time_worker_asc_adjustment_tm2_calib_M,coef_part_time_worker_asc_adjustment_tm2_calib_N, +ASC Adjustment for University student -- TM2 calibration,ptype == 3,coef_university_student_asc_adjustment_tm2_calib_M,coef_university_student_asc_adjustment_tm2_calib_N, +ASC Adjustment for Non-working adult -- TM2 calibration,ptype == 4,coef_non_working_adult_asc_adjustment_tm2_calib_M,coef_non_working_adult_asc_adjustment_tm2_calib_N, +ASC Adjustment for Retired --TM2 calibration,ptype == 5,coef_retired_asc_adjustment_tm2_calib_M,coef_retired_asc_adjustment_tm2_calib_N, diff --git a/test/cdap/configs/cdap_interaction_coefficients.csv b/test/cdap/configs/cdap_interaction_coefficients.csv new file mode 100644 index 000000000..f94fa1723 --- /dev/null +++ b/test/cdap/configs/cdap_interaction_coefficients.csv @@ -0,0 +1,177 @@ +activity,interaction_ptypes,coefficient +# 2-way interactions,, +H,11,coef_H_11 +H,12,coef_H_12 +H,13,coef_H_13 +H,14,coef_H_14 +H,15,coef_H_15 +H,16,coef_H_16 +H,17,coef_H_17 +H,18,coef_H_18 +H,22,coef_H_22 +H,23,coef_H_23 +H,24,coef_H_24 +H,25,coef_H_25 +H,26,coef_H_26 +H,27,coef_H_27 +H,28,coef_H_28 +H,33,coef_H_33 +H,34,coef_H_34 +H,35,coef_H_35 +H,36,coef_H_36 +H,37,coef_H_37 +H,38,coef_H_38 +H,44,coef_H_44 +H,45,coef_H_45 +H,46,coef_H_46 +H,47,coef_H_47 +H,48,coef_H_48 +H,55,coef_H_55 +H,56,coef_H_56_57 +H,57,coef_H_56_57 +H,58,coef_H_58 +H,66,coef_H_66 +H,67,coef_H_67 +H,68,coef_H_68 +H,77,coef_H_77 +H,78,coef_H_78 +H,88,coef_H_88 +M,11,coef_M_11 +M,12,coef_M_12 +M,13,coef_M_13 +M,16,coef_M_16 +M,17,coef_M_17 +M,18,coef_M_18 +M,22,coef_M_22 +M,23,coef_M_23 +M,26,coef_M_26 +M,27,coef_M_27 +M,28,coef_M_28 +M,33,coef_M_33 +M,36,coef_M_36 +M,37,coef_M_37 +M,38,coef_M_38 +M,66,coef_M_66 +M,67,coef_M_67 +M,68,coef_M_68 +M,77,coef_M_77 +M,78,coef_M_78 +M,88,coef_M_88 +N,11,coef_N_11 +N,12,coef_N_12 +N,13,coef_N_13 +N,14,coef_N_14 +N,15,coef_N_15 +N,16,coef_N_16 +N,17,coef_N_17 +N,18,coef_N_18 +N,22,coef_N_22 +N,23,coef_N_23 +N,24,coef_N_24 +N,25,coef_N_25 +N,26,coef_N_26 +N,27,coef_N_27 +N,28,coef_N_28 +N,33,coef_N_33 +N,34,coef_N_34 +N,35,coef_N_35 +N,36,coef_N_36 +N,37,coef_N_37 +N,38,coef_N_38 +N,44,coef_N_44 +N,45,coef_N_45 +N,46,coef_N_46 +N,47,coef_N_47 +N,48,coef_N_48 +N,55,coef_N_55 +N,56,coef_N_56_57_58 +N,57,coef_N_56_57_58 +N,58,coef_N_56_57_58 +N,66,coef_N_66 +N,67,coef_N_67 +N,68,coef_N_68 +N,77,coef_N_77 +N,78,coef_N_78 +N,88,coef_N_88 +# 3-way interactions,, +H,114,coef_H_114 +H,117,coef_H_117_118 +H,118,coef_H_117_118 +H,127,coef_H_127_128 +H,128,coef_H_127_128 +H,147,coef_H_147_148 +H,148,coef_H_147_148 +H,177,coef_H_177_178_187_188 +H,178,coef_H_177_178_187_188 +H,187,coef_H_177_178_187_188 +H,188,coef_H_177_178_187_188 +H,277,coef_H_277_278_287_288 +H,278,coef_H_277_278_287_288 +H,287,coef_H_277_278_287_288 +H,288,coef_H_277_278_287_288 +H,447,coef_H_447_448 +H,448,coef_H_447_448 +H,477,coef_H_477_478_487_488 +H,478,coef_H_477_478_487_488 +H,487,coef_H_477_478_487_488 +H,488,coef_H_477_478_487_488 +H,777,coef_H_777_778_788_888 +H,778,coef_H_777_778_788_888 +H,788,coef_H_777_778_788_888 +H,888,coef_H_777_778_788_888 +M,111,coef_M_111 +M,112,coef_M_112 +M,122,coef_M_122 +M,127,coef_M_127_128 +M,128,coef_M_127_128 +M,177,coef_M_177_178_187_188 +M,178,coef_M_177_178_187_188 +M,187,coef_M_177_178_187_188 +M,188,coef_M_177_178_187_188 +M,227,coef_M_227_228 +M,228,coef_M_227_228 +M,277,coef_M_277_278_287_288 +M,278,coef_M_277_278_287_288 +M,287,coef_M_277_278_287_288 +M,288,coef_M_277_278_287_288 +M,777,coef_M_777_778_788_888 +M,778,coef_M_777_778_788_888 +M,788,coef_M_777_778_788_888 +M,888,coef_M_777_778_788_888 +N,117,coef_N_117_118 +N,118,coef_N_117_118 +N,144,coef_N_144 +N,127,coef_N_127_128 +N,128,coef_N_127_128 +N,147,coef_N_147_148 +N,148,coef_N_147_148 +N,177,coef_N_177_178_187_188 +N,178,coef_N_177_178_187_188 +N,187,coef_N_177_178_187_188 +N,188,coef_N_177_178_187_188 +N,222,coef_N_222 +N,277,coef_N_277_278_287_288 +N,278,coef_N_277_278_287_288 +N,287,coef_N_277_278_287_288 +N,288,coef_N_277_278_287_288 +N,477,coef_N_477_478_487_488 +N,478,coef_N_477_478_487_488 +N,487,coef_N_477_478_487_488 +N,488,coef_N_477_478_487_488 +N,777,coef_N_777_778_788_888 +N,778,coef_N_777_778_788_888 +N,788,coef_N_777_778_788_888 +N,888,coef_N_777_778_788_888 +# cdap_final_rules,, +M,5,coef_UNAVAILABLE +M,4,coef_UNAVAILABLE +# cdap_all_people,, +M,***,coef_M_xxx +N,***,coef_N_xxx +H,***,coef_H_xxx +M,****,coef_M_xxxx +N,****,coef_N_xxxx +H,****,coef_H_xxxx +M,*****,coef_M_xxxxx +N,*****,coef_N_xxxxx +H,*****,coef_H_xxxxx diff --git a/test/cdap/configs/cdap_joint_tour_coefficients.csv b/test/cdap/configs/cdap_joint_tour_coefficients.csv new file mode 100644 index 000000000..14ee3fee3 --- /dev/null +++ b/test/cdap/configs/cdap_joint_tour_coefficients.csv @@ -0,0 +1,22 @@ +Label,description,Expression,dependency,coefficient +,constant - joint tour,1,,-3.1506 +,joint tour for hhsize 2,hhsize==2,,0.331420519 +,joint tour for hhsize 3,hhsize==3,,0.360848095 +,joint tour for hhsize 4,hhsize==4,,-0.118640717 +,joint tour for hhsize 5+,hhsize>=5,,-0.053509306 +,person x is adult and DAP is M,ptype_px<7,M_px,0.008 +,person x is adult and DAP is N,ptype_px<7,N_px,1.2557 +,person x is kid and DAP is M,ptype_px>6,M_px,0.1088 +,person x is kid and DAP is N,ptype_px>6,N_px,1.6898 +,Accessibility to retail employment/Non-Mandatory Attractions for Joint Tour,(autos_p1num_workers_p1)*nonmandatory_hov2_accessibility_p1,,0.055031985 +,Income less than $30k,income_p1<30000,,-0.192506367 +,Income between $60k and $100k,(income_p1>=60000)&(income_p1<=100000),,0.104325349 +,Income more than $100k,income_p1>100000,,0.104325349 +,No Car Households,autos_p1==0,,0 +,Cars Less than Workers,autos_p1num_workers_p1,,-0.005896499 +,Constant - Joint Tour - MTC TM2 Calibration,1,,-0.5918 +,WorkAccessForMandatoryDap,WorkLocationLogsum_px,M_px,0.17217579 +,If All Adults stay at Home/ None of the Adults have Dap 1 or 2,ptype_pxprod<7|ptype_pxprod>6,H_px,-0.988838929 diff --git a/test/cdap/configs/constants.yaml b/test/cdap/configs/constants.yaml new file mode 100644 index 000000000..b0bd5a1f3 --- /dev/null +++ b/test/cdap/configs/constants.yaml @@ -0,0 +1,68 @@ +## ActivitySim +## See full license in LICENSE.txt. + + +#HHT_NONE: 0 +#HHT_FAMILY_MARRIED: 1 +#HHT_FAMILY_MALE: 2 +#HHT_FAMILY_FEMALE: 3 +#HHT_NONFAMILY_MALE_ALONE: 4 +#HHT_NONFAMILY_MALE_NOTALONE: 5 +#HHT_NONFAMILY_FEMALE_ALONE: 6 +#HHT_NONFAMILY_FEMALE_NOTALONE: 7 + +# convenience for expression files +HHT_NONFAMILY: [4, 5, 6, 7] +HHT_FAMILY: [1, 2, 3] + +PSTUDENT_GRADE_OR_HIGH: 1 +PSTUDENT_UNIVERSITY: 2 +PSTUDENT_NOT: 3 + +GRADE_SCHOOL_MAX_AGE: 14 +GRADE_SCHOOL_MIN_AGE: 5 + +SCHOOL_SEGMENT_NONE: 0 +SCHOOL_SEGMENT_GRADE: 1 +SCHOOL_SEGMENT_HIGH: 2 +SCHOOL_SEGMENT_UNIV: 3 + +INCOME_SEGMENT_LOW: 1 +INCOME_SEGMENT_MED: 2 +INCOME_SEGMENT_HIGH: 3 +INCOME_SEGMENT_VERYHIGH: 4 + +PEMPLOY_FULL: 1 +PEMPLOY_PART: 2 +PEMPLOY_NOT: 3 +PEMPLOY_CHILD: 4 + +PTYPE_FULL: &ptype_full 1 +PTYPE_PART: &ptype_part 2 +PTYPE_UNIVERSITY: &ptype_university 3 +PTYPE_NONWORK: &ptype_nonwork 4 +PTYPE_RETIRED: &ptype_retired 5 +PTYPE_DRIVING: &ptype_driving 6 +PTYPE_SCHOOL: &ptype_school 7 +PTYPE_PRESCHOOL: &ptype_preschool 8 + +# these appear as column headers in non_mandatory_tour_frequency.csv +PTYPE_NAME: + *ptype_full: PTYPE_FULL + *ptype_part: PTYPE_PART + *ptype_university: PTYPE_UNIVERSITY + *ptype_nonwork: PTYPE_NONWORK + *ptype_retired: PTYPE_RETIRED + *ptype_driving: PTYPE_DRIVING + *ptype_school: PTYPE_SCHOOL + *ptype_preschool: PTYPE_PRESCHOOL + + +CDAP_ACTIVITY_MANDATORY: M +CDAP_ACTIVITY_NONMANDATORY: N +CDAP_ACTIVITY_HOME: H + +# Correction for transit skim expressions +# e.g. MTC transit skims (Cube TRANPLAN skims) use scaled ints and +# therefore need to be divided by the scale factor if used in expressions +TRANSIT_SCALE_FACTOR: 100 diff --git a/test/cdap/configs/initialize_households.yaml b/test/cdap/configs/initialize_households.yaml new file mode 100644 index 000000000..5d98a703d --- /dev/null +++ b/test/cdap/configs/initialize_households.yaml @@ -0,0 +1,37 @@ +annotate_tables: + - tablename: persons + column_map: + HHID: household_id + PERID: person_id + AGEP: age + SEX: sex + SCHL: education_attainment + OCCP: occupation + WKHP: hours_worked + WKW: weeks_worked + EMPLOYED: employment_status + ESR: esr + SCHG: grade_attending + annotate: + SPEC: annotate_persons + DF: persons + TABLES: + - households + - tablename: households + column_map: + HHID: household_id + MAZ: home_zone_id + HHINCADJ: income + NWRKRS_ESR: num_workers + VEH: auto_ownership + NP: hhsize + HHT: hh_type + BLD: building_size + TYPE: hh_unit_type + MTCCountyID: county_id + annotate: + SPEC: annotate_households + DF: households + TABLES: + - persons + - land_use \ No newline at end of file diff --git a/test/cdap/configs/initialize_landuse.yaml b/test/cdap/configs/initialize_landuse.yaml new file mode 100644 index 000000000..7cc1d7e34 --- /dev/null +++ b/test/cdap/configs/initialize_landuse.yaml @@ -0,0 +1,54 @@ +annotate_tables: + - tablename: land_use + column_map: + MAZ_ORIGINAL: zone_id + CountyID: county_id + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + annotate: + SPEC: annotate_landuse + DF: land_use + - tablename: accessibility + column_map: + column_1: nonmandatory_auto_accessibility + column_2: nonmandatory_transit_accessibility + column_3: nonmandatory_nm_accessibility + column_4: nonmandatory_sov0_accessibility + column_5: nonmandatory_sov1_accessibility + column_6: nonmandatory_sov2_accessibility + column_7: nonmandatory_hov0_accessibility + column_8: nonmandatory_hov1_accessibility + column_9: nonmandatory_hov2_accessibility + column_10: shop_hov_insufficient_accessibility + column_11: shop_hov_sufficient_accessibility + column_12: shop_hov_oversufficient_accessibility + column_13: maint_hov_insufficient_accessibility + column_14: maint_hov_sufficient_accessibility + column_15: maint_hov_oversufficient_accessibility + column_16: eat_hov_insufficient_accessibility + column_17: eat_hov_sufficient_accessibility + column_18: eat_hov_oversufficient_accessibility + column_19: visit_hov_insufficient_accessibility + column_20: visit_hov_sufficient_accessibility + column_21: visit_hov_oversufficient_accessibility + column_22: discr_hov_insufficient_accessibility + column_23: discr_hov_sufficient_accessibility + column_24: discr_hov_oversufficient_accessibility + column_25: escort_hov_insufficient_accessibility + column_26: escort_hov_sufficient_accessibility + column_27: escort_hov_oversufficient_accessibility + column_28: shop_sov_insufficient_accessibility + column_29: shop_sov_sufficient_accessibility + column_30: shop_sov_oversufficient_accessibility + column_31: maint_sov_insufficient_accessibility + column_32: maint_sov_sufficient_accessibility + column_33: maint_sov_oversufficient_accessibility + column_40: discr_sov_insufficient_accessibility + column_41: discr_sov_sufficient_accessibility + column_42: discr_sov_oversufficient_accessibility + column_45: total_emp_accessibility + column_47: hh_walktransit_accessibility + mgra : zone_id \ No newline at end of file diff --git a/test/cdap/configs/network_los.yaml b/test/cdap/configs/network_los.yaml new file mode 100644 index 000000000..391125a38 --- /dev/null +++ b/test/cdap/configs/network_los.yaml @@ -0,0 +1,14 @@ +# read cached skims (using numpy memmap) from output directory (memmap is faster than omx ) +read_skim_cache: False +# write memmapped cached skims to output directory after reading from omx, for use in subsequent runs +write_skim_cache: True + +zone_system: 1 + +taz_skims: skims.omx + +skim_time_periods: + time_window: 1440 + period_minutes: 60 + periods: [0, 3, 5, 9, 14, 18, 24] # 3=3:00-3:59, 5=5:00-5:59, 9=9:00-9:59, 14=2:00-2:59, 18=6:00-6:59 + labels: ['EA', 'EA', 'AM', 'MD', 'PM', 'EV'] \ No newline at end of file diff --git a/test/cdap/configs/settings.yaml b/test/cdap/configs/settings.yaml new file mode 100644 index 000000000..bd0f4acc9 --- /dev/null +++ b/test/cdap/configs/settings.yaml @@ -0,0 +1,60 @@ +# input tables +input_table_list: + - tablename: households + filename: households.csv + index_col: household_id + rename_columns: + unique_hh_id: household_id + NP: hhsize + hh_workers_from_esr: num_workers + VEH: auto_ownership + MAZ: home_zone_id + HINCP: income + keep_columns: + - home_zone_id + - income + - hhsize + - HHT + - auto_ownership + - num_workers + - tablename: persons + filename: persons.csv + index_col: person_id + rename_columns: + unique_hh_id: household_id + AGEP: age + SPORDER: PNUM + SEX: sex + employed: pemploy + student_status: pstudent + person_type: ptype + keep_columns: + - household_id + - age + - PNUM + - sex + - pemploy + - pstudent + - ptype + - tablename: land_use + filename: land_use.csv + index_col: zone_id + rename_columns: + MAZ_ORIGINAL: zone_id + CountyID: county_id + TAZ_ORIGINAL: TAZ + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + keep_columns: + - TAZ + - DISTRICT + - SD + - county_id + - TOTHH + - TOTPOP + - TOTACRE + +trace_hh_id: 2 \ No newline at end of file diff --git a/test/cdap/configs/tour_departure_and_duration_alternatives.csv b/test/cdap/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 000000000..bddab06b9 --- /dev/null +++ b/test/cdap/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/test/cdap/data/.gitkeep b/test/cdap/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/cdap/test_cdap.py b/test/cdap/test_cdap.py new file mode 100644 index 000000000..df74740b4 --- /dev/null +++ b/test/cdap/test_cdap.py @@ -0,0 +1,413 @@ +import logging +import pytest +import os +import shutil +import pandas as pd +import numpy as np +from numpy import dot +from numpy.linalg import norm + +# import models is necessary to initalize the model steps with orca +from activitysim.abm import models +from activitysim.core import pipeline, config +from activitysim.core import tracing + +logger = logging.getLogger(__name__) + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def module() -> str: + """ + A pytest fixture that returns the data folder location. + :return: folder location for any necessary data to initialize the tests + """ + return "cdap" + + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def tables(prepare_module_inputs) -> dict[str, str]: + """ + A pytest fixture that returns the "mock" tables to build pipeline dataframes. The + key-value pair is the name of the table and the index column. + :return: dict + """ + return { + "land_use": "MAZ_ORIGINAL", + "persons": "person_id", + "households": "household_id", + "accessibility": "MAZ_ORIGINAL", + } + + +# Used by conftest.py initialize_pipeline method +# Set to true if you need to read skims into the pipeline +@pytest.fixture(scope="module") +def initialize_network_los() -> bool: + """ + A pytest boolean fixture indicating whether network skims should be read from the + fixtures test data folder. + :return: bool + """ + return False + + +@pytest.fixture(scope="module") +def load_checkpoint() -> bool: + """ + checkpoint to be loaded from the pipeline when reconnecting. + """ + return "initialize_households" + + +# make a reconnect_pipeline internal to cdap +@pytest.mark.skipif( + os.path.isfile("test/cdap/output/pipeline.h5"), + reason="no need to recreate pipeline store if alreayd exist", +) +def test_prepare_input_pipeline(initialize_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["initialize_landuse", "initialize_households"]) + + pipeline.close_pipeline() + + +def test_cdap_from_pipeline(reconnect_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["cdap_simulate"], resume_after="initialize_households") + + # get the updated pipeline data + person_df = pipeline.get_table("persons") + + # get the updated pipeline data + household_df = pipeline.get_table("households") + + ############################ + # person cdap pattern validation + ############################ + # cdap person result from the model + logger.info("person cdap pattern validation") + + target_key = "activity_pattern" + simulated_key = "cdap_activity" + similarity_threshold = 0.99 + + simulated_df = create_summary( + person_df, key=simulated_key, out_col="Simulated_Share" + ) + + # cdap person result from the TM2 run + target_df = create_summary(person_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + ############################ + # household joint pattern validation + ############################ + # cdap household result from the model + logger.info("household joint vs non-joint tour validation") + + target_key = "has_joint_tour_tm2" + simulated_key = "has_joint_tour" + similarity_threshold = 0.99 + + simulated_df = create_summary( + household_df, key=simulated_key, out_col="Simulated_Share" + ) + + # cdap household result from the TM2 run + household_df["has_joint_tour_tm2"] = np.where( + household_df["cdap_pattern"].str.endswith("j"), 1, 0 + ) + target_df = create_summary(household_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + ############################ + # one person household cdap pattern validation + ############################ + # cdap household result from the model + logger.info("one-person household cdap pattern validation") + + target_key = "cdap_pattern" + simulated_key = "cdap_activity" + similarity_threshold = 0.99 + + household_df["cdap_pattern"] = household_df["cdap_pattern"].apply( + lambda x: x[:-1].upper() if x.endswith("0") else x.upper() + ) + household_df["cdap_activity"] = household_df.apply( + lambda x: x["cdap_activity"] + "J" + if x["has_joint_tour"] == 1 + else x["cdap_activity"], + axis=1, + ) + + hh1_df = household_df[household_df.hhsize == 1].copy() + + simulated_df = create_summary(hh1_df, key=simulated_key, out_col="Simulated_Share") + target_df = create_summary(hh1_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + ############################ + # two person household cdap pattern validation + ############################ + # cdap household result from the model + logger.info("two-person household cdap pattern validation") + + target_key = "cdap_pattern" + simulated_key = "cdap_activity" + similarity_threshold = 0.99 + + hh2_df = household_df[household_df.hhsize == 2].copy() + + simulated_df = create_summary(hh2_df, key=simulated_key, out_col="Simulated_Share") + target_df = create_summary(hh2_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + ############################ + # three person household cdap pattern validation + ############################ + # cdap household result from the model + logger.info("three-person household cdap pattern validation") + + target_key = "cdap_pattern" + simulated_key = "cdap_activity" + similarity_threshold = 0.99 + + hh3_df = household_df[household_df.hhsize == 3].copy() + + simulated_df = create_summary(hh3_df, key=simulated_key, out_col="Simulated_Share") + target_df = create_summary(hh3_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + +# fetch/prepare existing files for model inputs +# e.g. read accessibilities.csv from ctramp result, rename columns, write out to accessibility.csv which is the input to activitysim +@pytest.fixture(scope="module") +def prepare_module_inputs() -> None: + """ + copy input files from sharepoint into test folder + + create unique person id in person file + + :return: None + """ + # https://wsponlinenam.sharepoint.com/sites/US-TM2ConversionProject/Shared%20Documents/Forms/ + # AllItems.aspx?id=%2Fsites%2FUS%2DTM2ConversionProject%2FShared%20Documents%2FTask%203%20ActivitySim&viewid=7a1eaca7%2D3999%2D4d45%2D9701%2D9943cc3d6ab1 + accessibility_file = os.path.join( + "test", "cdap", "data", "tm2_outputs", "accessibilities.csv" + ) + household_file = os.path.join("test", "cdap", "data", "popsyn", "households.csv") + person_file = os.path.join("test", "cdap", "data", "popsyn", "persons.csv") + landuse_file = os.path.join( + "test", "cdap", "data", "landuse", "maz_data_withDensity.csv" + ) + + test_dir = os.path.join("test", "cdap", "data") + + shutil.copy(accessibility_file, os.path.join(test_dir, "accessibility.csv")) + shutil.copy(household_file, os.path.join(test_dir, "households.csv")) + shutil.copy(person_file, os.path.join(test_dir, "persons.csv")) + shutil.copy(landuse_file, os.path.join(test_dir, "land_use.csv")) + + # add original maz id to accessibility table + land_use_df = pd.read_csv(os.path.join(test_dir, "land_use.csv")) + accessibility_df = pd.read_csv(os.path.join(test_dir, "accessibility.csv")) + + accessibility_df = pd.merge( + accessibility_df, + land_use_df[["MAZ", "MAZ_ORIGINAL"]].rename(columns={"MAZ": "mgra"}), + how="left", + on="mgra", + ) + + accessibility_df.to_csv(os.path.join(test_dir, "accessibility.csv"), index=False) + + # currently household file has to have these two columns, even before annotation + # because annotate person happens before household and uses these two columns + # TODO find a way to get around this + #### + household_df = pd.read_csv(os.path.join(test_dir, "households.csv")) + + household_columns_dict = {"HHID": "household_id", "MAZ": "home_zone_id"} + + household_df.rename(columns=household_columns_dict, inplace=True) + + tm2_simulated_household_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "householdData_3.csv") + ) + tm2_simulated_household_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + household_df = pd.merge( + household_df, + tm2_simulated_household_df[ + [ + "household_id", + "autos", + "automated_vehicles", + "transponder", + "cdap_pattern", + "jtf_choice", + ] + ], + how="inner", # tm2 is not 100% sample run + on="household_id", + ) + + household_df.to_csv(os.path.join(test_dir, "households.csv"), index=False) + + person_df = pd.read_csv(os.path.join(test_dir, "persons.csv")) + + person_columns_dict = {"HHID": "household_id", "PERID": "person_id"} + + person_df.rename(columns=person_columns_dict, inplace=True) + + tm2_simulated_person_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "personData_3.csv") + ) + tm2_simulated_person_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + person_df = pd.merge( + person_df, + tm2_simulated_person_df[ + [ + "household_id", + "person_id", + "type", + "value_of_time", + "activity_pattern", + "imf_choice", + "inmf_choice", + "fp_choice", + "reimb_pct", + "workDCLogsum", + "schoolDCLogsum", + ] + ], + how="inner", # tm2 is not 100% sample run + on=["household_id", "person_id"], + ) + + # get tm2 simulated workplace and school location results + tm2_simulated_wsloc_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "wsLocResults_3.csv") + ) + tm2_simulated_wsloc_df.rename( + columns={"HHID": "household_id", "PersonID": "person_id"}, inplace=True + ) + + person_df = pd.merge( + person_df, + tm2_simulated_wsloc_df[ + [ + "household_id", + "person_id", + "WorkLocation", + "WorkLocationLogsum", # this is the same as `workDCLogsum` in tm2 person output + "SchoolLocation", + "SchoolLocationLogsum", # this is the same as `schoolDCLogsum` in tm2 person output + ] + ], + how="inner", # ctramp might not be 100% sample run + on=["household_id", "person_id"], + ) + + person_df.to_csv(os.path.join(test_dir, "persons.csv"), index=False) + #### + + +def create_summary(input_df, key, out_col="Share") -> pd.DataFrame: + """ + Create summary for the input data. + 1. group input data by the "key" column + 2. calculate the percent of input data records in each "key" category. + + :return: pd.DataFrame + """ + + out_df = input_df.groupby(key).size().reset_index(name="Count") + out_df[out_col] = round(out_df["Count"] / out_df["Count"].sum(), 4) + + return out_df[[key, out_col]] + + +def cosine_similarity(a, b): + """ + Computes cosine similarity between two vectors. + + Cosine similarity is used here as a metric to measure similarity between two sequence of numbers. + Two sequence of numbers are represented as vectors (in a multi-dimensional space) and cosine similiarity is defined as the cosine of the angle between them + i.e., dot products of the vectors divided by the product of their lengths. + + :return: + """ + + return dot(a, b) / (norm(a) * norm(b)) + + +def compare_simulated_against_target( + target_df: pd.DataFrame, + simulated_df: pd.DataFrame, + target_key: str, + simulated_key: str, +) -> bool: + """ + compares the simulated and target results by computing the cosine similarity between them. + + :return: + """ + + merged_df = pd.merge( + target_df, simulated_df, left_on=target_key, right_on=simulated_key, how="outer" + ) + merged_df = merged_df.fillna(0) + + logger.info("simulated vs target share:\n%s" % merged_df) + + similarity_value = cosine_similarity( + merged_df["Target_Share"].tolist(), merged_df["Simulated_Share"].tolist() + ) + + logger.info("cosine similarity:\n%s" % similarity_value) + + return similarity_value diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 000000000..7d8b33203 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,105 @@ +import os + +import orca +import pandas as pd +import pytest +from activitysim.core import pipeline +from activitysim.core.los import Network_LOS as los + + +@pytest.fixture(scope="module") +def initialize_pipeline( + module: str, tables: dict[str, str], initialize_network_los: bool +) -> pipeline.Pipeline: + test_dir = os.path.join("test", module) + configs_dir = os.path.join(test_dir, "configs") + data_dir = os.path.join(test_dir, "data") + output_dir = os.path.join(test_dir, "output") + + if os.path.isdir(configs_dir): + orca.add_injectable("configs_dir", configs_dir) + + if os.path.isdir(data_dir): + orca.add_injectable("data_dir", data_dir) + + if os.path.isdir(test_dir): + if not os.path.isdir(output_dir): + os.mkdir(output_dir) + orca.add_injectable("output_dir", output_dir) + + # Read in the input test dataframes + for dataframe_name, idx_name in tables.items(): + df = pd.read_csv( + os.path.join("test", module, "data", f"{dataframe_name}.csv"), + index_col=idx_name, + ) + orca.add_table(dataframe_name, df) + + if initialize_network_los: + net_los = los() + net_los.load_data() + orca.add_injectable("network_los", net_los) + + # Add an output directory in current working directory if it's not already there + try: + os.makedirs("output") + except FileExistsError: + # directory already exists + pass + + # Add the dataframes to the pipeline + pipeline.open_pipeline() + pipeline.add_checkpoint(module) + pipeline.close_pipeline() + + # By convention, this method needs to yield something + yield pipeline._PIPELINE + + if pipeline.is_open(): + pipeline.close_pipeline() + + +@pytest.fixture(scope="module") +def reconnect_pipeline( + module: str, initialize_network_los: bool, load_checkpoint: str +) -> pipeline.Pipeline: + test_dir = os.path.join("test", module) + configs_dir = os.path.join(test_dir, "configs") + data_dir = os.path.join(test_dir, "data") + output_dir = os.path.join(test_dir, "output") + + if os.path.isdir(configs_dir): + orca.add_injectable("configs_dir", configs_dir) + + if os.path.isdir(data_dir): + orca.add_injectable("data_dir", data_dir) + + if os.path.isdir(test_dir): + if not os.path.isdir(output_dir): + os.mkdir(output_dir) + orca.add_injectable("output_dir", output_dir) + + # Read in the existing pipeline + orca.add_injectable("pipeline_file_path", output_dir) + + if initialize_network_los: + net_los = los() + net_los.load_data() + orca.add_injectable("network_los", net_los) + + # Add an output directory in current working directory if it's not already there + try: + os.makedirs("output") + except FileExistsError: + # directory already exists + pass + + pipeline.open_pipeline(resume_after=load_checkpoint) + pipeline.add_checkpoint(module) + pipeline.close_pipeline() + # By convention, this method needs to yield something + yield pipeline._PIPELINE + + # pytest teardown code + if pipeline.is_open(): + pipeline.close_pipeline() diff --git a/test/joint_tour_frequency/.gitkeep b/test/joint_tour_frequency/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/joint_tours/.gitkeep b/test/joint_tours/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/joint_tours/configs/JointTourFrequency.xls b/test/joint_tours/configs/JointTourFrequency.xls new file mode 100644 index 000000000..2eb7699bb Binary files /dev/null and b/test/joint_tours/configs/JointTourFrequency.xls differ diff --git a/test/joint_tours/configs/annotate_households.csv b/test/joint_tours/configs/annotate_households.csv new file mode 100644 index 000000000..eead2858c --- /dev/null +++ b/test/joint_tours/configs/annotate_households.csv @@ -0,0 +1,19 @@ +Description,Target,Expression +#,, annotate households table after import +,_PERSON_COUNT,"lambda query, persons, households: persons.query(query).groupby('household_id').size().reindex(households.index).fillna(0).astype(np.int8)" +num_adults,num_adults,"_PERSON_COUNT('adult', persons, households)" +num_children,num_children,"_PERSON_COUNT('~adult', persons, households)" +num_travel_active,num_travel_active,persons.travel_active.astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active_preschoolers,num_travel_active_preschoolers,((persons.ptype == PTYPE_PRESCHOOL) & persons.travel_active).astype(int).groupby(persons.household_id).sum().reindex(households.index).fillna(0).astype(np.int8) +num_travel_active_non_preschoolers,num_travel_active_non_preschoolers,num_travel_active - num_travel_active_preschoolers +participates_in_jtf_model,participates_in_jtf_model,(num_travel_active > 1) & (num_travel_active_non_preschoolers > 0) +number of travel active fulltime workers,num_travel_active_full_time_workers,"_PERSON_COUNT('(ptype == 1) & (cdap_activity != \'H\')', persons, households)" +number of travel active parttime workers,num_travel_active_part_time_workers,"_PERSON_COUNT('(ptype == 2) & (cdap_activity != \'H\')', persons, households)" +number of travel active university student,num_travel_active_university_students,"_PERSON_COUNT('(ptype == 3) & (cdap_activity != \'H\')', persons, households)" +number of travel active non-workers,num_travel_active_non_workers,"_PERSON_COUNT('(ptype == 4) & (cdap_activity != \'H\')', persons, households)" +number of travel active retirees,num_travel_active_retirees,"_PERSON_COUNT('(ptype == 5) & (cdap_activity != \'H\')', persons, households)" +number of travel active driving age students,num_travel_active_driving_age_students,"_PERSON_COUNT('(ptype == 6) & (cdap_activity != \'H\')', persons, households)" +number of travel active pre-driving age school kids,num_travel_active_pre_driving_age_school_kids,"_PERSON_COUNT('(ptype == 7) & (cdap_activity != \'H\')', persons, households)" +number of travel active pre-school kids,num_travel_active_pre_school_kids,"_PERSON_COUNT('(ptype == 8) & (cdap_activity != \'H\')', persons, households)" +number of travel active adults,num_travel_active_adults,"_PERSON_COUNT('adult & (cdap_activity != \'H\')', persons, households)" +number of travel active chilren,num_travel_active_children,"_PERSON_COUNT('~adult & (cdap_activity != \'H\')', persons, households)" \ No newline at end of file diff --git a/test/joint_tours/configs/annotate_landuse.csv b/test/joint_tours/configs/annotate_landuse.csv new file mode 100644 index 000000000..65237c0ad --- /dev/null +++ b/test/joint_tours/configs/annotate_landuse.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +#,, annotate landuse table after import +household_density,household_density,land_use.TOTHH / land_use.TOTACRE +employment_density,employment_density,land_use.TOTEMP / land_use.TOTACRE +population_density,population_density,land_use.TOTPOP / land_use.TOTACRE +density_index,density_index,(household_density *employment_density) / (household_density + employment_density).clip(lower=1) \ No newline at end of file diff --git a/test/joint_tours/configs/annotate_persons.csv b/test/joint_tours/configs/annotate_persons.csv new file mode 100644 index 000000000..6af8a61d7 --- /dev/null +++ b/test/joint_tours/configs/annotate_persons.csv @@ -0,0 +1,16 @@ +Description,Target,Expression +#,, annotate persons table after import +,ptype,0 +,ptype,"np.where(persons.type == 'Full-time worker', 1, ptype)" +,ptype,"np.where(persons.type == 'Part-time worker', 2, ptype)" +,ptype,"np.where(persons.type == 'University student', 3, ptype)" +,ptype,"np.where(persons.type == 'Non-worker', 4, ptype)" +,ptype,"np.where(persons.type == 'Retired', 5, ptype)" +,ptype,"np.where(persons.type == 'Student of driving age', 6, ptype)" +,ptype,"np.where(persons.type == 'Student of non-driving age', 7, ptype)" +,ptype,"np.where(persons.type == 'Child too young for school', 8, ptype)" +home_zone_id,home_zone_id,"reindex(households.home_zone_id, persons.household_id)" +travel_active,travel_active,persons.cdap_activity != CDAP_ACTIVITY_HOME +# adult is needed as it's harded coded in activitysim core overlap.py +adult,adult,ptype<=6 +child,child,ptype>6 \ No newline at end of file diff --git a/test/joint_tours/configs/annotate_persons_jtp.csv b/test/joint_tours/configs/annotate_persons_jtp.csv new file mode 100644 index 000000000..a72c86605 --- /dev/null +++ b/test/joint_tours/configs/annotate_persons_jtp.csv @@ -0,0 +1,3 @@ +Description,Target,Expression +#,, annotate persons table after joint_tour_participation model has run +num_joint_tours,num_joint_tours,"joint_tour_participants.groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8)" diff --git a/test/joint_tours/configs/annotate_tours.csv b/test/joint_tours/configs/annotate_tours.csv new file mode 100644 index 000000000..225abe7f8 --- /dev/null +++ b/test/joint_tours/configs/annotate_tours.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +,tour_category,tours.tour_category.str.lower() +,tour_purpose,tours.tour_purpose.str.lower() +,tour_type,tours.tour_purpose.str.lower() +,origin,tours.orig_mgra +,destination,tours.dest_mgra diff --git a/test/joint_tours/configs/constants.yaml b/test/joint_tours/configs/constants.yaml new file mode 100644 index 000000000..b0bd5a1f3 --- /dev/null +++ b/test/joint_tours/configs/constants.yaml @@ -0,0 +1,68 @@ +## ActivitySim +## See full license in LICENSE.txt. + + +#HHT_NONE: 0 +#HHT_FAMILY_MARRIED: 1 +#HHT_FAMILY_MALE: 2 +#HHT_FAMILY_FEMALE: 3 +#HHT_NONFAMILY_MALE_ALONE: 4 +#HHT_NONFAMILY_MALE_NOTALONE: 5 +#HHT_NONFAMILY_FEMALE_ALONE: 6 +#HHT_NONFAMILY_FEMALE_NOTALONE: 7 + +# convenience for expression files +HHT_NONFAMILY: [4, 5, 6, 7] +HHT_FAMILY: [1, 2, 3] + +PSTUDENT_GRADE_OR_HIGH: 1 +PSTUDENT_UNIVERSITY: 2 +PSTUDENT_NOT: 3 + +GRADE_SCHOOL_MAX_AGE: 14 +GRADE_SCHOOL_MIN_AGE: 5 + +SCHOOL_SEGMENT_NONE: 0 +SCHOOL_SEGMENT_GRADE: 1 +SCHOOL_SEGMENT_HIGH: 2 +SCHOOL_SEGMENT_UNIV: 3 + +INCOME_SEGMENT_LOW: 1 +INCOME_SEGMENT_MED: 2 +INCOME_SEGMENT_HIGH: 3 +INCOME_SEGMENT_VERYHIGH: 4 + +PEMPLOY_FULL: 1 +PEMPLOY_PART: 2 +PEMPLOY_NOT: 3 +PEMPLOY_CHILD: 4 + +PTYPE_FULL: &ptype_full 1 +PTYPE_PART: &ptype_part 2 +PTYPE_UNIVERSITY: &ptype_university 3 +PTYPE_NONWORK: &ptype_nonwork 4 +PTYPE_RETIRED: &ptype_retired 5 +PTYPE_DRIVING: &ptype_driving 6 +PTYPE_SCHOOL: &ptype_school 7 +PTYPE_PRESCHOOL: &ptype_preschool 8 + +# these appear as column headers in non_mandatory_tour_frequency.csv +PTYPE_NAME: + *ptype_full: PTYPE_FULL + *ptype_part: PTYPE_PART + *ptype_university: PTYPE_UNIVERSITY + *ptype_nonwork: PTYPE_NONWORK + *ptype_retired: PTYPE_RETIRED + *ptype_driving: PTYPE_DRIVING + *ptype_school: PTYPE_SCHOOL + *ptype_preschool: PTYPE_PRESCHOOL + + +CDAP_ACTIVITY_MANDATORY: M +CDAP_ACTIVITY_NONMANDATORY: N +CDAP_ACTIVITY_HOME: H + +# Correction for transit skim expressions +# e.g. MTC transit skims (Cube TRANPLAN skims) use scaled ints and +# therefore need to be divided by the scale factor if used in expressions +TRANSIT_SCALE_FACTOR: 100 diff --git a/test/joint_tours/configs/initialize_households.yaml b/test/joint_tours/configs/initialize_households.yaml new file mode 100644 index 000000000..a5cabc3df --- /dev/null +++ b/test/joint_tours/configs/initialize_households.yaml @@ -0,0 +1,38 @@ +annotate_tables: + - tablename: persons + column_map: + HHID: household_id + PERID: person_id + AGEP: age + SEX: sex + SCHL: education_attainment + OCCP: occupation + WKHP: hours_worked + WKW: weeks_worked + EMPLOYED: employment_status + ESR: esr + SCHG: grade_attending + activity_pattern: cdap_activity + annotate: + SPEC: annotate_persons + DF: persons + TABLES: + - households + - tablename: households + column_map: + HHID: household_id + MAZ: home_zone_id + HHINCADJ: income + NWRKRS_ESR: num_workers + VEH: auto_ownership + NP: hhsize + HHT: hh_type + BLD: building_size + TYPE: hh_unit_type + MTCCountyID: county_id + annotate: + SPEC: annotate_households + DF: households + TABLES: + - persons + - land_use \ No newline at end of file diff --git a/test/joint_tours/configs/initialize_landuse.yaml b/test/joint_tours/configs/initialize_landuse.yaml new file mode 100644 index 000000000..7cc1d7e34 --- /dev/null +++ b/test/joint_tours/configs/initialize_landuse.yaml @@ -0,0 +1,54 @@ +annotate_tables: + - tablename: land_use + column_map: + MAZ_ORIGINAL: zone_id + CountyID: county_id + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + annotate: + SPEC: annotate_landuse + DF: land_use + - tablename: accessibility + column_map: + column_1: nonmandatory_auto_accessibility + column_2: nonmandatory_transit_accessibility + column_3: nonmandatory_nm_accessibility + column_4: nonmandatory_sov0_accessibility + column_5: nonmandatory_sov1_accessibility + column_6: nonmandatory_sov2_accessibility + column_7: nonmandatory_hov0_accessibility + column_8: nonmandatory_hov1_accessibility + column_9: nonmandatory_hov2_accessibility + column_10: shop_hov_insufficient_accessibility + column_11: shop_hov_sufficient_accessibility + column_12: shop_hov_oversufficient_accessibility + column_13: maint_hov_insufficient_accessibility + column_14: maint_hov_sufficient_accessibility + column_15: maint_hov_oversufficient_accessibility + column_16: eat_hov_insufficient_accessibility + column_17: eat_hov_sufficient_accessibility + column_18: eat_hov_oversufficient_accessibility + column_19: visit_hov_insufficient_accessibility + column_20: visit_hov_sufficient_accessibility + column_21: visit_hov_oversufficient_accessibility + column_22: discr_hov_insufficient_accessibility + column_23: discr_hov_sufficient_accessibility + column_24: discr_hov_oversufficient_accessibility + column_25: escort_hov_insufficient_accessibility + column_26: escort_hov_sufficient_accessibility + column_27: escort_hov_oversufficient_accessibility + column_28: shop_sov_insufficient_accessibility + column_29: shop_sov_sufficient_accessibility + column_30: shop_sov_oversufficient_accessibility + column_31: maint_sov_insufficient_accessibility + column_32: maint_sov_sufficient_accessibility + column_33: maint_sov_oversufficient_accessibility + column_40: discr_sov_insufficient_accessibility + column_41: discr_sov_sufficient_accessibility + column_42: discr_sov_oversufficient_accessibility + column_45: total_emp_accessibility + column_47: hh_walktransit_accessibility + mgra : zone_id \ No newline at end of file diff --git a/test/joint_tours/configs/initialize_tours.yaml b/test/joint_tours/configs/initialize_tours.yaml new file mode 100644 index 000000000..999382c62 --- /dev/null +++ b/test/joint_tours/configs/initialize_tours.yaml @@ -0,0 +1,6 @@ +# +annotate_tours: + SPEC: annotate_tours + DF: tours + TABLES: + - land_use \ No newline at end of file diff --git a/test/joint_tours/configs/joint_tour_frequency_composition.csv b/test/joint_tours/configs/joint_tour_frequency_composition.csv new file mode 100644 index 000000000..2cace7b25 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition.csv @@ -0,0 +1,99 @@ +Label,Description,Expression,Coefficient +,Constant for shopping tour,@df.shopping,coef_constant_for_shopping_tour +,Constant for Maintenance tour,@df.othmaint,coef_constant_for_maintenance_tour +,Constant for eating out tour,@df.eatout,coef_constant_for_eating_out_tour +,Constant for visiting tour,@df.social,coef_constant_for_visiting_tour +,Constant for discretionary tour,@df.othdiscr,coef_constant_for_discretionary_tour +,Constant for 2 shopping tour,@df.shopping==2,coef_constant_for_2_shopping_tour +,1 Shopping and 1 Maintenance Tour,@((df.shopping==1) & (df.othmaint==1)),coef_1_shopping_and_1_maintenance_tour +,1 Shopping and 1 Eating Out Tour,@((df.shopping==1) & (df.eatout==1)),coef_1_shopping_and_1_eating_out_tour +,1 Shopping and 1 Visiting Tour,@((df.shopping==1) & (df.social==1)),coef_1_shopping_and_1_visiting_tour +,1 Shopping and 1 Discretionary Tour,@((df.shopping==1) & (df.othdiscr==1)),coef_1_shopping_and_1_discretionary_tour +,Constant for 2 Maintenance tour,@df.othmaint==2,coef_constant_for_2_maintenance_tour +,1 Maintenance and 1 Eating Out Tour,@((df.othmaint==1) & (df.eatout==1)),coef_1_maintenance_and_1_eating_out_tour +,1 Maintenance and 1 Visiting Tour,@((df.othmaint==1) & (df.social==1)),coef_1_maintenance_and_1_visiting_tour +,1 Maintenance and 1 Discretionary Tour,@((df.othmaint==1) & (df.othdiscr==1)),coef_1_maintenance_and_1_discretionary_tour +,Constant for 2 eating out tour,@df.eatout==2,coef_constant_for_2_eating_out_tour +,1 Eating Out and 1 Visiting Tour,@((df.eatout==1) & (df.social==1)),coef_1_eating_out_and_1_visiting_tour +,1 Eating Out and 1 Discretionary Tour,@((df.eatout==1) & (df.othdiscr==1)),coef_1_eating_out_and_1_discretionary_tour +,Constant for 2 visiting tour,@df.social==2,coef_constant_for_2_visiting_tour +,1 Visiting and 1 Discretionary Tour,@((df.social==1) & (df.othdiscr==1)),coef_1_visiting_and_1_discretionary_tour +,Constant for 2 discretionary tour,othdiscr==2,coef_constant_for_2_discretionary_tour +,Number of Active Full time workers /Shopping,num_travel_active_full_time_workers * shopping,coef_number_of_active_full_time_workers_shopping +,Number of Active Non-workers /Shopping,num_travel_active_non_workers * shopping,coef_number_of_active_nonworkers_shopping +,Number of Active Pre- Driving Age School Children /Shopping,num_travel_active_pre_driving_age_school_kids * shopping,coef_number_of_active_pre_driving_age_school_children_shopping +,Number of Active Preschool Children /Shopping,num_travel_active_pre_school_kids * shopping,coef_number_of_active_preschool_children_shopping +,Number of Active Non-workers /Maintenance,num_travel_active_non_workers * othmaint,coef_number_of_active_nonworkers_maintenance +,Number of Active Retirees /Maintenance,num_travel_active_retirees * othmaint,coef_number_of_active_retirees_maintenance +,Number of Active Driving Age School Children /Maintenance,num_travel_active_driving_age_students * othmaint,coef_number_of_active_driving_age_school_children_maintenance +,Number of Active Preschool Children /Maintenance,num_travel_active_pre_school_kids * othmaint,coef_number_of_active_preschool_children_maintenance +,Number of Active Full time workers /Eating Out,num_travel_active_full_time_workers * eatout,coef_number_of_active_full_time_workers_eating_out +,Number of Active University Students /Eating Out,num_travel_active_university_students * eatout,coef_number_of_active_university_students_eating_out +,Number of Active Retirees /Eating Out,num_travel_active_retirees * eatout,coef_number_of_active_retirees_eating_out +,Number of Active Pre- Driving Age School Children /Eating Out,num_travel_active_pre_driving_age_school_kids * eatout,coef_number_of_active_pre_driving_age_school_children_eating_out +,Number of Active Preschool Children /Eating Out,num_travel_active_pre_school_kids * eatout,coef_number_of_active_preschool_children_eating_out +,Number of Active Pre- Driving Age School Children /Visiting,num_travel_active_pre_driving_age_school_kids * social,coef_number_of_active_pre_driving_age_school_children_visiting +,Number of Active Preschool Children /Visiting,num_travel_active_pre_school_kids * social,coef_number_of_active_preschool_children_visiting +,Number of Active Part time workers /Discretionary,num_travel_active_part_time_workers * othdiscr,coef_number_of_active_part_time_workers_discretionary +,Number of Active University Students /Discretionary,num_travel_active_university_students * othdiscr,coef_number_of_active_university_students_discretionary +,Number of Active Driving Age School Children /Discretionary,num_travel_active_driving_age_students * othdiscr,coef_number_of_active_driving_age_school_children_discretionary +,Number of Active Preschool Children /Discretionary,num_travel_active_pre_school_kids * othdiscr,coef_number_of_active_preschool_children_discretionary +,HH has more autos than workers/ Maintenance,(auto_ownership > num_workers) * othmaint,coef_hh_has_more_autos_than_workers_maintenance +,Income > $100k /Maintenance,(income>100000) * othmaint,coef_income_gtr_100k_maintenance +,"Income Less than $29,999 / Eating Out",(income<30000) * eatout,coef_income_less_than_29999__eating_out +,"Income Between $30,000 to $59,999 / Eating Out",((income>=30000) & (income<60000)) * othmaint,coef_income_between_30000_to_59999__eating_out +,"Income Less than $29,999 / Discretionary",(income<30000) * othdiscr,coef_income_less_than_29999__discretionary +,"Income Between $30,000 to $59,999 / Discretionary",((income>=30000) & (income<60000)) * othdiscr,coef_income_between_30000_to_59999__discretionary +,Shopping HOV accessibility for 2 Tours,((autosnum_workers)*shop_hov_oversufficient_accessibility)*(num_joint_tours==2)*shopping,coef_shopping_hov_accessibility_for_2_tours +,Maintenance HOV Accessibility,((autosnum_workers)*maint_hov_oversufficient_accessibility)*othmaint,coef_maintenance_hov_accessibility +,Discretionary HOV Accessibility,((autosnum_workers)*discr_hov_oversufficient_accessibility)*othdiscr,coef_discretionary_hov_accessibility +,Constant for Children Party/ Shopping Tour,@(df.purpose1==5)*(df.party1==2)+(df.purpose2==5)*(df.party2==2),coef_constant_for_children_party_shopping_tour +,Constant for Children Party/ Maintenance Tour,@(df.purpose1==6)*(df.party1==2)+(df.purpose2==6)*(df.party2==2),coef_constant_for_children_party_maintenance_tour +,Constant for Children Party/ Eating Out Tour,@(df.purpose1==7)*(df.party1==2)+(df.purpose2==7)*(df.party2==2),coef_constant_for_children_party_eating_out_tour +,Constant for Children Party/ Visiting Tour,@(df.purpose1==8)*(df.party1==2)+(df.purpose2==8)*(df.party2==2),coef_constant_for_children_party_visiting_tour +,Constant for Children Party/ Discretionary Tour,@(df.purpose1==9)*(df.party1==2)+(df.purpose2==9)*(df.party2==2),coef_constant_for_children_party_discretionary_tour +,Constant for Mixed Party/ Shopping Tour,@(df.purpose1==5)*(df.party1==2)+(df.purpose2==5)*(df.party2==2),coef_constant_for_mixed_party_shopping_tour +,Constant for Mixed Party/ Maintenance Tour,@(df.purpose1==6)*(df.party1==3)+(df.purpose2==6)*(df.party2==3),coef_constant_for_mixed_party_maintenance_tour +,Constant for Mixed Party/ Eating Out Tour,@(df.purpose1==7)*(df.party1==3)+(df.purpose2==7)*(df.party2==3),coef_constant_for_mixed_party_eating_out_tour +,Constant for Mixed Party/ Visiting Tour,@(df.purpose1==8)*(df.party1==3)+(df.purpose2==8)*(df.party2==3),coef_constant_for_mixed_party_visiting_tour +,Constant for Mixed Party/ Discretionary Tour,@(df.purpose1==9)*(df.party1==3)+(df.purpose2==9)*(df.party2==3),coef_constant_for_mixed_party_discretionary_tour +,Number of Active Full time workers /Adult Party,num_travel_active_full_time_workers * (party1==1) + num_travel_active_full_time_workers * (party2==1),coef_number_of_active_full_time_workers_adult_party +,Number of Active Part time workers /Adult Party,num_travel_active_part_time_workers * (party1==1) + num_travel_active_part_time_workers * (party2==1),coef_number_of_active_part_time_workers_adult_party +,Number of Active University Students /Adult Party,num_travel_active_university_students * (party1==1) + num_travel_active_university_students * (party2==1),coef_number_of_active_university_students_adult_party +,Number of Active Non-workers /Adult Party,num_travel_active_non_workers * (party1==1) + num_travel_active_non_workers * (party2==1),coef_number_of_active_nonworkers_adult_party +,Number of Active Retirees /Adult Party,num_travel_active_retirees * (party1==1) + num_travel_active_retirees * (party2==1),coef_number_of_active_retirees_adult_party +,Number of Active Driving Age School Children /Children Party,num_travel_active_driving_age_students * (party1==1) + num_travel_active_driving_age_students * (party2==1),coef_number_of_active_driving_age_school_children_children_party +,Number of Active Pre- Driving Age School Children /Children Party,num_travel_active_pre_driving_age_school_kids * (party1==2) + num_travel_active_pre_driving_age_school_kids * (party2==2),coef_number_of_active_pre_driving_age_school_children_children_party +,Number of Active Part time workers /Mixed Party,num_travel_active_part_time_workers * (party1==2) + num_travel_active_part_time_workers * (party2==2),coef_number_of_active_part_time_workers_mixed_party +,Number of Active Driving Age School Children /Mixed Party,num_travel_active_driving_age_students * (party1==3) + num_travel_active_driving_age_students * (party2==3),coef_number_of_active_driving_age_school_children_mixed_party +,Number of Active Pre- Driving Age School Children /Mixed Party,num_travel_active_pre_driving_age_school_kids * (party1==3) + num_travel_active_pre_driving_age_school_kids * (party2==3),coef_number_of_active_pre_driving_age_school_children_mixed_party +,Number of Active Preschool Children /Mixed Party,num_travel_active_pre_school_kids * (party1==3) + num_travel_active_pre_school_kids * (party2==3),coef_number_of_active_preschool_children_mixed_party +,HH has no autos / Mixed Party,@(df.autos==0)*(df.party1==3)+(df.autos==0)*(df.party2==3),coef_hh_has_no_autos__mixed_party +,HH has less autos than workers/ Mixed Party,@(df.autos100000)*(df.party1==2)+(df.income>100000)*(df.party2==2),coef_income_more_than_100k_child_party +,Income more than $100k /Mixed Party,@(df.income>100000)*(df.party1==3)+(df.income>100000)*(df.party2==3),coef_income_more_than_100k_mixed_party +,Log of max window overlaps between adults,@df.log_time_window_overlap_adult*((df.party1==1)+(df.party2==1)),coef_log_of_max_window_overlaps_between_adults +,Log of max window overlaps between children,@df.log_time_window_overlap_child*((df.party1==2)+(df.party2==2)),coef_log_of_max_window_overlaps_between_children +,Log of max window overlaps between adult & child,@df.log_time_window_overlap_adult_child*((df.party1==3)+(df.party2==3)),coef_log_of_max_window_overlaps_between_adult_child +,Not more than 1 travel active adult in HH,@(df.num_travel_active_adults < 2)*(((df.party1==1)+(df.party2==1))>0),coef_unavailable +,Not more than 1 travel active child in HH,@(df.num_travel_active_children < 2)*(((df.party1==2)+(df.party2==2))>0),coef_unavailable +,No travel-active pair adult-child in HH ,@((df.num_travel_active_adults*df.num_travel_active_children) ==0)*(((df.party1==3)+(df.party2==3))>0),coef_unavailable +,Adjustment for Children Party/ Shopping Tour,@(df.purpose1==5)*(df.party1==2)+(df.purpose2==5)*(df.party2==2),coef_adjustment_for_children_party_shopping_tour +,Adjustment for Children Party/ Maintenance Tour,@(df.purpose1==6)*(df.party1==2)+(df.purpose2==6)*(df.party2==2),coef_adjustment_for_children_party_maintenance_tour +,Adjustment for Children Party/ Eating Out Tour,@(df.purpose1==7)*(df.party1==2)+(df.purpose2==7)*(df.party2==2),coef_adjustment_for_children_party_eating_out_tour +,Adjustment for Children Party/ Visiting Tour,@(df.purpose1==8)*(df.party1==2)+(df.purpose2==8)*(df.party2==2),coef_adjustment_for_children_party_visiting_tour +,Adjustment for Children Party/ Discretionary Tour,@(df.purpose1==9)*(df.party1==2)+(df.purpose2==9)*(df.party2==2),coef_adjustment_for_children_party_discretionary_tour +,Adjustment for Mixed Party/ Shopping Tour,@(df.purpose1==5)*(df.party1==2)+(df.purpose2==5)*(df.party2==2),coef_adjustment_for_mixed_party_shopping_tour +,Adjustment for Mixed Party/ Maintenance Tour,@(df.purpose1==6)*(df.party1==3)+(df.purpose2==6)*(df.party2==3),coef_adjustment_for_mixed_party_maintenance_tour +,Adjustment for Mixed Party/ Eating Out Tour,@(df.purpose1==7)*(df.party1==3)+(df.purpose2==7)*(df.party2==3),coef_adjustment_for_mixed_party_eating_out_tour +,Adjustment for Mixed Party/ Visiting Tour,@(df.purpose1==8)*(df.party1==3)+(df.purpose2==8)*(df.party2==3),coef_adjustment_for_mixed_party_visiting_tour +,Adjustment for Mixed Party/ Discretionary Tour,@(df.purpose1==9)*(df.party1==3)+(df.purpose2==9)*(df.party2==3),coef_adjustment_for_mixed_party_discretionary_tour +,Adjustment for shopping tour,shopping,coef_adjustment_for_shopping_tour +,Adjustment for Maintenance tour,othmaint,coef_adjustment_for_maintenance_tour +,Adjustment for eating out tour,eatout,coef_adjustment_for_eating_out_tour +,Adjustment for visiting tour,social,coef_adjustment_for_visiting_tour +,Adjustment for discretionary tour,othdiscr,coef_adjustment_for_discretionary_tour +,Adjustment for share of 2 Joint Tours,num_joint_tours==2,coef_adjustment_for_share_of_2_joint_tours +,TM2 Adjustment for Children Party,@(df.party1==2)+(df.party2==2),coef_tm2_adjustment_for_children_party +,TM2 Adjustment for Mixed Party,@(df.party1==3)+(df.party2==3),coef_tm2_adjustment_for_mixed_party +,TM2 adjustment for share of 2 Joint Tours,num_joint_tours==2,coef_tm2_adjustment_for_share_of_2_joint_tours diff --git a/test/joint_tours/configs/joint_tour_frequency_composition.yaml b/test/joint_tours/configs/joint_tour_frequency_composition.yaml new file mode 100644 index 000000000..ce31ea8df --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition.yaml @@ -0,0 +1,35 @@ +LOGIT_TYPE: MNL + +SPEC: joint_tour_frequency_composition.csv +COEFFICIENTS: joint_tour_frequency_composition_coeffs.csv + +preprocessor: + SPEC: joint_tour_frequency_composition_annotate_households_preprocessor.csv + DF: households + TABLES: + - persons + +ALTS_PREPROCESSOR: + SPEC: joint_tour_frequency_composition_annotate_alt_preprocessor.csv + DF: alt_tdd + +# define the structure of alternative table +ALTS_TABLE_STRUCTURE: + PURPOSE: + COLUMNS: + - purpose1 + - purpose2 + VALUE_MAP: + 5: shopping + 6: othmaint + 7: eatout + 8: social + 9: othdiscr + COMPOSITION: + COLUMNS: + - party1 + - party2 + VALUE_MAP: + 1: adults + 2: children + 3: mixed \ No newline at end of file diff --git a/test/joint_tours/configs/joint_tour_frequency_composition_alternatives.csv b/test/joint_tours/configs/joint_tour_frequency_composition_alternatives.csv new file mode 100644 index 000000000..657f98741 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition_alternatives.csv @@ -0,0 +1,151 @@ +alt,purpose1,purpose2,party1,party2 +1,5,0,1,0 +2,5,0,2,0 +3,5,0,3,0 +4,6,0,1,0 +5,6,0,2,0 +6,6,0,3,0 +7,7,0,1,0 +8,7,0,2,0 +9,7,0,3,0 +10,8,0,1,0 +11,8,0,2,0 +12,8,0,3,0 +13,9,0,1,0 +14,9,0,2,0 +15,9,0,3,0 +16,5,5,1,1 +17,5,5,1,2 +18,5,5,1,3 +19,5,5,2,1 +20,5,5,2,2 +21,5,5,2,3 +22,5,5,3,1 +23,5,5,3,2 +24,5,5,3,3 +25,5,6,1,1 +26,5,6,1,2 +27,5,6,1,3 +28,5,6,2,1 +29,5,6,2,2 +30,5,6,2,3 +31,5,6,3,1 +32,5,6,3,2 +33,5,6,3,3 +34,5,7,1,1 +35,5,7,1,2 +36,5,7,1,3 +37,5,7,2,1 +38,5,7,2,2 +39,5,7,2,3 +40,5,7,3,1 +41,5,7,3,2 +42,5,7,3,3 +43,5,8,1,1 +44,5,8,1,2 +45,5,8,1,3 +46,5,8,2,1 +47,5,8,2,2 +48,5,8,2,3 +49,5,8,3,1 +50,5,8,3,2 +51,5,8,3,3 +52,5,9,1,1 +53,5,9,1,2 +54,5,9,1,3 +55,5,9,2,1 +56,5,9,2,2 +57,5,9,2,3 +58,5,9,3,1 +59,5,9,3,2 +60,5,9,3,3 +61,6,6,1,1 +62,6,6,1,2 +63,6,6,1,3 +64,6,6,2,1 +65,6,6,2,2 +66,6,6,2,3 +67,6,6,3,1 +68,6,6,3,2 +69,6,6,3,3 +70,6,7,1,1 +71,6,7,1,2 +72,6,7,1,3 +73,6,7,2,1 +74,6,7,2,2 +75,6,7,2,3 +76,6,7,3,1 +77,6,7,3,2 +78,6,7,3,3 +79,6,8,1,1 +80,6,8,1,2 +81,6,8,1,3 +82,6,8,2,1 +83,6,8,2,2 +84,6,8,2,3 +85,6,8,3,1 +86,6,8,3,2 +87,6,8,3,3 +88,6,9,1,1 +89,6,9,1,2 +90,6,9,1,3 +91,6,9,2,1 +92,6,9,2,2 +93,6,9,2,3 +94,6,9,3,1 +95,6,9,3,2 +96,6,9,3,3 +97,7,7,1,1 +98,7,7,1,2 +99,7,7,1,3 +100,7,7,2,1 +101,7,7,2,2 +102,7,7,2,3 +103,7,7,3,1 +104,7,7,3,2 +105,7,7,3,3 +106,7,8,1,1 +107,7,8,1,2 +108,7,8,1,3 +109,7,8,2,1 +110,7,8,2,2 +111,7,8,2,3 +112,7,8,3,1 +113,7,8,3,2 +114,7,8,3,3 +115,7,9,1,1 +116,7,9,1,2 +117,7,9,1,3 +118,7,9,2,1 +119,7,9,2,2 +120,7,9,2,3 +121,7,9,3,1 +122,7,9,3,2 +123,7,9,3,3 +124,8,8,1,1 +125,8,8,1,2 +126,8,8,1,3 +127,8,8,2,1 +128,8,8,2,2 +129,8,8,2,3 +130,8,8,3,1 +131,8,8,3,2 +132,8,8,3,3 +133,8,9,1,1 +134,8,9,1,2 +135,8,9,1,3 +136,8,9,2,1 +137,8,9,2,2 +138,8,9,2,3 +139,8,9,3,1 +140,8,9,3,2 +141,8,9,3,3 +142,9,9,1,1 +143,9,9,1,2 +144,9,9,1,3 +145,9,9,2,1 +146,9,9,2,2 +147,9,9,2,3 +148,9,9,3,1 +149,9,9,3,2 +150,9,9,3,3 diff --git a/test/joint_tours/configs/joint_tour_frequency_composition_annotate_alt_preprocessor.csv b/test/joint_tours/configs/joint_tour_frequency_composition_annotate_alt_preprocessor.csv new file mode 100644 index 000000000..389d28a13 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition_annotate_alt_preprocessor.csv @@ -0,0 +1,7 @@ +Description,Target,Expression +,shopping,"np.where(alt_tdd.purpose1 == 5, 1, 0) + np.where(alt_tdd.purpose2 == 5, 1, 0)" +,othmaint,"np.where(alt_tdd.purpose1 == 6, 1, 0) + np.where(alt_tdd.purpose2 == 6, 1, 0)" +,eatout,"np.where(alt_tdd.purpose1 == 7, 1, 0) + np.where(alt_tdd.purpose2 == 7, 1, 0)" +,social,"np.where(alt_tdd.purpose1 == 8, 1, 0) + np.where(alt_tdd.purpose2 == 8, 1, 0)" +,othdiscr,"np.where(alt_tdd.purpose1 == 9, 1, 0) + np.where(alt_tdd.purpose2 == 9, 1, 0)" +,num_joint_tours,shopping+othmaint+eatout+social+othdiscr \ No newline at end of file diff --git a/test/joint_tours/configs/joint_tour_frequency_composition_annotate_households_preprocessor.csv b/test/joint_tours/configs/joint_tour_frequency_composition_annotate_households_preprocessor.csv new file mode 100644 index 000000000..1b4a5c91d --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition_annotate_households_preprocessor.csv @@ -0,0 +1,8 @@ +Description,Target,Expression +,_HH_OVERLAPS,"hh_time_window_overlap(households, persons)" +,time_window_overlap_adult,_HH_OVERLAPS['aa'] +,time_window_overlap_child,_HH_OVERLAPS['cc'] +,time_window_overlap_adult_child,_HH_OVERLAPS['ac'] +logTimeWindowOverlapAdult,log_time_window_overlap_adult,np.log1p(time_window_overlap_adult) +logTimeWindowOverlapChild,log_time_window_overlap_child,np.log1p(time_window_overlap_child) +logTimeWindowOverlapAdultChild,log_time_window_overlap_adult_child,np.log1p(time_window_overlap_adult_child) diff --git a/test/joint_tours/configs/joint_tour_frequency_composition_coeffs.csv b/test/joint_tours/configs/joint_tour_frequency_composition_coeffs.csv new file mode 100644 index 000000000..da82e8fa9 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_frequency_composition_coeffs.csv @@ -0,0 +1,97 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_constant_for_shopping_tour,0,T +coef_constant_for_maintenance_tour,-1.477,F +coef_constant_for_eating_out_tour,0.5796,F +coef_constant_for_visiting_tour,-1.0037,F +coef_constant_for_discretionary_tour,-1.1195,F +coef_constant_for_2_shopping_tour,-13.70946409,F +coef_1_shopping_and_1_maintenance_tour,-12.13684801,F +coef_1_shopping_and_1_eating_out_tour,-12.79892713,F +coef_1_shopping_and_1_visiting_tour,-12.22077221,F +coef_1_shopping_and_1_discretionary_tour,-12.57867869,F +coef_constant_for_2_maintenance_tour,-13.43572169,F +coef_1_maintenance_and_1_eating_out_tour,-12.18915033,F +coef_1_maintenance_and_1_visiting_tour,-11.81267905,F +coef_1_maintenance_and_1_discretionary_tour,-12.28867197,F +coef_constant_for_2_eating_out_tour,-13.15388273,F +coef_1_eating_out_and_1_visiting_tour,-13.15388273,F +coef_1_eating_out_and_1_discretionary_tour,-12.56102569,F +coef_constant_for_2_visiting_tour,-13.15388273,F +coef_1_visiting_and_1_discretionary_tour,-12.37222202,F +coef_constant_for_2_discretionary_tour,-13.23532342,F +coef_number_of_active_full_time_workers_shopping,0.09864381,F +coef_number_of_active_nonworkers_shopping,0.393630718,F +coef_number_of_active_pre_driving_age_school_children_shopping,-0.313021042,F +coef_number_of_active_preschool_children_shopping,-1.213950718,F +coef_number_of_active_nonworkers_maintenance,0.322738327,F +coef_number_of_active_retirees_maintenance,0.298632515,F +coef_number_of_active_driving_age_school_children_maintenance,0.503901856,F +coef_number_of_active_preschool_children_maintenance,-1.160523204,F +coef_number_of_active_full_time_workers_eating_out,-0.305934663,F +coef_number_of_active_university_students_eating_out,-0.65706029,F +coef_number_of_active_retirees_eating_out,-0.391710731,F +coef_number_of_active_pre_driving_age_school_children_eating_out,-0.25140082,F +coef_number_of_active_preschool_children_eating_out,-1.700731169,F +coef_number_of_active_pre_driving_age_school_children_visiting,0.162335324,F +coef_number_of_active_preschool_children_visiting,-0.96955678,F +coef_number_of_active_part_time_workers_discretionary,0.217898126,F +coef_number_of_active_university_students_discretionary,-0.610578234,F +coef_number_of_active_driving_age_school_children_discretionary,0.359485499,F +coef_number_of_active_preschool_children_discretionary,-1.244458661,F +coef_hh_has_more_autos_than_workers_maintenance,-0.336188392,F +coef_income_gtr_100k_maintenance,-0.475730683,F +coef_income_less_than_29999__eating_out,-1.282190776,F +coef_income_between_30000_to_59999__eating_out,-0.275046208,F +coef_income_less_than_29999__discretionary,-0.352579013,F +coef_income_between_30000_to_59999__discretionary,-0.191735343,F +coef_shopping_hov_accessibility_for_2_tours,0.039513822,F +coef_maintenance_hov_accessibility,0.128132691,F +coef_discretionary_hov_accessibility,0.089590553,F +coef_constant_for_children_party_shopping_tour,-5.374907972,F +coef_constant_for_children_party_maintenance_tour,-5.144798184,F +coef_constant_for_children_party_eating_out_tour,-4.09806907,F +coef_constant_for_children_party_visiting_tour,-4.09806907,F +coef_constant_for_children_party_discretionary_tour,-4.09806907,F +coef_constant_for_mixed_party_shopping_tour,0.575879495,F +coef_constant_for_mixed_party_maintenance_tour,0.515873866,F +coef_constant_for_mixed_party_eating_out_tour,0.168592084,F +coef_constant_for_mixed_party_visiting_tour,0.078060666,F +coef_constant_for_mixed_party_discretionary_tour,0.856042068,F +coef_number_of_active_full_time_workers_adult_party,0.599335502,F +coef_number_of_active_part_time_workers_adult_party,1.113944272,F +coef_number_of_active_university_students_adult_party,0.231138167,F +coef_number_of_active_nonworkers_adult_party,0.341446999,F +coef_number_of_active_retirees_adult_party,0.657220801,F +coef_number_of_active_driving_age_school_children_children_party,0.580109231,F +coef_number_of_active_pre_driving_age_school_children_children_party,0.580109231,F +coef_number_of_active_part_time_workers_mixed_party,0.522327137,F +coef_number_of_active_driving_age_school_children_mixed_party,0.216908669,F +coef_number_of_active_pre_driving_age_school_children_mixed_party,0.31440104,F +coef_number_of_active_preschool_children_mixed_party,0.897670235,F +coef_hh_has_no_autos__mixed_party,-2.920728233,F +coef_hh_has_less_autos_than_workers_mixed_party,-0.546339245,F +coef_income_more_than_100k_child_party,-1.189112151,F +coef_income_more_than_100k_mixed_party,-0.303217156,F +coef_log_of_max_window_overlaps_between_adults,2.96902119,F +coef_log_of_max_window_overlaps_between_children,4.673601828,F +coef_log_of_max_window_overlaps_between_adult_child,3.523795377,F +coef_adjustment_for_children_party_shopping_tour,0.407745781,F +coef_adjustment_for_children_party_maintenance_tour,0.284925252,F +coef_adjustment_for_children_party_eating_out_tour,0,T +coef_adjustment_for_children_party_visiting_tour,0.966264444,F +coef_adjustment_for_children_party_discretionary_tour,0.144740532,F +coef_adjustment_for_mixed_party_shopping_tour,0.681178558,F +coef_adjustment_for_mixed_party_maintenance_tour,0.476324741,F +coef_adjustment_for_mixed_party_eating_out_tour,0.827297043,F +coef_adjustment_for_mixed_party_visiting_tour,0.691826384,F +coef_adjustment_for_mixed_party_discretionary_tour,0.697808415,F +coef_adjustment_for_shopping_tour,0,T +coef_adjustment_for_maintenance_tour,0.06575155,F +coef_adjustment_for_eating_out_tour,0.0643679,F +coef_adjustment_for_visiting_tour,0.00785518,F +coef_adjustment_for_discretionary_tour,0.076075677,F +coef_adjustment_for_share_of_2_joint_tours,-1.214059893,F +coef_tm2_adjustment_for_children_party,0,F +coef_tm2_adjustment_for_mixed_party,0,F +coef_tm2_adjustment_for_share_of_2_joint_tours,-0.5,F diff --git a/test/joint_tours/configs/joint_tour_participation.csv b/test/joint_tours/configs/joint_tour_participation.csv new file mode 100644 index 000000000..9f3151129 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_participation.csv @@ -0,0 +1,67 @@ +Label,Description,Expression,participate,not_participate +,Dummy for full-time worker in adult party,(ptype==1) & (composition=='adults'),coef_full_time_worker_adults_only_party, +,Dummy for part-time worker in adult party,(ptype==2) & (composition=='adults'),coef_part_time_worker_adults_only_party, +,Dummy for university student in adult party,(ptype==3) & (composition=='adults'),coef_university_students_adults_only_party, +,Dummy for nonworker in adult party,(ptype==4) & (composition=='adults'),coef_non_worker_adults_only_party, +,Dummy for retiree in adult party,(ptype==5) & (composition=='adults'),coef_retiree_adults_only_party, +,Dummy for driving school child in children party,(ptype==6) & (composition=='children'),coef_driving_age_student_children_only_party, +,Dummy for pre-driving school child in children party,(ptype==7) & (composition=='children'),coef_pre_driving_age_student_children_only_party, +,Dummy for preschool child in children party,(ptype==8) & (composition=='children'),coef_child_too_young_for_school_children_only_party, +util_full_time_worker_mixed_party,Dummy for full-time worker in mixed party,(ptype==1) & (composition=='mixed'),coef_full_time_worker_mixed_party, +util_part_time_worker_mixed_party,Dummy for part-time worker in mixed party,(ptype==2) & (composition=='mixed'),coef_part_time_worker_mixed_party, +util_university_student_mixed_party,Dummy for university student in mixed party,(ptype==3) & (composition=='mixed'),coef_university_student_mixed_party, +util_non_worker_mixed_party,Dummy for nonworker in mixed party,(ptype==4) & (composition=='mixed'),coef_non_worker_mixed_party, +util_retiree_mixed_party,Dummy for retiree in mixed party,(ptype==5) & (composition=='mixed'),coef_retiree_mixed_party, +util_child_too_young_for_school_mixed_party,Dummy for driving school child in mixed party,(ptype==6) & (composition=='mixed'),coef_child_too_young_for_school_mixed_party, +util_pre_driving_age_student_mixed_party,Dummy for pre-driving school child in mixed party,(ptype==7) & (composition=='mixed'),coef_pre_driving_age_student_mixed_party, +util_driving_age_student_mixed_party,Dummy for preschool child in mixed party,(ptype==8) & (composition=='mixed'),coef_driving_age_student_mixed_party, +#,,,, +,Dummy for part-time worker on maintenance joint tour ,(ptype==2) & (tour_type=='othmaint'),coef_part_time_worker_specific_to_maintenance_joint_tours, +,Dummy for non-worker on maintenance joint tour ,(ptype==4) & (tour_type=='othmaint'),coef_non_worker_specific_to_maintenance_joint_tours, +,Dummy for preschool child on maintenance joint tour ,(ptype==8) & (tour_type=='othmaint'),coef_pre_school_kid_specific_to_maintenance_joint_tours, +,Dummy for full-time worker on eating out joint tour ,(ptype==1) & (tour_type=='eatout'),coef_full_time_worker_specific_to_eating_out_joint_tours, +,Dummy for part-time worker on eating out joint tour ,(ptype==2) & (tour_type=='eatout'),coef_part_time_worker_specific_to_eating_out_joint_tours, +,Dummy for pre-driving age school child on eating out joint tour ,(ptype==7) & (tour_type=='eatout'),coef_pre_driving_age_student_specific_to_eating_out_joint_tours, +,Dummy for part-time worker on discretionary joint tour ,(ptype==2) & (tour_type=='othdiscr'),coef_part_time_worker_specific_to_discretionary_joint_tours, +,Dummy for retiree on discretionary joint tour ,(ptype==5) & (tour_type=='othdiscr'),coef_retiree_specific_to_discretionary_joint_tours, +,Dummy for driving school child on discretionary joint tour ,(ptype==6) & (tour_type=='othdiscr'),coef_driving_age_student_specific_to_discretionary_joint_tours, +,Dummy for pre-driving school child on discretionary joint tour ,(ptype==7) & (tour_type=='othdiscr'),coef_pre_driving_age_student_specific_to_discretionary_joint_tours, +,Dummy for part-time worker on visiting joint tour ,(ptype==2) & (tour_type=='social'),coef_part_time_worker_specific_to_visiting_joint_tours, +,Dummy for non-worker on visiting joint tour ,(ptype==4) & (tour_type=='social'),coef_non_worker_specific_to_visiting_joint_tours, +,Dummy for retiree on visiting joint tour ,(ptype==5) & (tour_type=='social'),coef_retiree_specific_to_visiting_joint_tours, +,Dummy for driving school child on visiting joint tour ,(ptype==6) & (tour_type=='social'),coef_driving_age_student_specific_to_visiting_joint_tours, +,Dummy for preschool child on visiting joint tour ,(ptype==8) & (tour_type=='social'),coef_pre_school_kid_specific_to_visiting_joint_tours, +#,,,, +,Dummy for low car ownership for adult in adult party,(autosnum_workers)&(composition=='mixed')&adult,coef_adult_more_automobiles_than_workers_mixed_party, +,Dummy for no car for child in mixed party,(autos==0)&(composition=='mixed')&child,coef_child_zero_automobiles_mixed_party, +#,,,, +,Dummy for low income for adult in adult party,(income<30000)&(composition=='adults')&adult,coef_dummy_for_low_income_for_adult_in_adult_party, +,Dummy for high income for adult in mixed party,(income>100000)&(composition=='mixed')&adult,coef_dummy_for_high_income_for_adult_in_mixed_party, +,Dummy for high income for child in mixed party,(income>100000)&(composition=='mixed')&child,coef_dummy_for_high_income_for_child_in_mixed_party, +#,,,, +,No of HH joint tours for adult in adult party,(adult&(composition=='adults'))*num_hh_joint_tours,coef_adult_number_of_joint_tours_adult_only, +,No of HH joint tours for adult in mixed party,(adult&(composition=='mixed'))*num_hh_joint_tours,coef_adult_number_of_joint_tours_mixed, +,No of HH joint tours for child in children party,(child&(composition=='children'))*num_hh_joint_tours,coef_child_number_of_joint_tours_child_only, +,No of HH joint tours for child in mixed party,(child&(composition=='mixed'))*num_hh_joint_tours,coef_child_number_of_joint_tours_mixed, +#,,,, +,No of other HH adults for adult in adult party,(adult & (composition=='adults')) * (num_adults.clip(upper=4) - 1),coef_adult_number_of_other_adults_in_the_household_adults_only_party, +,No of other HH adults for adult in mixed party,(adult & (composition=='mixed')) * (num_adults.clip(upper=4) - 1),coef_adult_number_of_other_adults_in_the_household_mixed_party, +,No of other HH children for child in children party,(~adult & (composition=='children')) * (num_children.clip(upper=4) - 1),coef_child_number_of_other_children_in_the_household_child_only_party, +,No of other HH children for child in mixed party,(~adult & (composition=='mixed')) * (num_children.clip(upper=4) - 1),coef_child_number_of_other_children_in_the_household_mixed, +#,,,, +util_adult_log_of_max_window_overlap_with_an_adult_adult_only_party,"Adult, log of max window overlap with an adult, adult-only party",(adult & (composition=='adults')) * log_time_window_overlap_adult,coef_adult_log_of_max_window_overlap_with_an_adult_adult_only_party, +util_adult_log_of_max_window_overlap_with_a_child_mixed,"Adult, log of max window overlap with a child, mixed",(adult & (composition=='mixed')) * log_time_window_overlap_adult_child,coef_adult_log_of_max_window_overlap_with_a_child_mixed, +util_child_log_of_max_window_overlap_with_an_adult_mixed,"Child, log of max window overlap with an adult, mixed",(~adult &(composition=='mixed')) * log_time_window_overlap_adult_child,coef_child_log_of_max_window_overlap_with_an_adult_mixed, +util_child_log_of_max_window_overlap_with_a_child_child,"Child, log of max window overlap with a child, child",(~adult & (composition=='children')) * log_time_window_overlap_child,coef_child_log_of_max_window_overlap_with_a_child_child, +#,,,, +util_adults_are_prohibited_in_participating_in_child_only_tours,Adults are prohibited in participating in child-only tours,adult & (composition=='children'),coef_unavailable, +util_children_are_prohibited_in_participating_in_adult_only_tours,Children are prohibited in participating in adult-only tours,~adult & (composition=='adults'),coef_unavailable, +util_persons_with_home_activity_patterns_are_prohibilted_from_participating,Persons with Home activity patterns are prohibilted from participating,~travel_active,coef_unavailable, +#,,,, +util_if_only_two_available_adults_both_must_participate_in_adult_only_tour,"If only two available adults, both must participate in adult-only tour",adult & travel_active & (composition=='adults') & (num_travel_active_adults<3),,coef_unavailable +util_if_only_one_available_adult_traveler_must_participate_in_mixed_tour,"If only one available adult, traveler must participate in mixed tour",adult & travel_active & (composition=='mixed') & (num_travel_active_adults<2),,coef_unavailable +util_if_only_two_available_children_both_must_participate_in_child_only_tour,"If only two available children, both must participate in child-only tour",~adult & travel_active & (composition=='children') & (num_travel_active_children<3),,coef_unavailable +util_if_only_one_available_child_traveler_must_participate_in_mixed_tour,"If only one available child, traveler must participate in mixed tour",~adult & travel_active & (composition == 'mixed') & (num_travel_active_children<2),,coef_unavailable +#,,,, +,Global adjustment constant for whether person participated or not,1,coef_global_adj_for_paticipation, diff --git a/test/joint_tours/configs/joint_tour_participation.yaml b/test/joint_tours/configs/joint_tour_participation.yaml new file mode 100644 index 000000000..6e4fe5050 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_participation.yaml @@ -0,0 +1,21 @@ + +SPEC: joint_tour_participation.csv +COEFFICIENTS: joint_tour_participation_coefficients.csv + +LOGIT_TYPE: MNL + +max_participation_choice_iterations: 1000 + +preprocessor: + SPEC: joint_tour_participation_annotate_participants_preprocessor + DF: participants + TABLES: + - tours +# - persons +# - accessibility + +annotate_persons: + SPEC: annotate_persons_jtp + DF: persons + TABLES: + - joint_tour_participants diff --git a/test/joint_tours/configs/joint_tour_participation_annotate_participants_preprocessor.csv b/test/joint_tours/configs/joint_tour_participation_annotate_participants_preprocessor.csv new file mode 100644 index 000000000..95dac2f9e --- /dev/null +++ b/test/joint_tours/configs/joint_tour_participation_annotate_participants_preprocessor.csv @@ -0,0 +1,13 @@ +Description,Target,Expression +,_P_OVERLAPS,person_time_window_overlap(persons) +,time_window_overlap_adult,"reindex(_P_OVERLAPS.aa, participants.person_id)" +,time_window_overlap_child,"reindex(_P_OVERLAPS.cc, participants.person_id)" +,time_window_overlap_adult_child,"reindex(_P_OVERLAPS.ac, participants.person_id)" +logTimeWindowOverlapAdult,log_time_window_overlap_adult,np.log1p(time_window_overlap_adult) +logTimeWindowOverlapChild,log_time_window_overlap_child,np.log1p(time_window_overlap_child) +logTimeWindowOverlapAdultChild,log_time_window_overlap_adult_child,np.log1p(time_window_overlap_adult_child) +#,, +,_JOINT_TOURS,tours[tours.tour_category=='joint'] +,num_hh_joint_tours,"reindex_i(_JOINT_TOURS.groupby('household_id').size(), participants.household_id)" +#,, +,person_is_preschool,participants.ptype == 8 \ No newline at end of file diff --git a/test/joint_tours/configs/joint_tour_participation_coefficients.csv b/test/joint_tours/configs/joint_tour_participation_coefficients.csv new file mode 100644 index 000000000..8126d3088 --- /dev/null +++ b/test/joint_tours/configs/joint_tour_participation_coefficients.csv @@ -0,0 +1,59 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_full_time_worker_adults_only_party,-0.844885174,F +coef_part_time_worker_adults_only_party,-1.837563723,F +coef_university_students_adults_only_party,-0.970251833,F +coef_non_worker_adults_only_party,-0.757939204,F +coef_retiree_adults_only_party,1.196798335,F +coef_driving_age_student_children_only_party,-12.08924396,F +coef_pre_driving_age_student_children_only_party,-16.16999328,F +coef_child_too_young_for_school_children_only_party,-16.16999328,F +coef_full_time_worker_mixed_party,0.453048547,F +coef_part_time_worker_mixed_party,1.263225489,F +coef_university_student_mixed_party,1.561741231,F +coef_non_worker_mixed_party,2.90040237,F +coef_retiree_mixed_party,1.043276837,F +coef_child_too_young_for_school_mixed_party,-1.916267403,F +coef_pre_driving_age_student_mixed_party,-1.91645719,F +coef_driving_age_student_mixed_party,-0.933863842,F +#,, +coef_part_time_worker_specific_to_maintenance_joint_tours,0.766072366,F +coef_non_worker_specific_to_maintenance_joint_tours,0.971450303,F +coef_pre_school_kid_specific_to_maintenance_joint_tours,-0.52817951,F +coef_full_time_worker_specific_to_eating_out_joint_tours,0.535579735,F +coef_part_time_worker_specific_to_eating_out_joint_tours,1.23257663,F +coef_pre_driving_age_student_specific_to_eating_out_joint_tours,1.535608884,F +coef_part_time_worker_specific_to_discretionary_joint_tours,0.539337302,F +coef_retiree_specific_to_discretionary_joint_tours,1.105118702,F +coef_driving_age_student_specific_to_discretionary_joint_tours,-1.151066894,F +coef_pre_driving_age_student_specific_to_discretionary_joint_tours,0.798684189,F +coef_part_time_worker_specific_to_visiting_joint_tours,1.075535443,F +coef_non_worker_specific_to_visiting_joint_tours,1.075535443,F +coef_retiree_specific_to_visiting_joint_tours,-1.930328716,F +coef_driving_age_student_specific_to_visiting_joint_tours,-1.334515344,F +coef_pre_school_kid_specific_to_visiting_joint_tours,1.552698221,F +#,, +coef_adult_fewer_automobiles_than_workers_adult_only_party,1.292641814,F +coef_adult_more_automobiles_than_workers_mixed_party,-0.390671553,F +coef_child_zero_automobiles_mixed_party,-1.546687521,F +#,, +coef_dummy_for_low_income_for_adult_in_adult_party,-0.680688378,F +coef_dummy_for_high_income_for_adult_in_mixed_party,-0.20257569,F +coef_dummy_for_high_income_for_child_in_mixed_party,-0.74160668,F +#,, +coef_adult_number_of_joint_tours_adult_only,-0.599443484,F +coef_adult_number_of_joint_tours_mixed,-0.218541079,F +coef_child_number_of_joint_tours_child_only,-0.313832442,F +coef_child_number_of_joint_tours_mixed,-0.241748337,F +#,, +coef_adult_number_of_other_adults_in_the_household_adults_only_party,-0.747528682,F +coef_adult_number_of_other_adults_in_the_household_mixed_party,-0.285988025,F +coef_child_number_of_other_children_in_the_household_child_only_party,-2.305908575,F +coef_child_number_of_other_children_in_the_household_mixed,-0.471545203,F +#,, +coef_adult_log_of_max_window_overlap_with_an_adult_adult_only_party,1.634378325,F +coef_adult_log_of_max_window_overlap_with_a_child_mixed,0.057012356,F +coef_child_log_of_max_window_overlap_with_an_adult_mixed,1.616796615,F +coef_child_log_of_max_window_overlap_with_a_child_child,10.70256432,F +#,, +coef_global_adj_for_paticipation,-1,T diff --git a/test/joint_tours/configs/network_los.yaml b/test/joint_tours/configs/network_los.yaml new file mode 100644 index 000000000..391125a38 --- /dev/null +++ b/test/joint_tours/configs/network_los.yaml @@ -0,0 +1,14 @@ +# read cached skims (using numpy memmap) from output directory (memmap is faster than omx ) +read_skim_cache: False +# write memmapped cached skims to output directory after reading from omx, for use in subsequent runs +write_skim_cache: True + +zone_system: 1 + +taz_skims: skims.omx + +skim_time_periods: + time_window: 1440 + period_minutes: 60 + periods: [0, 3, 5, 9, 14, 18, 24] # 3=3:00-3:59, 5=5:00-5:59, 9=9:00-9:59, 14=2:00-2:59, 18=6:00-6:59 + labels: ['EA', 'EA', 'AM', 'MD', 'PM', 'EV'] \ No newline at end of file diff --git a/test/joint_tours/configs/settings.yaml b/test/joint_tours/configs/settings.yaml new file mode 100644 index 000000000..64584bdf4 --- /dev/null +++ b/test/joint_tours/configs/settings.yaml @@ -0,0 +1,79 @@ +# input tables +input_table_list: + - tablename: households + filename: households.csv + index_col: household_id + rename_columns: + unique_hh_id: household_id + NP: hhsize + hh_workers_from_esr: num_workers + VEH: auto_ownership + MAZ: home_zone_id + HINCP: income + keep_columns: + - home_zone_id + - income + - hhsize + - HHT + - auto_ownership + - num_workers + - tablename: persons + filename: persons.csv + index_col: person_id + rename_columns: + unique_hh_id: household_id + AGEP: age + SPORDER: PNUM + SEX: sex + employed: pemploy + student_status: pstudent + person_type: ptype + keep_columns: + - household_id + - age + - PNUM + - sex + - pemploy + - pstudent + - ptype + - tablename: land_use + filename: land_use.csv + index_col: zone_id + rename_columns: + MAZ_ORIGINAL: zone_id + CountyID: county_id + TAZ_ORIGINAL: TAZ + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + keep_columns: + - TAZ + - DISTRICT + - SD + - county_id + - TOTHH + - TOTPOP + - TOTACRE + - tablename: tours + filename: mandatory_tours.csv + # since tours has a canonical index name 'tour_id', we must explicitly indicate that no index should be assigned + # canonical index_col 'tour_id' will be assigned by initialize_tours + index_col: + rename_columns: + hh_id: household_id + start_period: start + end_period: end + keep_columns: + - person_id + - household_id + - person_type + - tour_category + - tour_purpose + - orig_mgra + - dest_mgra + - start + - end + +trace_hh_id: \ No newline at end of file diff --git a/test/joint_tours/configs/tour_departure_and_duration_alternatives.csv b/test/joint_tours/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 000000000..bddab06b9 --- /dev/null +++ b/test/joint_tours/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/test/joint_tours/test_joint_tours.py b/test/joint_tours/test_joint_tours.py new file mode 100644 index 000000000..2edccb042 --- /dev/null +++ b/test/joint_tours/test_joint_tours.py @@ -0,0 +1,265 @@ +import logging +import pytest +import os +import shutil +import pandas as pd +import numpy as np +from numpy import dot +from numpy.linalg import norm + +# import models is necessary to initalize the model steps with orca +from activitysim.abm import models +from activitysim.core import pipeline, config +from activitysim.core import tracing + +logger = logging.getLogger(__name__) + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def module() -> str: + """ + A pytest fixture that returns the data folder location. + :return: folder location for any necessary data to initialize the tests + """ + return "joint_tours" + + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +# def tables() -> dict[str, str]: +def tables(prepare_module_inputs) -> dict[str, str]: + """ + A pytest fixture that returns the "mock" tables to build pipeline dataframes. The + key-value pair is the name of the table and the index column. + :return: dict + """ + return { + "land_use": "MAZ_ORIGINAL", + "persons": "person_id", + "households": "household_id", + "accessibility": "MAZ_ORIGINAL", + "tours": "tour_id", + } + + +# Used by conftest.py initialize_pipeline method +# Set to true if you need to read skims into the pipeline +@pytest.fixture(scope="module") +def initialize_network_los() -> bool: + """ + A pytest boolean fixture indicating whether network skims should be read from the + fixtures test data folder. + :return: bool + """ + return False + + +# Used by conftest.py reconnect_pipeline method +@pytest.fixture(scope="module") +def load_checkpoint() -> bool: + """ + checkpoint to be loaded from the pipeline when reconnecting. + """ + return "initialize_households" + + +@pytest.mark.skipif( + os.path.isfile("test/joint_tours/output/pipeline.h5"), + reason="no need to recreate pipeline store if already exist", +) +def test_prepare_input_pipeline(initialize_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["initialize_landuse", "initialize_households"]) + person_df = pipeline.get_table("persons") + pipeline.close_pipeline() + + +def test_joint_tours_frequency_composition( + reconnect_pipeline: pipeline.Pipeline, caplog +): + + caplog.set_level(logging.INFO) + + # run model step + pipeline.run( + models=["joint_tour_frequency_composition"], + resume_after="initialize_households", + ) + + pipeline.close_pipeline() + + +def test_joint_tours_participation(reconnect_pipeline: pipeline.Pipeline, caplog): + + caplog.set_level(logging.INFO) + + # run model step + pipeline.run( + models=["joint_tour_participation"], + resume_after="joint_tour_frequency_composition", + ) + + pipeline.close_pipeline() + + +# fetch/prepare existing files for model inputs +# e.g. read accessibilities.csv from ctramp result, rename columns, write out to accessibility.csv which is the input to activitysim +@pytest.fixture(scope="module") +def prepare_module_inputs() -> None: + """ + copy input files from sharepoint into test folder + + create unique person id in person file + + :return: None + """ + # https://wsponlinenam.sharepoint.com/sites/US-TM2ConversionProject/Shared%20Documents/Forms/ + # AllItems.aspx?id=%2Fsites%2FUS%2DTM2ConversionProject%2FShared%20Documents%2FTask%203%20ActivitySim&viewid=7a1eaca7%2D3999%2D4d45%2D9701%2D9943cc3d6ab1 + test_dir = os.path.join("test", "joint_tours", "data") + + accessibility_file = os.path.join(test_dir, "tm2_outputs", "accessibilities.csv") + household_file = os.path.join(test_dir, "popsyn", "households.csv") + person_file = os.path.join(test_dir, "popsyn", "persons.csv") + landuse_file = os.path.join(test_dir, "landuse", "maz_data_withDensity.csv") + + shutil.copy(accessibility_file, os.path.join(test_dir, "accessibility.csv")) + shutil.copy(household_file, os.path.join(test_dir, "households.csv")) + shutil.copy(person_file, os.path.join(test_dir, "persons.csv")) + shutil.copy(landuse_file, os.path.join(test_dir, "land_use.csv")) + + # add original maz id to accessibility table + land_use_df = pd.read_csv(os.path.join(test_dir, "land_use.csv")) + + accessibility_df = pd.read_csv(os.path.join(test_dir, "accessibility.csv")) + + accessibility_df = pd.merge( + accessibility_df, + land_use_df[["MAZ", "MAZ_ORIGINAL"]].rename(columns={"MAZ": "mgra"}), + how="left", + on="mgra", + ) + + accessibility_df.to_csv(os.path.join(test_dir, "accessibility.csv"), index=False) + + # currently household file has to have these two columns, even before annotation + # because annotate person happens before household and uses these two columns + # TODO find a way to get around this + #### + + # household file from populationsim + household_df = pd.read_csv(os.path.join(test_dir, "households.csv")) + + household_columns_dict = {"HHID": "household_id", "MAZ": "home_zone_id"} + + household_df.rename(columns=household_columns_dict, inplace=True) + + # get columns from ctramp output + tm2_simulated_household_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "householdData_1.csv") + ) + tm2_simulated_household_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + household_df = pd.merge( + household_df, + tm2_simulated_household_df[ + [ + "household_id", + "autos", + "automated_vehicles", + "transponder", + "cdap_pattern", + "jtf_choice", + ] + ], + how="inner", # tm2 is not 100% sample run + on="household_id", + ) + + household_df.to_csv(os.path.join(test_dir, "households.csv"), index=False) + + # person file from populationsim + person_df = pd.read_csv(os.path.join(test_dir, "persons.csv")) + + person_columns_dict = {"HHID": "household_id", "PERID": "person_id"} + + person_df.rename(columns=person_columns_dict, inplace=True) + + # get columns from ctramp result + tm2_simulated_person_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "personData_1.csv") + ) + tm2_simulated_person_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + person_df = pd.merge( + person_df, + tm2_simulated_person_df[ + [ + "household_id", + "person_id", + "type", + "value_of_time", + "activity_pattern", + "imf_choice", + "inmf_choice", + "fp_choice", + "reimb_pct", + "workDCLogsum", + "schoolDCLogsum", + ] + ], + how="inner", # ctramp might not be 100% sample run + on=["household_id", "person_id"], + ) + + person_df["PNUM"] = person_df.groupby("household_id")["person_id"].rank() + + person_df.to_csv(os.path.join(test_dir, "persons.csv"), index=False) + + ## get tour data from tm2 output + + tm2_simulated_indiv_tour_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "indivTourData_1.csv") + ) + tm2_simulated_indiv_tour_df = tm2_simulated_indiv_tour_df[ + tm2_simulated_indiv_tour_df.tour_category == "MANDATORY" + ] + + tm2_simulated_tour_df = pd.concat( + [tm2_simulated_indiv_tour_df], sort=False, ignore_index=True + ) + + tm2_simulated_tour_df.rename(columns={"hh_id": "household_id"}).to_csv( + os.path.join(test_dir, "tours.csv"), index=False + ) + + +def create_summary(input_df, key, out_col="Share") -> pd.DataFrame: + """ + Create summary for the input data. + 1. group input data by the "key" column + 2. calculate the percent of input data records in each "key" category. + + :return: pd.DataFrame + """ + + out_df = input_df.groupby(key).size().reset_index(name="Count") + out_df[out_col] = round(out_df["Count"] / out_df["Count"].sum(), 4) + + return out_df[[key, out_col]] + + +def cosine_similarity(a, b): + """ + Computes cosine similarity between two vectors. + + Cosine similarity is used here as a metric to measure similarity between two sequence of numbers. + Two sequence of numbers are represented as vectors (in a multi-dimensional space) and cosine similiarity is defined as the cosine of the angle between them + i.e., dot products of the vectors divided by the product of their lengths. + + :return: + """ + + return dot(a, b) / (norm(a) * norm(b)) diff --git a/test/non_mandatory_tour_frequency/.gitkeep b/test/non_mandatory_tour_frequency/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/non_mandatory_tour_frequency/configs/NonMandatoryIndividualTourFrequency.xls b/test/non_mandatory_tour_frequency/configs/NonMandatoryIndividualTourFrequency.xls new file mode 100644 index 000000000..4726c3f73 Binary files /dev/null and b/test/non_mandatory_tour_frequency/configs/NonMandatoryIndividualTourFrequency.xls differ diff --git a/test/non_mandatory_tour_frequency/configs/annotate_households.csv b/test/non_mandatory_tour_frequency/configs/annotate_households.csv new file mode 100644 index 000000000..ac21d3797 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/annotate_households.csv @@ -0,0 +1,13 @@ +Description,Target,Expression +#,, annotate households table after import +,_PERSON_COUNT,"lambda query, persons, households: persons.query(query).groupby('household_id').size().reindex(households.index).fillna(0).astype(np.int8)" +number of fulltime workers,num_full_time_workers,"_PERSON_COUNT('ptype == 1', persons, households)" +number of parttime workers,num_part_time_workers,"_PERSON_COUNT('ptype == 2', persons, households)" +number of university student,num_university_students,"_PERSON_COUNT('ptype == 3', persons, households)" +number of non-workers,num_non_workers,"_PERSON_COUNT('ptype == 4', persons, households)" +number of retirees,num_retirees,"_PERSON_COUNT('ptype == 5', persons, households)" +number of driving age students,num_driving_age_students,"_PERSON_COUNT('ptype == 6', persons, households)" +number of pre-driving age school kids,num_pre_driving_age_school_kids,"_PERSON_COUNT('ptype == 7', persons, households)" +number of pre-school kids,num_pre_school_kids,"_PERSON_COUNT('ptype == 8', persons, households)" +number of pre-driving age school kids who go out,num_pre_driving_age_school_kids_go_out,"_PERSON_COUNT('(ptype == 7) & (cdap_activity != \'H\')', persons, households)" +number of pre-school kids who go out,num_pre_school_kids_go_out,"_PERSON_COUNT('(ptype == 8) & (cdap_activity != \'H\')', persons, households)" \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/annotate_landuse.csv b/test/non_mandatory_tour_frequency/configs/annotate_landuse.csv new file mode 100644 index 000000000..65237c0ad --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/annotate_landuse.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +#,, annotate landuse table after import +household_density,household_density,land_use.TOTHH / land_use.TOTACRE +employment_density,employment_density,land_use.TOTEMP / land_use.TOTACRE +population_density,population_density,land_use.TOTPOP / land_use.TOTACRE +density_index,density_index,(household_density *employment_density) / (household_density + employment_density).clip(lower=1) \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/annotate_persons.csv b/test/non_mandatory_tour_frequency/configs/annotate_persons.csv new file mode 100644 index 000000000..a68eb7e67 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/annotate_persons.csv @@ -0,0 +1,17 @@ +Description,Target,Expression +#,, annotate persons table after import +age_16_to_19,age_16_to_19,"persons.age.between(16, 19)" +age_16_p,age_16_p,persons.age >= 16 +adult,adult,persons.age >= 18 +male,male,persons.sex == 1 +female,female,persons.sex == 2 +,ptype,0 +,ptype,"np.where(persons.type == 'Full-time worker', 1, ptype)" +,ptype,"np.where(persons.type == 'Part-time worker', 2, ptype)" +,ptype,"np.where(persons.type == 'University student', 3, ptype)" +,ptype,"np.where(persons.type == 'Non-worker', 4, ptype)" +,ptype,"np.where(persons.type == 'Retired', 5, ptype)" +,ptype,"np.where(persons.type == 'Student of driving age', 6, ptype)" +,ptype,"np.where(persons.type == 'Student of non-driving age', 7, ptype)" +,ptype,"np.where(persons.type == 'Child too young for school', 8, ptype)" +home_zone_id,home_zone_id,"reindex(households.home_zone_id, persons.household_id)" \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/annotate_persons_after_hh.csv b/test/non_mandatory_tour_frequency/configs/annotate_persons_after_hh.csv new file mode 100644 index 000000000..0dfa16be6 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/annotate_persons_after_hh.csv @@ -0,0 +1,5 @@ +Description,Target,Expression +#,, annotate persons table after annotate_households +#,, adults get full hh_value_of_time and children get 60% +,_hh_vot,"reindex(households.hh_value_of_time, persons.household_id)" +,value_of_time,"_hh_vot.where(persons.age>=18, _hh_vot * 0.667)" \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/annotate_persons_nmtf.csv b/test/non_mandatory_tour_frequency/configs/annotate_persons_nmtf.csv new file mode 100644 index 000000000..07890f237 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/annotate_persons_nmtf.csv @@ -0,0 +1,10 @@ +Description,Target,Expression +#,, annotate persons table after non_mandatory_tour_frequency model has run +num_non_mand,num_non_mand,tours[tours.tour_category=='non_mandatory'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_escort_tours,num_escort_tours,tours[tours.tour_type == 'escort'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_eatout_tours,num_eatout_tours,tours[tours.tour_type == 'eatout'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_shop_tours,num_shop_tours,tours[tours.tour_type == 'shopping'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_maint_tours,num_maint_tours,tours[tours.tour_type == 'othmaint'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_discr_tours,num_discr_tours,tours[tours.tour_type == 'othdiscr'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_social_tours,num_social_tours,tours[tours.tour_type == 'social'].groupby('person_id').size().reindex(persons.index).fillna(0).astype(np.int8) +num_non_escort_tours,num_non_escort_tours,num_non_mand-num_escort_tours diff --git a/test/non_mandatory_tour_frequency/configs/constants.yaml b/test/non_mandatory_tour_frequency/configs/constants.yaml new file mode 100644 index 000000000..b0bd5a1f3 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/constants.yaml @@ -0,0 +1,68 @@ +## ActivitySim +## See full license in LICENSE.txt. + + +#HHT_NONE: 0 +#HHT_FAMILY_MARRIED: 1 +#HHT_FAMILY_MALE: 2 +#HHT_FAMILY_FEMALE: 3 +#HHT_NONFAMILY_MALE_ALONE: 4 +#HHT_NONFAMILY_MALE_NOTALONE: 5 +#HHT_NONFAMILY_FEMALE_ALONE: 6 +#HHT_NONFAMILY_FEMALE_NOTALONE: 7 + +# convenience for expression files +HHT_NONFAMILY: [4, 5, 6, 7] +HHT_FAMILY: [1, 2, 3] + +PSTUDENT_GRADE_OR_HIGH: 1 +PSTUDENT_UNIVERSITY: 2 +PSTUDENT_NOT: 3 + +GRADE_SCHOOL_MAX_AGE: 14 +GRADE_SCHOOL_MIN_AGE: 5 + +SCHOOL_SEGMENT_NONE: 0 +SCHOOL_SEGMENT_GRADE: 1 +SCHOOL_SEGMENT_HIGH: 2 +SCHOOL_SEGMENT_UNIV: 3 + +INCOME_SEGMENT_LOW: 1 +INCOME_SEGMENT_MED: 2 +INCOME_SEGMENT_HIGH: 3 +INCOME_SEGMENT_VERYHIGH: 4 + +PEMPLOY_FULL: 1 +PEMPLOY_PART: 2 +PEMPLOY_NOT: 3 +PEMPLOY_CHILD: 4 + +PTYPE_FULL: &ptype_full 1 +PTYPE_PART: &ptype_part 2 +PTYPE_UNIVERSITY: &ptype_university 3 +PTYPE_NONWORK: &ptype_nonwork 4 +PTYPE_RETIRED: &ptype_retired 5 +PTYPE_DRIVING: &ptype_driving 6 +PTYPE_SCHOOL: &ptype_school 7 +PTYPE_PRESCHOOL: &ptype_preschool 8 + +# these appear as column headers in non_mandatory_tour_frequency.csv +PTYPE_NAME: + *ptype_full: PTYPE_FULL + *ptype_part: PTYPE_PART + *ptype_university: PTYPE_UNIVERSITY + *ptype_nonwork: PTYPE_NONWORK + *ptype_retired: PTYPE_RETIRED + *ptype_driving: PTYPE_DRIVING + *ptype_school: PTYPE_SCHOOL + *ptype_preschool: PTYPE_PRESCHOOL + + +CDAP_ACTIVITY_MANDATORY: M +CDAP_ACTIVITY_NONMANDATORY: N +CDAP_ACTIVITY_HOME: H + +# Correction for transit skim expressions +# e.g. MTC transit skims (Cube TRANPLAN skims) use scaled ints and +# therefore need to be divided by the scale factor if used in expressions +TRANSIT_SCALE_FACTOR: 100 diff --git a/test/non_mandatory_tour_frequency/configs/initialize_households.yaml b/test/non_mandatory_tour_frequency/configs/initialize_households.yaml new file mode 100644 index 000000000..07e34e8a4 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/initialize_households.yaml @@ -0,0 +1,48 @@ +annotate_tables: + - tablename: persons + column_map: + HHID: household_id + PERID: person_id + AGEP: age + SEX: sex + SCHL: education_attainment + OCCP: occupation + WKHP: hours_worked + WKW: weeks_worked + EMPLOYED: employment_status + ESR: esr + SCHG: grade_attending + activity_pattern: cdap_activity + annotate: + SPEC: annotate_persons + DF: persons + TABLES: + - households + - tablename: households + column_map: + HHID: household_id + MAZ: home_zone_id + HHINCADJ: income + NWRKRS_ESR: num_workers + VEH: auto_ownership + NP: hhsize + HHT: hh_type + BLD: building_size + TYPE: hh_unit_type + MTCCountyID: county_id + annotate: + SPEC: annotate_households + DF: households + TABLES: + - persons + - land_use + +CONSTANTS: + PTYPE_FULL: 1 + PTYPE_PART: 2 + PTYPE_UNIVERSITY: 3 + PTYPE_NONWORK: 4 + PTYPE_RETIRED: 5 + PTYPE_DRIVING: 6 + PTYPE_SCHOOL: 7 + PTYPE_PRESCHOOL: 8 \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/initialize_landuse.yaml b/test/non_mandatory_tour_frequency/configs/initialize_landuse.yaml new file mode 100644 index 000000000..7cc1d7e34 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/initialize_landuse.yaml @@ -0,0 +1,54 @@ +annotate_tables: + - tablename: land_use + column_map: + MAZ_ORIGINAL: zone_id + CountyID: county_id + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + annotate: + SPEC: annotate_landuse + DF: land_use + - tablename: accessibility + column_map: + column_1: nonmandatory_auto_accessibility + column_2: nonmandatory_transit_accessibility + column_3: nonmandatory_nm_accessibility + column_4: nonmandatory_sov0_accessibility + column_5: nonmandatory_sov1_accessibility + column_6: nonmandatory_sov2_accessibility + column_7: nonmandatory_hov0_accessibility + column_8: nonmandatory_hov1_accessibility + column_9: nonmandatory_hov2_accessibility + column_10: shop_hov_insufficient_accessibility + column_11: shop_hov_sufficient_accessibility + column_12: shop_hov_oversufficient_accessibility + column_13: maint_hov_insufficient_accessibility + column_14: maint_hov_sufficient_accessibility + column_15: maint_hov_oversufficient_accessibility + column_16: eat_hov_insufficient_accessibility + column_17: eat_hov_sufficient_accessibility + column_18: eat_hov_oversufficient_accessibility + column_19: visit_hov_insufficient_accessibility + column_20: visit_hov_sufficient_accessibility + column_21: visit_hov_oversufficient_accessibility + column_22: discr_hov_insufficient_accessibility + column_23: discr_hov_sufficient_accessibility + column_24: discr_hov_oversufficient_accessibility + column_25: escort_hov_insufficient_accessibility + column_26: escort_hov_sufficient_accessibility + column_27: escort_hov_oversufficient_accessibility + column_28: shop_sov_insufficient_accessibility + column_29: shop_sov_sufficient_accessibility + column_30: shop_sov_oversufficient_accessibility + column_31: maint_sov_insufficient_accessibility + column_32: maint_sov_sufficient_accessibility + column_33: maint_sov_oversufficient_accessibility + column_40: discr_sov_insufficient_accessibility + column_41: discr_sov_sufficient_accessibility + column_42: discr_sov_oversufficient_accessibility + column_45: total_emp_accessibility + column_47: hh_walktransit_accessibility + mgra : zone_id \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/network_los.yaml b/test/non_mandatory_tour_frequency/configs/network_los.yaml new file mode 100644 index 000000000..391125a38 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/network_los.yaml @@ -0,0 +1,14 @@ +# read cached skims (using numpy memmap) from output directory (memmap is faster than omx ) +read_skim_cache: False +# write memmapped cached skims to output directory after reading from omx, for use in subsequent runs +write_skim_cache: True + +zone_system: 1 + +taz_skims: skims.omx + +skim_time_periods: + time_window: 1440 + period_minutes: 60 + periods: [0, 3, 5, 9, 14, 18, 24] # 3=3:00-3:59, 5=5:00-5:59, 9=9:00-9:59, 14=2:00-2:59, 18=6:00-6:59 + labels: ['EA', 'EA', 'AM', 'MD', 'PM', 'EV'] \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.csv new file mode 100644 index 000000000..7a3fc8703 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.csv @@ -0,0 +1,187 @@ +Label,Description,Expression,PTYPE_FULL,PTYPE_PART,PTYPE_UNIVERSITY,PTYPE_NONWORK,PTYPE_RETIRED,PTYPE_DRIVING,PTYPE_SCHOOL,PTYPE_PRESCHOOL +util_escorting_tour,Escorting Tour,escort,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour,coef_escorting_tour +util_discretionary_tour,Discretionary Tour,othdiscr,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour,coef_discretionary_tour +util_shopping_tour,Shopping Tour,shopping,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour,coef_shopping_tour +util_maintenance_tour,Maintenance Tour,othmaint,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour,coef_maintenance_tour +util_visiting_or_social_tour,Visiting/Social Tour,social,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour,coef_visiting_or_social_tour +util_eating_out_tour,Eating Out Tour,eatout,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour,coef_eating_out_tour +util_total_number_of_tours_is_0_no_prior_tours,Total Number of Tours = 0 (No Prior Tours),(tot_tours == 0) & (num_mandatory_tours == 0) & (num_person_joint_tours == 0),coef_unavailable,coef_unavailable,coef_unavailable,coef_unavailable,coef_unavailable,coef_unavailable,coef_unavailable,coef_unavailable +util_total_number_of_tours_is_0_prior_tours,Total Number of Tours = 0 (1 or more Prior Tours),(tot_tours == 0) & ((num_mandatory_tours > 0) | (num_person_joint_tours > 0)),coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours,coef_total_number_of_tours_is_0_prior_tours +util_total_number_of_tours_is_1,Total Number of Tours = 1,tot_tours == 1,coef_total_number_of_tours_is_1,coef_total_number_of_tours_is_1,coef_total_number_of_tours_is_1,,,,, +util_total_number_of_tours_is_2,Total Number of Tours = 2,tot_tours == 2,coef_total_number_of_tours_is_2,coef_total_number_of_tours_is_2,,,,,coef_total_number_of_tours_is_2,coef_total_number_of_tours_is_2 +util_total_number_of_tours_is_3,Total Number of Tours = 3,tot_tours == 3,coef_total_number_of_tours_is_3,coef_total_number_of_tours_is_3,,coef_total_number_of_tours_is_3,,,coef_total_number_of_tours_is_3,coef_total_number_of_tours_is_3 +util_total_number_of_tours_is_4,Total Number of Tours = 4,tot_tours == 4,coef_total_number_of_tours_is_4,coef_total_number_of_tours_is_4,,coef_total_number_of_tours_is_4,,,, +util_total_number_of_tours_is_5,Total Number of Tours = 5,tot_tours == 5,coef_unavailable,coef_total_number_of_tours_is_5,,coef_unavailable,coef_unavailable,,, +util_total_number_of_tours_is_6_plus,Total Number of Tours = 6+,tot_tours > 5,coef_unavailable,coef_total_number_of_tours_is_6_plus,,coef_unavailable,coef_unavailable,,, +util_total_number_of_tours_is_1+,Total Number of Tours >= 1,tot_tours >= 1,,,,,,coef_total_number_of_tours_is_1_plus,, +util_total_number_of_tours_is_4+,Total Number of Tours >= 4,tot_tours >= 4,,,,,,coef_unavailable,coef_unavailable,coef_unavailable +util_has_mandatory_tours_and_tour_frequency_is_1,One or more Mandatory tour & tour frequency =1,(num_mandatory_tours>0)&(tot_tours == 1),,,,,,,coef_has_mandatory_tours_and_tour_frequency_is_1, +util_has_mandatory_tours_and_tour_frequency_is_2,One or more Mandatory tour & tour frequency =2,(num_mandatory_tours>0)&(tot_tours == 2),coef_has_mandatory_tours_and_tour_frequency_is_2,coef_has_mandatory_tours_and_tour_frequency_is_2,,,,,, +util_has_mandatory_tours_and_tour_frequency_is_2+,One or more Mandatory tour & tour frequency =2+,(num_mandatory_tours>0)&(tot_tours >= 2),,,coef_has_mandatory_tours_and_tour_frequency_is_2_plus,,,coef_has_mandatory_tours_and_tour_frequency_is_2_plus,coef_has_mandatory_tours_and_tour_frequency_is_2_plus,coef_has_mandatory_tours_and_tour_frequency_is_2_plus +util_has_mandatory_tours_and_tour_frequency_is_3,One or more Mandatory tour & tour frequency =3,(num_mandatory_tours>0)&(tot_tours == 3),coef_has_mandatory_tours_and_tour_frequency_is_3,coef_has_mandatory_tours_and_tour_frequency_is_3,,,,,, +util_has_mandatory_tours_and_tour_frequency_is_4+,One or more Mandatory tour & tour frequency =4+,(num_mandatory_tours>0)&(tot_tours >= 4),coef_has_mandatory_tours_and_tour_frequency_is_4_plus,coef_has_mandatory_tours_and_tour_frequency_is_4_plus,,,,,, +util_has_joint_tours_and_tour_frequency_is_1,One or more Joint tour & tour frequency =1,(num_person_joint_tours>0)&(tot_tours == 1),,,coef_has_joint_tours_and_tour_frequency_is_1,coef_has_joint_tours_and_tour_frequency_is_1,coef_has_joint_tours_and_tour_frequency_is_1,,, +util_has_joint_tours_and_tour_frequency_is_2,One or more Joint tour & tour frequency =2,(num_person_joint_tours>0)&(tot_tours == 2),,,,coef_has_joint_tours_and_tour_frequency_is_2,,,, +util_has_joint_tours_and_tour_frequency_is_3+,One or more Joint tour & tour frequency =3+,(num_person_joint_tours>0)&(tot_tours >= 3),coef_has_joint_tours_and_tour_frequency_is_3_plus,,,coef_has_joint_tours_and_tour_frequency_is_3_plus,,,, +util_has_joint_tours_and_tour_frequency_is_4+,One or more Joint tour & tour frequency =4+,(num_person_joint_tours>0)&(tot_tours >= 4),,coef_has_joint_tours_and_tour_frequency_is_4_plus,,,,,, +util_has_joint_tours_and_tour_frequency_is_2+,One or more Joint tour & tour frequency =2+,(num_person_joint_tours>0)&(tot_tours >= 2),,,coef_has_joint_tours_and_tour_frequency_is_2_plus,,coef_has_joint_tours_and_tour_frequency_is_2_plus,,, +util_has_joint_tours_and_tour_frequency_is_1+,One or more Joint tour & tour frequency =1+,(num_person_joint_tours>0)&(tot_tours >= 1),,,,,,,coef_has_joint_tours_and_tour_frequency_is_1_plus, +util_number_of_joint_shopping_tours,Number of Joint Shopping tours,(shopping>0) * num_person_joint_shop_tours,coef_number_of_joint_shopping_tours,,,coef_number_of_joint_shopping_tours,coef_number_of_joint_shopping_tours,,, +util_number_of_joint_maintenance_tours,Number of Joint Maintenance tours,(othmaint>0) * num_person_joint_maint_tours,,,,coef_number_of_joint_maintenance_tours,coef_number_of_joint_maintenance_tours,,, +util_number_of_joint_eating_out_tours,Number of Joint Eating Out tours,(eatout>0) * num_person_joint_eatout_tours,,,,,coef_number_of_joint_eating_out_tours,,, +util_number_of_joint_discretionary_tours,Number of Joint Discretionary tours,(othdiscr>0) * num_person_joint_othdiscr_tours,coef_number_of_joint_discretionary_tours,coef_number_of_joint_discretionary_tours,,,coef_number_of_joint_discretionary_tours,coef_number_of_joint_discretionary_tours,coef_number_of_joint_discretionary_tours, +util_more_than_one_escorting_tours,More than one escorting tours,escort > 1,coef_more_than_one_escorting_tours,coef_more_than_one_escorting_tours,coef_more_than_one_escorting_tours,coef_more_than_one_escorting_tours,coef_more_than_one_escorting_tours,,coef_more_than_one_escorting_tours,coef_more_than_one_escorting_tours +util_more_than_one_shopping_tours,More than one shopping tours,shopping > 1,,coef_more_than_one_shopping_tours,,coef_more_than_one_shopping_tours,coef_more_than_one_shopping_tours,,, +util_more_than_one_maintenance_tours,More than one maintenance tours,othmaint>1,,,,coef_more_than_one_maintenance_tours,coef_more_than_one_maintenance_tours,,, +util_more_than_one_discretionary_tours,More than one discretionary tours,othdiscr > 1,coef_more_than_one_discretionary_tours,coef_more_than_one_discretionary_tours,,coef_more_than_one_discretionary_tours,,coef_more_than_one_discretionary_tours,coef_more_than_one_discretionary_tours, +util_low_income_group_and_escorting_tour,Dummy for low Income group (> 150K) & escorting tour,low_income * escort,,,coef_low_income_group_and_escorting_tour,,,coef_low_income_group_and_escorting_tour,, +util_mediumlow_income_group_and_escorting_tour,Dummy for medium low Income group (> 150K) & escorting tour,medium_low_income * escort,,,coef_medium_low_income_group_and_escorting_tour,,,coef_medium_low_income_group_and_escorting_tour,, +util_mediumhigh_income_group_and_escorting_tour,Dummy for medium high Income group (> 150K) & escorting tour,medium_high_income * escort,,,coef_medium_high_income_group_and_escorting_tour,,,,, +util_high_income_group_and_escorting_tour,Dummy for high Income group (> 150K) & escorting tour,high_income * escort,coef_high_income_group_and_escorting_tour,coef_high_income_group_and_escorting_tour,coef_high_income_group_and_escorting_tour,,,,,coef_high_income_group_and_escorting_tour +util_low_income_group_and_shopping_tour,Dummy for low Income group (> 150K) & shopping tour,low_income * shopping,,coef_low_income_group_and_shopping_tour,,coef_low_income_group_and_shopping_tour,,,, +util_mediumlow_income_group_and_shopping_tour,Dummy for medium low Income group (> 150K) & shopping tour,medium_low_income * shopping,,coef_medium_low_income_group_and_shopping_tour,,coef_medium_low_income_group_and_shopping_tour,,,, +util_mediumhigh_income_group_and_shopping_tour,Dummy for medium high Income group (> 150K) & shopping tour,medium_high_income * shopping,coef_mediumhigh_income_group_and_shopping_tour,coef_medium_high_income_group_and_shopping_tour,coef_medium_high_income_group_and_shopping_tour,,coef_mediumhigh_income_group_and_shopping_tour,,, +util_high_income_group_and_shopping_tour,Dummy for high Income group (> 150K) & shopping tour,high_income * shopping,coef_high_income_group_and_shopping_tour,coef_high_income_group_and_shopping_tour,coef_high_income_group_and_shopping_tour,,coef_high_income_group_and_shopping_tour,,coef_high_income_group_and_shopping_tour, +util_low_income_group_and_maintenance_tour,Dummy for low Income group (<30k) & maintenance tour,low_income * othmaint,coef_low_income_group_and_maintenance_tour,,,,coef_low_income_group_and_maintenance_tour,,, +util_mediumlow_income_group_and_maintenance_tour,Dummy for Mediumlow Income group (30K-60K) & maintenance tour,medium_low_income * othmaint,coef_mediumlow_income_group_and_maintenance_tour,,,,coef_mediumlow_income_group_and_maintenance_tour,,, +util_mediumhigh_income_group_and_maintenance_tour,Dummy for Medium high Income group (30K-60K) & maintenance tour,medium_high_income * othmaint,,,coef_mediumhigh_income_group_and_maintenance_tour,,,,coef_mediumhigh_income_group_and_maintenance_tour, +util_high_income_group_and_maintenance_tour,Dummy for High Income group (>150K) & maintenance tour,high_income * othmaint,coef_high_income_group_and_maintenance_tour,,coef_high_income_group_and_maintenance_tour,,,,coef_high_income_group_and_maintenance_tour, +util_low_income_group_and_eating_out_tour,Dummy for Low Income group (<30K) & Eating out tour,low_income * eatout,coef_low_income_group_and_eating_out_tour,coef_low_income_group_and_eating_out_tour,,coef_low_income_group_and_eating_out_tour,coef_low_income_group_and_eating_out_tour,,, +util_medium_low_income_group_and_eating_out_tour,Dummy for medium low Income group (>150K) & Eating out tour,medium_low_income * eatout,,coef_medium_low_income_group_and_eating_out_tour,,,coef_medium_low_income_group_and_eating_out_tour,,, +util_medium_high_income_group_and_eating_out_tour,Dummy for medium high Income group (>150K) & Eating out tour,medium_high_income * eatout,,,coef_medium_high_income_group_and_eating_out_tour,,,,, +util_high_income_group_and_eating_out_tour,Dummy for High Income group (>150K) & Eating out tour,high_income * eatout,coef_high_income_group_and_eating_out_tour,,coef_high_income_group_and_eating_out_tour,coef_high_income_group_and_eating_out_tour,,,, +util_low_income_group_and_discretionary_tour,Dummy for Low Income group (<30K) & Discretionary tour,low_income * othdiscr,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour,coef_low_income_group_and_discretionary_tour, +util_medium_low_income_group_and_discretionary_tour,Dummy for Medium Low Income group (<30K) & Discretionary tour,medium_low_income * othdiscr,,,,coef_medium_low_income_group_and_discretionary_tour,,,coef_medium_low_income_group_and_discretionary_tour, +util_mediumhigh_income_group_and_discretionary_tour,Dummy for Mediumhigh Income group (100k-150K) & Discretionary tour,medium_high_income * othdiscr,coef_mediumhigh_income_group_and_discretionary_tour,coef_mediumhigh_income_group_and_discretionary_tour,coef_mediumhigh_income_group_and_discretionary_tour,,coef_mediumhigh_income_group_and_discretionary_tour,coef_mediumhigh_income_group_and_discretionary_tour,, +util_high_income_group_and_discretionary_tour,Dummy for High Income group (>150K) & Discretionary tour,high_income * othdiscr,coef_high_income_group_and_discretionary_tour,coef_high_income_group_and_discretionary_tour,coef_high_income_group_and_discretionary_tour,,coef_high_income_group_and_discretionary_tour,coef_high_income_group_and_discretionary_tour,coef_high_income_group_and_discretionary_tour, +util_low_income_group_and_visiting_tour,Dummy for Low Income group (<30k) & Visiting tour,low_income * social,coef_low_income_group_and_visiting_tour,,coef_low_income_group_and_visiting_tour,,,,coef_low_income_group_and_visiting_tour, +util_mediumlow_income_group_and_visiting_tour,Dummy for medium Low Income group (<30k) & Visiting tour,medium_low_income * social,,,coef_medium_low_income_group_and_visiting_tour,,,,coef_medium_low_income_group_and_visiting_tour, +util_high_income_group_and_visiting_tour,Dummy for high Income group (<30k) & Visiting tour,high_income * social,,,coef_high_income_group_and_visiting_tour,coef_high_income_group_and_visiting_tour,coef_high_income_group_and_visiting_tour,coef_high_income_group_and_visiting_tour,coef_high_income_group_and_visiting_tour, +util_mediumhigh_income_group_and_visiting_tour,Dummy for Mediumhigh Income group (50K-100K) & Visiting tour,medium_high_income * social,,,,coef_mediumhigh_income_group_and_visiting_tour,,coef_mediumhigh_income_group_and_visiting_tour,, +util_female_and_escorting_tour,Dummy for Female & Escorting Tour,female * escort,coef_female_and_escorting_tour,coef_female_and_escorting_tour,coef_female_and_escorting_tour,coef_female_and_escorting_tour,,,, +util_female_and_shopping_tour,Dummy for Female & Shopping Tour,female * shopping,,coef_female_and_shopping_tour,coef_female_and_shopping_tour,coef_female_and_shopping_tour,coef_female_and_shopping_tour,coef_female_and_shopping_tour,, +util_female_and_maintenance_tour,Dummy for Female & Maintenance Tour,female * othmaint,,,coef_female_and_maintenance_tour,,coef_female_and_maintenance_tour,,, +util_female_and_eatingout_tour,Dummy for Female & EatingOut Tour,female * eatout,,coef_female_and_eatingout_tour,,,coef_female_and_eatingout_tour,,, +util_female_and_discretionary_tour,Dummy for Female & Discretionary Tour,female * othdiscr,,,,,coef_female_and_discretionary_tour,,, +util_female_and_discretionary_tour,Dummy for Female & Visiting Tour,female * social,,,coef_female_and_visit_tour,coef_female_and_visit_tour,,,, +util_zero_car_ownership_and_tour_frequency_is_2+,Dummy for zero car ownership & tour frequency >=2,no_cars & (tot_tours >= 2),coef_zero_car_ownership_and_tour_frequency_is_2_plus,coef_zero_car_ownership_and_tour_frequency_is_2_plus,,coef_zero_car_ownership_and_tour_frequency_is_2_plus,,,, +util_car_shortage_vs_workers_and_tour_frequency_is_2+,Dummy for Car Shortage vs Workers & tour frequency >=2,~no_cars & (car_sufficiency < 0) & (tot_tours >= 2),coef_car_shortage_vs_workers_and_tour_frequency_is_2_plus,coef_car_shortage_vs_workers_and_tour_frequency_is_2_plus,,,,,, +util_car_surplus_vs_workers_and_tour_frequency_is_1+,Dummy for Car Surplus vs Workers & tour frequency >=1,~no_cars & (car_sufficiency > 0) & (tot_tours >= 1),,,coef_car_surplus_vs_workers_and_tour_frequency_is_1_plus,,,,, +util_car_surplus_vs_workers_and_tour_frequency_is_3+,Dummy for Car Surplus vs Workers & tour frequency >=3,~no_cars & (car_sufficiency > 0) & (tot_tours >= 3),coef_car_surplus_vs_workers_and_tour_frequency_is_3_plus,,,,,,, +util_zero_car_ownership_and_escorting_tour,Dummy for zero car ownership & number of escorting tour,no_cars * escort,coef_zero_car_ownership_and_escorting_tour,,,coef_zero_car_ownership_and_escorting_tour,,,,coef_zero_car_ownership_and_escorting_tour +util_car_shortage_vs_workers_and_escorting_tour,Dummy for Car Shortage vs Workers & number of escorting tours,(~no_cars & (car_sufficiency < 0)) * escort,coef_car_shortage_vs_workers_and_number_of_escorting_tours,coef_car_shortage_vs_workers_and_number_of_escorting_tours,,,,,,coef_car_shortage_vs_workers_and_number_of_escorting_tours +util_car_surplus_vs_workers_and_escorting_tour,Dummy for Car Surplus vs Workers & number of escorting tours,(~no_cars & (car_sufficiency > 0)) * escort,,coef_car_surplus_vs_workers_and_number_of_escorting_tours,,coef_car_surplus_vs_workers_and_number_of_escorting_tours,,,, +util_car_shortage_vs_workers_and_shopping_tour,Dummy for Car Shortage vs Workers & number of shopping tours,(~no_cars & (car_sufficiency < 0)) * shopping,,coef_car_shortage_vs_workers_and_number_of_shopping_tours,,,,,, +util_car_surplus_vs_workers_and_shopping_tour,Dummy for Car Surplus vs Workers & number of shopping tours,(~no_cars & (car_sufficiency > 0)) * shopping,,coef_car_surplus_vs_workers_and_number_of_shopping_tours,,,,,, +util_car_surplus_vs_workers_and_maintenance_tour,Dummy for Car Surplus vs Workers & number of maintenance tours,(~no_cars & (car_sufficiency > 0)) * othmaint,,,,,,,coef_car_surplus_vs_workers_and_number_of_maintenance_tours, +util_car_surplus_vs_workers_and_discretionary_tour,Dummy for Car Surplus vs Workers & number of discretionary tours,(~no_cars & (car_sufficiency > 0)) * othdiscr,,,,,,,coef_car_surplus_vs_workers_and_number_of_discretionary_tours, +util_number_of_full_time_worker_and_escorting_tour,Dummy for number of Full time Worker (other than modeled person) & Escorting tour ,num_full_time_workers_not_self * escort,coef_number_of_full_time_worker_and_escorting_tour,coef_number_of_full_time_worker_and_escorting_tour,coef_number_of_full_time_worker_and_escorting_tour,coef_number_of_full_time_worker_and_escorting_tour,coef_number_of_full_time_worker_and_escorting_tour,,, +util_number_of_part_time_worker_and_escorting_tour,Dummy for number of Part time Worker (other than modeled person) & Escorting tour ,num_part_time_workers_not_self * escort,coef_number_of_part_time_worker_and_escorting_tour,coef_number_of_part_time_worker_and_escorting_tour,coef_number_of_part_time_worker_and_escorting_tour,coef_number_of_part_time_worker_and_escorting_tour,coef_number_of_part_time_worker_and_escorting_tour,,,coef_number_of_part_time_worker_and_escorting_tour +util_number_of_non_worker_and_escorting_tour,Dummy for number of Non-Worker (other than modeled person) & Escorting tour ,num_non_workers_not_self * escort,coef_number_of_non_worker_and_escorting_tour,coef_number_of_non_worker_and_escorting_tour,coef_number_of_non_worker_and_escorting_tour,coef_number_of_non_worker_and_escorting_tour,coef_number_of_non_worker_and_escorting_tour,,,coef_number_of_non_worker_and_escorting_tour +util_number_of_retiree_and_escorting_tour,Dummy for number of Retiree (other than modeled person) & Escorting tour ,num_retirees_not_self * escort,coef_number_of_retiree_and_escorting_tour,,coef_number_of_retiree_and_escorting_tour,coef_number_of_retiree_and_escorting_tour,,,, +util_number_of_university_student_and_escorting_tour,Dummy for number of University Student (other than modeled person) & Escorting tour ,num_university_students_not_self * escort,coef_number_of_university_student_and_escorting_tour,coef_number_of_university_student_and_escorting_tour,coef_number_of_university_student_and_escorting_tour,coef_number_of_university_student_and_escorting_tour,,,,coef_number_of_university_student_and_escorting_tour +util_number_of_driving_school_kid_and_escorting_tour,Dummy for number of Driving School Kid (other than modeled person) & Escorting tour ,num_driving_age_students_not_self * escort,coef_number_of_driving_school_kid_and_escorting_tour,coef_number_of_driving_school_kid_and_escorting_tour,,coef_number_of_driving_school_kid_and_escorting_tour,coef_number_of_driving_school_kid_and_escorting_tour,,, +util_go_out_pre_driving_school_kid_and_escorting_tour,Dummy for number of Pre-Driving School Kid go out & Escorting tour ,num_pre_driving_age_school_kids_go_out * escort,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour,coef_go_out_pre_driving_school_kid_and_escorting_tour +util_go_out_pre_school_kid_and_escorting_tour,Dummy for Pre-School Kid going out & Escorting tour ,num_pre_school_kids_go_out * escort,coef_go_out_school_kid_and_escorting_tour,coef_go_out_school_kid_and_escorting_tour,coef_go_out_school_kid_and_escorting_tour,coef_go_out_school_kid_and_escorting_tour,,,,coef_go_out_school_kid_and_escorting_tour +util_number_of_full_time_worker_and_shopping_tour,Dummy for number of Full time Worker (other than modeled person) & Shopping tour ,num_full_time_workers_not_self * shopping,,coef_number_of_full_time_worker_and_shopping_tour,coef_number_of_full_time_worker_and_shopping_tour,,,coef_number_of_full_time_worker_and_shopping_tour,, +util_number_of_part_time_worker_and_shopping_tour,Dummy for number of Part time Worker (other than modeled person) & Shopping tour ,num_part_time_workers_not_self * shopping,,coef_number_of_part_time_worker_and_shopping_tour,coef_number_of_part_time_worker_and_shopping_tour,,,coef_number_of_part_time_worker_and_shopping_tour,, +util_number_of_non_worker_and_shopping_tour,Dummy for number of Non-Worker (other than modeled person) & Shopping tour ,num_non_workers_not_self * shopping,,coef_number_of_non_worker_and_shopping_tour,,coef_number_of_non_worker_and_shopping_tour,,coef_number_of_non_worker_and_shopping_tour,, +util_number_of_retiree_and_shopping_tour,Dummy for number of Retiree (other than modeled person) & Shopping tour ,num_retirees_not_self * shopping,,,,,coef_number_of_retiree_and_shopping_tour,,, +util_number_of_university_student_and_shopping_tour,Dummy for number of University Student (other than modeled person) & Shopping tour ,num_university_students_not_self * shopping,,,coef_number_of_university_student_and_shopping_tour,,,,, +util_number_of_driving_school_kid_and_shopping_tour,Dummy for number of Driving School Kid (other than modeled person) & Shopping tour ,num_driving_age_students_not_self * shopping,coef_number_of_driving_school_kid_and_shopping_tour,,,,,,coef_number_of_driving_school_kid_and_shopping_tour, +util_number_of_pre_driving_school_kid_and_shopping_tour,Dummy for number of Pre-Driving School Kid (other than modeled person) & Shopping tour ,num_pre_driving_age_school_kids_not_self * shopping,coef_number_of_pre_driving_school_kid_and_shopping_tour,,,,,coef_number_of_pre_driving_school_kid_and_shopping_tour,coef_number_of_pre_driving_school_kid_and_shopping_tour, +util_number_of_pre_school_kid_and_shopping_tour,Dummy for number of Pre-School Kid (other than modeled person) & Shopping tour ,num_pre_school_kids_not_self * shopping,coef_number_of_pre_school_kid_and_shopping_tour,,,,,coef_number_of_pre_school_kid_and_shopping_tour,coef_number_of_pre_school_kid_and_shopping_tour, +util_number_of_full_time_worker_and_maintenance_tour,Dummy for number of Full time Worker (other than modeled person) & Maintenance tour ,num_full_time_workers_not_self * othmaint,coef_number_of_full_time_worker_and_maintenance_tour,coef_number_of_full_time_worker_and_maintenance_tour,coef_number_of_full_time_worker_and_maintenance_tour,coef_number_of_full_time_worker_and_maintenance_tour,,,, +util_number_of_part_time_worker_and_maintenance_tour,Dummy for number of Part time Worker (other than modeled person) & Maintenance tour ,num_part_time_workers_not_self * othmaint,coef_number_of_part_time_worker_and_maintenance_tour,coef_number_of_part_time_worker_and_maintenance_tour,coef_number_of_part_time_worker_and_maintenance_tour,coef_number_of_part_time_worker_and_maintenance_tour,,,, +util_number_of_non_worker_and_maintenance_tour,Dummy for number of Non-Worker(other than modeled person) & Maintenance tour ,num_non_workers_not_self * othmaint,coef_number_of_non_worker_and_maintenance_tour,coef_number_of_non_worker_and_maintenance_tour,coef_number_of_non_worker_and_maintenance_tour,,,,, +util_number_of_retiree_and_maintenance_tour,Dummy for number of Retiree (other than modeled person) & Maintenance tour ,num_retirees_not_self * othmaint,,,,,coef_number_of_retiree_and_maintenance_tour,,, +util_number_of_university_student_and_maintenance_tour,Dummy for number of University Student (other than modeled person) & Maintenance tour ,num_university_students_not_self * othmaint,coef_number_of_university_student_and_maintenance_tour,,coef_number_of_university_student_and_maintenance_tour,,,,, +util_number_of_full_time_worker_and_eating_out_tour,Dummy for number of Full time Worker (other than modeled person) & Eating Out tour ,num_full_time_workers_not_self * eatout,coef_number_of_full_time_worker_and_eating_out_tour,coef_number_of_full_time_worker_and_eating_out_tour,,,,,, +util_number_of_part_time_worker_and_eating_out_tour,Dummy for number of Part time Worker (other than modeled person) & Eating Out tour ,num_part_time_workers_not_self * eatout,coef_number_of_part_time_worker_and_eating_out_tour,,,,,,, +util_number_of_non_worker_and_eating_out_tour,Dummy for number of Non-Worker (other than modeled person) & Eating Out tour ,num_non_workers_not_self * eatout,coef_number_of_non_worker_and_eating_out_tour,,,,,,, +util_number_of_retiree_and_eating_out_tour,Dummy for number of Retiree (other than modeled person) & Eating Out tour ,num_retirees_not_self * eatout,coef_number_of_retiree_and_eating_out_tour,,,,,,, +util_number_of_university_student_and_eating_out_tour,Dummy for number of University Student (other than modeled person) & Eating Out tour ,num_university_students_not_self * eatout,coef_number_of_university_student_and_eating_out_tour,,,,,,, +util_number_of_pre_driving_school_kid_and_eating_out_tour,Dummy for number of Pre-Driving School Kid (other than modeled person) & Eating Out tour ,num_pre_driving_age_school_kids_not_self * eatout,coef_number_of_pre_driving_school_kid_and_eating_out_tour,,,coef_number_of_pre_driving_school_kid_and_eating_out_tour,,,, +util_number_of_pre_school_kid_and_eating_out_tour,Dummy for number of Pre-School Kid (other than modeled person) & Eating Out tour ,num_pre_school_kids_not_self * eatout,coef_number_of_pre_school_kid_and_eating_out_tour,,,coef_number_of_pre_school_kid_and_eating_out_tour,,,, +util_number_of_part_time_worker_and_visiting_tour,Dummy for number of Part time Worker (other than modeled person) & Visiting tour ,num_part_time_workers_not_self * social,,coef_number_of_part_time_worker_and_visiting_tour,,,,,, +util_number_of_non_worker_and_visiting_tour,Dummy for number of Non-Worker (other than modeled person) & Visiting tour ,num_non_workers_not_self * social,coef_number_of_non_worker_and_visiting_tour,,,,,,, +util_number_of_retiree_and_visiting_tour,Dummy for number of Retiree (other than modeled person) & Visiting tour ,num_retirees_not_self * social,coef_number_of_retiree_and_visiting_tour,coef_number_of_retiree_and_visiting_tour,,,coef_number_of_retiree_and_visiting_tour,,, +util_number_of_university_student_and_visiting_tour,Dummy for number of University Student (other than modeled person) & Visiting tour ,num_university_students_not_self * social,coef_number_of_university_student_and_visiting_tour,,,,,,, +util_number_of_driving_school_kid_and_visiting_tour,Dummy for number of Driving School Kid (other than modeled person) & visiting tour ,num_driving_age_students_not_self * social,,coef_number_of_driving_school_kid_and_visiting_tour,,,,,coef_number_of_driving_school_kid_and_visiting_tour, +util_number_of_pre_driving_school_kid_and_visiting_tour,Dummy for number of Pre-Driving School Kid (other than modeled person) & visiting tour ,num_pre_driving_age_school_kids_not_self * social,,coef_number_of_pre_driving_school_kid_and_visiting_tour,,coef_number_of_pre_driving_school_kid_and_visiting_tour,,,coef_number_of_pre_driving_school_kid_and_visiting_tour, +util_number_of_pre_school_kid_and_visiting_tour,Dummy for number of Pre-School Kid (other than modeled person) & visiting tour ,num_pre_school_kids_not_self * social,,coef_number_of_pre_school_kid_and_visiting_tour,,coef_number_of_pre_school_kid_and_visiting_tour,,,coef_number_of_pre_school_kid_and_visiting_tour, +util_number_of_part_time_worker_and_discretionary_tour,Dummy for number of Part time Worker (other than modeled person) & Discretionary tour ,num_part_time_workers_not_self * othdiscr,,,,,,coef_number_of_part_time_worker_and_discretionary_tour,, +util_number_of_non_worker_and_discretionary_tour,Dummy for number of Non-Worker (other than modeled person) & Discretionary tour ,num_non_workers_not_self * othdiscr,,,,,,coef_number_of_non_worker_and_discretionary_tour,, +util_number_of_university_student_and_discretionary_tour,Dummy for number of University Student (other than modeled person) & Discretionary tour ,num_university_students_not_self * othdiscr,,,coef_number_of_university_student_and_discretionary_tour,,,coef_number_of_university_student_and_discretionary_tour,, +util_number_of_driving_school_kid_and_discretionary_tour,Dummy for number of Driving School Kid (other than modeled person) & Discretionary tour ,num_driving_age_students_not_self * othdiscr,coef_number_of_driving_school_kid_and_discretionary_tour,coef_number_of_driving_school_kid_and_discretionary_tour,,coef_number_of_driving_school_kid_and_discretionary_tour,,,coef_number_of_driving_school_kid_and_discretionary_tour, +util_number_of_pre_driving_school_kid_and_discretionary_tour,Dummy for number of Pre-Driving School Kid (other than modeled person) & Discretionary tour ,num_pre_driving_age_school_kids_not_self * othdiscr,coef_number_of_pre_driving_school_kid_and_discretionary_tour,coef_number_of_pre_driving_school_kid_and_discretionary_tour,,coef_number_of_pre_driving_school_kid_and_discretionary_tour,,,coef_number_of_pre_driving_school_kid_and_discretionary_tour, +util_number_of_pre_school_kid_and_discretionary_tour,Dummy for number of Pre-School Kid (other than modeled person) & Discretionary tour ,num_pre_school_kids_not_self * othdiscr,coef_number_of_pre_school_kid_and_discretionary_tour,coef_number_of_pre_school_kid_and_discretionary_tour,,coef_number_of_pre_school_kid_and_discretionary_tour,,,coef_number_of_pre_school_kid_and_discretionary_tour, +util_retired_hh_and_escorting,"Household Type (All Retirees and Non-workers only), Escorting",retiredHh * escort,,,,,coef_retired_hh_and_escorting_tour,,, +util_retired_hh_and_shopping,"Household Type (All Retirees and Non-workers only), Shopping",retiredHh * shopping,,,,,coef_retired_hh_and_shopping_tour,,, +util_retired_hh_and_eating_out,"Household Type (All Retirees and Non-workers only), Eating out",retiredHh * eatout,,,,,coef_retired_hh_and_eating_out_tour,,, +util_retired_hh_and_discretionary,"Household Type (All Retirees and Non-workers only), Discretionary",retiredHh * othdiscr,,,,,coef_retired_hh_and_discretionary_tour,,, +util_work_accessibility_and_tour_frequency_is_1,Work Accessibility & Tour Frequency =1,WorkLocationLogsum * ((tot_tours == 1) & (cdap_activity == 'M')),coef_work_accessibility_and_tour_frequency_is_1,coef_work_accessibility_and_tour_frequency_is_1,,,,,, +util_work_accessibility_and_tour_frequency_is_2,Work Accessibility & Tour Frequency =2,WorkLocationLogsum * ((tot_tours == 2) & (cdap_activity == 'M')),coef_work_accessibility_and_tour_frequency_is_2,coef_work_accessibility_and_tour_frequency_is_2,,,,,, +util_work_accessibility_and_tour_frequency_is_3,Work Accessibility & Tour Frequency =3,WorkLocationLogsum * ((tot_tours == 3) & (cdap_activity == 'M')),coef_work_accessibility_and_tour_frequency_is_3,,,,,,, +util_work_accessibility_and_tour_frequency_is_3_plus,Work Accessibility & Tour Frequency =3+,WorkLocationLogsum * ((tot_tours >= 3) & (cdap_activity == 'M')),,coef_work_accessibility_and_tour_frequency_is_3_plus,,,,,, +util_work_accessibility_and_tour_frequency_is_4,Work Accessibility & Tour Frequency =4,WorkLocationLogsum * ((tot_tours == 4) & (cdap_activity == 'M')),coef_work_accessibility_and_tour_frequency_is_4,,,,,,, +util_work_accessibility_and_tour_frequency_is_5_plus,Work Accessibility & Tour Frequency =5+,WorkLocationLogsum * ((tot_tours > 5) & (cdap_activity == 'M')),coef_work_accessibility_and_tour_frequency_is_5_plus,,,,,,, +util_school_accessibility_and_tour_frequency_is_1,School Accessibility & Tour Frequency =1,SchoolLocationLogsum * ((tot_tours == 1) & (cdap_activity == 'M')),,,,,,,coef_school_accessibility_and_tour_frequency_is_1, +util_school_accessibility_and_tour_frequency_is_1_plus,School Accessibility & Tour Frequency =1+,SchoolLocationLogsum * ((tot_tours >= 1) & (cdap_activity == 'M')),,,coef_school_accessibility_and_tour_frequency_is_1_plus,,,,, +util_school_accessibility_and_tour_frequency_is_2_plus,School Accessibility & Tour Frequency =2+,SchoolLocationLogsum * ((tot_tours >= 2) & (cdap_activity == 'M')),,,,,,coef_school_accessibility_and_tour_frequency_is_2_plus,coef_school_accessibility_and_tour_frequency_is_2_plus, +util_work_from_home_and_tour_frequency_is_1,Work From Home & Tour Frequency =1,(WorkLocation==99999) & (tot_tours == 1),coef_work_from_home_and_tour_frequency_is_1,,,,,,, +util_work_from_home_and_tour_frequency_is_2,Work From Home & Tour Frequency =2,(WorkLocation==99999) & (tot_tours == 2),coef_work_from_home_and_tour_frequency_is_2,,,,,,, +util_work_from_home_and_tour_frequency_is_3,Work From Home & Tour Frequency =3,(WorkLocation==99999) & (tot_tours == 3),coef_work_from_home_and_tour_frequency_is_3,,,,,,, +util_work_from_home_and_tour_frequency_is_4,Work From Home & Tour Frequency =4,(WorkLocation==99999) & (tot_tours == 4),coef_work_from_home_and_tour_frequency_is_4,,,,,,, +util_work_from_home_and_tour_frequency_is_5_plus,Work From Home & Tour Frequency =5+,(WorkLocation==99999) & (tot_tours > 5),coef_work_from_home_and_tour_frequency_is_5_plus,,,,,,, +util_retail_accessibility_for_escorting,Retail Accessibility for Escorting,((autosnum_workers)*escort_hov_oversufficient_accessibility)*escort,coef_retail_accessibility_for_escorting,coef_retail_accessibility_for_escorting,,coef_retail_accessibility_for_escorting,coef_retail_accessibility_for_escorting,,coef_retail_accessibility_for_escorting,coef_retail_accessibility_for_escorting +util_retail_accessibility_for_shopping,Retail Accessibility for Shopping,((autosnum_workers)*shop_hov_oversufficient_accessibility)*shopping,coef_retail_accessibility_for_shopping,,,,coef_retail_accessibility_for_shopping,coef_retail_accessibility_for_shopping,coef_retail_accessibility_for_shopping,coef_retail_accessibility_for_shopping +util_retail_accessibility_for_maintenance,Retail Accessibility for Maintenance,((autosnum_workers)*maint_hov_oversufficient_accessibility)*othmaint,coef_retail_accessibility_for_maintenance,coef_retail_accessibility_for_maintenance,,coef_retail_accessibility_for_maintenance,coef_retail_accessibility_for_maintenance,,coef_retail_accessibility_for_maintenance, +util_retail_accessibility_for_eating_out,Retail Accessibility for Eating Out,((autosnum_workers)*eat_hov_oversufficient_accessibility)*eatout,coef_retail_accessibility_for_eating_out,coef_retail_accessibility_for_eating_out,,,,coef_retail_accessibility_for_eating_out,coef_retail_accessibility_for_eating_out, +util_retail_accessibility_for_discretionary,Retail Accessibility for Discretionary,((autosnum_workers)*discr_hov_oversufficient_accessibility)*othdiscr,,,coef_retail_accessibility_for_discretionary,coef_retail_accessibility_for_discretionary,coef_retail_accessibility_for_discretionary,,coef_retail_accessibility_for_discretionary, +util_retail_accessibility_for_visiting,Retail Accessibility for Visiting,((autosnum_workers)*visit_hov_oversufficient_accessibility)*othdiscr,,,,coef_retail_accessibility_for_visiting,coef_retail_accessibility_for_visiting,,, +util_walk_accessibility_for_discretionary,Walk Accessibility for Discretionary,nonmandatory_nm_accessibility *othdiscr,coef_walk_accessibility_for_discretionary,coef_walk_accessibility_for_discretionary,,,,,, +util_walk_accessibility_for_eat_out,Walk Accessibility for Eating Out,nonmandatory_nm_accessibility *eatout,,,coef_walk_accessibility_for_eatout,coef_walk_accessibility_for_eatout,,,, +util_origin_population_density_for_visiting,Population Density & Visiting tour,PopDen * social,,coef_origin_population_density_for_visiting,,,,,, +util_college_education_and_escorting,College Education & Escorting tour,(education_attainment>=13) * escort,,,,,coef_college_education_for_escorting,,, +util_college_education_and_visiting,College Education & Visiting tour,(education_attainment>=13) * social,coef_college_education_for_visiting,,,,coef_college_education_for_visiting,,, +util_college_education_and_discretionary,College Education & Discretionary tour,(education_attainment>=13) * othdiscr,coef_college_education_for_discretionary,coef_college_education_for_discretionary,,coef_college_education_for_discretionary,coef_college_education_for_discretionary,,, +util_college_education_and_shopping,College Education & Shopping tour,(education_attainment>=13) * shopping,,,,coef_college_education_for_shopping,coef_college_education_for_shopping,,, +util_college_education_and_maintenance,College Education & Maintenance tour,(education_attainment>=13) * othmaint,,,,coef_college_education_for_maintenance,,,, +util_college_education_and_eating_out,College Education & Eating out tour,(education_attainment>=13) * eatout,,,,coef_college_education_for_eatout,,,, +util_low_education_and_visiting,Less than High School Education & Visiting tour,(education_attainment<9) * social,coef_low_education_for_visiting,,,coef_low_education_for_visiting,,,, +util_low_education_and_discretionary,Less than High School Education & Discretionary tour,(education_attainment<9) * othdiscr,,coef_low_education_for_discretionary,,coef_low_education_for_discretionary,coef_low_education_for_discretionary,,, +util_low_education_and_escorting,Less than High School Education & Escorting tour,(education_attainment<9) * escort,,,,coef_low_education_for_escorting,coef_low_education_for_escorting,,, +util_low_education_and_shopping,Less than High School Education & Shopping tour,(education_attainment<9) * shopping,,,,coef_low_education_for_shopping,coef_low_education_for_shopping,,, +util_low_education_and_eating_out,Less than High School Education & Eating out tour,(education_attainment<9) * eatout,,,,coef_low_education_for_eatout,,,, +util_low_education_and_maintenance,Less than High School Education & Maintenance tour,(education_attainment<9) * othmaint,,,,,coef_low_education_for_maintenance,,, +util_detached_household_and_escorting_tour,Detached Household & Escorting tour,(building_size==1) * escort,coef_detached_household_and_escorting,coef_detached_household_and_escorting,,,coef_detached_household_and_escorting,,, +util_detached_household_and_eat_out,Detached Household & Eating out tour,(building_size==1) * eatout,,coef_detached_household_and_eating_out,,,coef_detached_household_and_eating_out,,, +util_detached_household_and_discretionary,Detached Household & discretionary tour,(building_size==1) * othdiscr,,,coef_detached_household_and_discretionary,,coef_detached_household_and_discretionary,,, +util_1_escort_tour_constant,1 Escort Tour Constant,escort == 1,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant,coef_1_escort_tour_constant +util_2_plus_escort_tours_constant,2+ Escort Tours Constant,escort >= 2,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant,coef_2_plus_escort_tours_constant +util_1_shopping_tours_constant,1 Shopping Tours Constant,shopping == 1,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant,coef_1_shopping_tours_constant +util_2_plus_shopping_tours_constant,2+ Shopping Tours Constant,shopping >= 2,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant,coef_2_plus_shopping_tours_constant +util_1_maintenance_tours_constant,1 Maintenance Tours Constant,othmaint == 1,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant,coef_1_maintenance_tours_constant +util_2_plus_maintenance_tours_constant,2+ Maintenance Tours Constant,othmaint >= 2,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant,coef_2_plus_maintenance_tours_constant +util_1_plus_eating_out_tours_constant,1+ Eating Out Tours Constant,(eatout >= 1) * eatout,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant,coef_1_plus_eating_out_tours_constant +util_1_plus_visting_tours_constant,1+ Visting Tours Constant,(social >= 1) * social,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant,coef_1_plus_visting_tours_constant +util_1_other_discretionary_tours_constant,1 Other Discretionary Tours Constant,othdiscr == 1,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant,coef_1_other_discretionary_tours_constant +util_2_plus_other_discretionary_tours_constant,2+ Other Discretionary Tours Constant,othdiscr >= 2,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant,coef_2_plus_other_discretionary_tours_constant +util_1_escort_tour_constant_tm2,1 Escort Tour constant_tm2,escort == 1,,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2,coef_1_escort_tour_constant_tm2 +util_2_plus_escort_tours_constant_tm2,2+ Escort Tours constant_tm2,escort >= 2,,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2,coef_2_plus_escort_tours_constant_tm2 +util_1_shopping_tours_constant_tm2,1 Shopping Tours constant_tm2,shopping == 1,,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2,coef_1_shopping_tours_constant_tm2 +util_2_plus_shopping_tours_constant_tm2,2+ Shopping Tours constant_tm2,shopping >= 2,,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2,coef_2_plus_shopping_tours_constant_tm2 +util_1_maintenance_tours_constant_tm2,1 Maintenance Tours constant_tm2,othmaint == 1,,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2,coef_1_maintenance_tours_constant_tm2 +util_2_plus_maintenance_tours_constant_tm2,2+ Maintenance Tours constant_tm2,othmaint >= 2,,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2,coef_2_plus_maintenance_tours_constant_tm2 +util_1_plus_eating_out_tours_constant_tm2,1+ Eating Out Tours constant_tm2,(eatout >= 1) * eatout,,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2,coef_1_plus_eating_out_tours_constant_tm2 +util_1_plus_visting_tours_constant_tm2,1+ Visting Tours constant_tm2,(social >= 1) * social,,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2,coef_1_plus_visting_tours_constant_tm2 +util_1_other_discretionary_tours_constant_tm2,1 Other Discretionary Tours constant_tm2,othdiscr == 1,,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2,coef_1_other_discretionary_tours_constant_tm2 +util_2_plus_other_discretionary_tours_constant_tm2,2+ Other Discretionary Tours constant_tm2,othdiscr >= 2,,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2,coef_2_plus_other_discretionary_tours_constant_tm2 +util_mandatory_dap_and_1_non_mand_tour_ABM_2_calib,Mandatory and 1 Non-Mandatory - ABM2 Calibration,(cdap_activity=='M') & (tot_tours==1),coef_mandatory_dap_and_1_non_mand_tour,coef_mandatory_dap_and_1_non_mand_tour,coef_mandatory_dap_and_1_non_mand_tour,,,coef_mandatory_dap_and_1_non_mand_tour,coef_mandatory_dap_and_1_non_mand_tour, +util_mandatory_dap_and_2_non_mand_tour_ABM_2_calib,Mandatory and 2 Non-Mandatory - ABM2 Calibration,(cdap_activity=='M') & (tot_tours==2),coef_mandatory_dap_and_2_non_mand_tour,coef_mandatory_dap_and_2_non_mand_tour,coef_mandatory_dap_and_2_non_mand_tour,,,coef_mandatory_dap_and_2_non_mand_tour,coef_mandatory_dap_and_2_non_mand_tour, +util_mandatory_dap_and_3_plus_non_mand_tour_ABM_2_calib,Mandatory and 3+ Non-Mandatory - ABM2 Calibration,(cdap_activity=='M') & (tot_tours>=3),coef_mandatory_dap_and_3_plus_non_mand_tour,coef_mandatory_dap_and_3_plus_non_mand_tour,coef_mandatory_dap_and_3_plus_non_mand_tour,,,coef_mandatory_dap_and_3_plus_non_mand_tour,coef_mandatory_dap_and_3_plus_non_mand_tour, +util_non_mandatory_dap_and_1_non_mand_tour_ABM_2_calib,0 Mandatory and 1 Non-Mandatory - ABM2 Calibration,(cdap_activity=='N') & (tot_tours==1),coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour,coef_non_mandatory_dap_and_1_non_mand_tour +util_non_mandatory_dap_and_2_non_mand_tour_ABM_2_calib,0 Mandatory and 2 Non-Mandatory - ABM2 Calibration,(cdap_activity=='N') & (tot_tours==2),coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour,coef_non_mandatory_dap_and_2_non_mand_tour +util_non_mandatory_dap_and_3_non_mand_tour_ABM_2_calib,0 Mandatory and 3 Non-Mandatory - ABM2 Calibration,(cdap_activity=='N') & (tot_tours==3),coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour,coef_non_mandatory_dap_and_3_non_mand_tour +util_non_mandatory_dap_and_4_plus_non_mand_tour_ABM_2_calib,0 Mandatory and 4+ Non-Mandatory - ABM2 Calibration,(cdap_activity=='N') & (tot_tours>=4),coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour,coef_non_mandatory_dap_and_4_plus_non_mand_tour diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.yaml b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.yaml new file mode 100644 index 000000000..53f56d613 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency.yaml @@ -0,0 +1,52 @@ + +SEGMENT_COL: ptype +SPEC: non_mandatory_tour_frequency.csv + +SPEC_SEGMENTS: + - NAME: PTYPE_FULL + PTYPE: 1 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_FULL.csv + - NAME: PTYPE_PART + PTYPE: 2 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_PART.csv + - NAME: PTYPE_UNIVERSITY + PTYPE: 3 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_UNIVERSITY.csv + - NAME: PTYPE_NONWORK + PTYPE: 4 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_NONWORK.csv + - NAME: PTYPE_RETIRED + PTYPE: 5 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_RETIRED.csv + - NAME: PTYPE_DRIVING + PTYPE: 6 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_DRIVING.csv + - NAME: PTYPE_SCHOOL + PTYPE: 7 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_SCHOOL.csv + - NAME: PTYPE_PRESCHOOL + PTYPE: 8 + COEFFICIENTS: non_mandatory_tour_frequency_coefficients_PTYPE_PRESCHOOL.csv + +annotate_persons: + SPEC: annotate_persons_nmtf + DF: persons + TABLES: + - tours + +preprocessor: + SPEC: non_mandatory_tour_frequency_annotate_persons_preprocessor + DF: persons + TABLES: + - tours +# - accessibility + +CONSTANTS: + PTYPE_FULL: 1 + PTYPE_PART: 2 + PTYPE_UNIVERSITY: 3 + PTYPE_NONWORK: 4 + PTYPE_RETIRED: 5 + PTYPE_DRIVING: 6 + PTYPE_SCHOOL: 7 + PTYPE_PRESCHOOL: 8 diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_alternatives.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_alternatives.csv new file mode 100644 index 000000000..e4d4f2e4a --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_alternatives.csv @@ -0,0 +1,198 @@ +escort,shopping,othmaint,eatout,social,othdiscr +0,0,0,0,0,0 +0,0,0,0,0,1 +0,0,0,0,0,2 +0,0,0,0,1,0 +0,0,0,0,1,1 +0,0,0,0,1,2 +0,0,0,1,0,0 +0,0,0,1,0,1 +0,0,0,1,0,2 +0,0,0,1,1,0 +0,0,0,1,1,1 +0,0,0,1,1,2 +0,0,1,0,0,0 +0,0,1,0,0,1 +0,0,1,0,0,2 +0,0,1,0,1,0 +0,0,1,0,1,1 +0,0,1,0,1,2 +0,0,1,1,0,0 +0,0,1,1,0,1 +0,0,1,1,0,2 +0,0,1,1,1,0 +0,0,1,1,1,1 +0,0,1,1,1,2 +0,0,2,0,0,0 +0,0,2,0,0,1 +0,0,2,0,0,2 +0,0,2,0,1,0 +0,0,2,0,1,1 +0,0,2,0,1,2 +0,0,2,1,0,0 +0,0,2,1,0,1 +0,0,2,1,0,2 +0,0,2,1,1,0 +0,0,2,1,1,1 +0,1,0,0,0,0 +0,1,0,0,0,1 +0,1,0,0,0,2 +0,1,0,0,1,0 +0,1,0,0,1,1 +0,1,0,0,1,2 +0,1,0,1,0,0 +0,1,0,1,0,1 +0,1,0,1,0,2 +0,1,0,1,1,0 +0,1,0,1,1,1 +0,1,0,1,1,2 +0,1,1,0,0,0 +0,1,1,0,0,1 +0,1,1,0,0,2 +0,1,1,0,1,0 +0,1,1,0,1,1 +0,1,1,0,1,2 +0,1,1,1,0,0 +0,1,1,1,0,1 +0,1,1,1,0,2 +0,1,1,1,1,0 +0,1,1,1,1,1 +0,1,2,0,0,0 +0,1,2,0,0,1 +0,1,2,0,0,2 +0,1,2,0,1,0 +0,1,2,0,1,1 +0,1,2,1,0,0 +0,1,2,1,0,1 +0,1,2,1,1,0 +0,2,0,0,0,0 +0,2,0,0,0,1 +0,2,0,0,0,2 +0,2,0,0,1,0 +0,2,0,0,1,1 +0,2,0,0,1,2 +0,2,0,1,0,0 +0,2,0,1,0,1 +0,2,0,1,0,2 +0,2,0,1,1,0 +0,2,0,1,1,1 +0,2,1,0,0,0 +0,2,1,0,0,1 +0,2,1,0,0,2 +0,2,1,0,1,0 +0,2,1,0,1,1 +0,2,1,1,0,0 +0,2,1,1,0,1 +0,2,1,1,1,0 +0,2,2,0,0,0 +0,2,2,0,0,1 +0,2,2,0,1,0 +0,2,2,1,0,0 +1,0,0,0,0,0 +1,0,0,0,0,1 +1,0,0,0,0,2 +1,0,0,0,1,0 +1,0,0,0,1,1 +1,0,0,0,1,2 +1,0,0,1,0,0 +1,0,0,1,0,1 +1,0,0,1,0,2 +1,0,0,1,1,0 +1,0,0,1,1,1 +1,0,0,1,1,2 +1,0,1,0,0,0 +1,0,1,0,0,1 +1,0,1,0,0,2 +1,0,1,0,1,0 +1,0,1,0,1,1 +1,0,1,0,1,2 +1,0,1,1,0,0 +1,0,1,1,0,1 +1,0,1,1,0,2 +1,0,1,1,1,0 +1,0,1,1,1,1 +1,0,2,0,0,0 +1,0,2,0,0,1 +1,0,2,0,0,2 +1,0,2,0,1,0 +1,0,2,0,1,1 +1,0,2,1,0,0 +1,0,2,1,0,1 +1,0,2,1,1,0 +1,1,0,0,0,0 +1,1,0,0,0,1 +1,1,0,0,0,2 +1,1,0,0,1,0 +1,1,0,0,1,1 +1,1,0,0,1,2 +1,1,0,1,0,0 +1,1,0,1,0,1 +1,1,0,1,0,2 +1,1,0,1,1,0 +1,1,0,1,1,1 +1,1,1,0,0,0 +1,1,1,0,0,1 +1,1,1,0,0,2 +1,1,1,0,1,0 +1,1,1,0,1,1 +1,1,1,1,0,0 +1,1,1,1,0,1 +1,1,1,1,1,0 +1,1,2,0,0,0 +1,1,2,0,0,1 +1,1,2,0,1,0 +1,1,2,1,0,0 +1,2,0,0,0,0 +1,2,0,0,0,1 +1,2,0,0,0,2 +1,2,0,0,1,0 +1,2,0,0,1,1 +1,2,0,1,0,0 +1,2,0,1,0,1 +1,2,0,1,1,0 +1,2,1,0,0,0 +1,2,1,0,0,1 +1,2,1,0,1,0 +1,2,1,1,0,0 +1,2,2,0,0,0 +2,0,0,0,0,0 +2,0,0,0,0,1 +2,0,0,0,0,2 +2,0,0,0,1,0 +2,0,0,0,1,1 +2,0,0,0,1,2 +2,0,0,1,0,0 +2,0,0,1,0,1 +2,0,0,1,0,2 +2,0,0,1,1,0 +2,0,0,1,1,1 +2,0,1,0,0,0 +2,0,1,0,0,1 +2,0,1,0,0,2 +2,0,1,0,1,0 +2,0,1,0,1,1 +2,0,1,1,0,0 +2,0,1,1,0,1 +2,0,1,1,1,0 +2,0,2,0,0,0 +2,0,2,0,0,1 +2,0,2,0,1,0 +2,0,2,1,0,0 +2,1,0,0,0,0 +2,1,0,0,0,1 +2,1,0,0,0,2 +2,1,0,0,1,0 +2,1,0,0,1,1 +2,1,0,1,0,0 +2,1,0,1,0,1 +2,1,0,1,1,0 +2,1,1,0,0,0 +2,1,1,0,0,1 +2,1,1,0,1,0 +2,1,1,1,0,0 +2,1,2,0,0,0 +2,2,0,0,0,0 +2,2,0,0,0,1 +2,2,0,0,1,0 +2,2,0,1,0,0 +2,2,1,0,0,0 diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_annotate_persons_preprocessor.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_annotate_persons_preprocessor.csv new file mode 100644 index 000000000..9b63dbc42 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_annotate_persons_preprocessor.csv @@ -0,0 +1,36 @@ +Description,Target,Expression +#,, +,low_income,persons.income<=30000 +,medium_low_income,(persons.income > 30000) & (persons.income <= 60000) +,medium_income,(persons.income > 60000) & (persons.income <= 100000) +,medium_high_income,(persons.income > 100000) & (persons.income <= 150000) +,high_income,(persons.income > 150000) +,no_cars,(persons.auto_ownership == 0) +,car_sufficiency,persons.autos-persons.num_workers +#,, +# joint tour counts per persons,, +get joint tours,_JOINT_TOURS,tours[tours.tour_category=='JOINT_NON_MANDATORY'] +create participant list in joint tours,_JOINT_TOURS,"_JOINT_TOURS.assign(person_num=_JOINT_TOURS.apply(lambda x: [int(p) for p in x.tour_participants.split(' ')],axis=1))" +explode joint tour participants,_JOINT_TOURS,_JOINT_TOURS.explode('person_num') +join joint tour info with persons,_JOINT_TOURS_PERSONS,"pd.merge(_JOINT_TOURS[['household_id','person_num','tour_purpose']],persons.reset_index()[['household_id','person_num','person_id']], on=['household_id','person_num'], how='left')" +,num_person_joint_tours,"reindex_i(_JOINT_TOURS_PERSONS.groupby(['person_id']).size(), persons.index)" +,num_person_joint_shop_tours,"reindex_i(_JOINT_TOURS_PERSONS[_JOINT_TOURS_PERSONS.tour_purpose=='Shop'].groupby(['person_id']).size(), persons.index)" +,num_person_joint_maint_tours,"reindex_i(_JOINT_TOURS_PERSONS[_JOINT_TOURS_PERSONS.tour_purpose=='Maintenance'].groupby(['person_id']).size(), persons.index)" +,num_person_joint_eatout_tours,"reindex_i(_JOINT_TOURS_PERSONS[_JOINT_TOURS_PERSONS.tour_purpose=='Eating Out'].groupby(['person_id']).size(), persons.index)" +,num_person_joint_visit_tours,"reindex_i(_JOINT_TOURS_PERSONS[_JOINT_TOURS_PERSONS.tour_purpose=='Visiting'].groupby(['person_id']).size(), persons.index)" +,num_person_joint_othdiscr_tours,"reindex_i(_JOINT_TOURS_PERSONS[_JOINT_TOURS_PERSONS.tour_purpose=='Discretionary'].groupby(['person_id']).size(), persons.index)" +# non_mandatory tour frequency extension,, +,_INDIV_TOURS,tours[tours.tour_category!='JOINT_NON_MANDATORY'] +,num_mandatory_tours,"reindex_i(_INDIV_TOURS[_INDIV_TOURS.tour_purpose=='MANDATORY'].groupby('person_id').size(), persons.index)" +,has_mandatory_tour,(num_mandatory_tours > 0) * 1 +,has_joint_tour,(num_person_joint_tours > 0) * 1 +# number of person types in household in addition to self,, +,num_full_time_workers_not_self,"np.where(df.ptype == PTYPE_FULL, df.num_full_time_workers-1, df.num_full_time_workers)" +,num_part_time_workers_not_self,"np.where(df.ptype == PTYPE_PART, df.num_part_time_workers-1, df.num_part_time_workers)" +,num_university_students_not_self,"np.where(df.ptype == PTYPE_UNIVERSITY, df.num_university_students-1, df.num_university_students)" +,num_non_workers_not_self,"np.where(df.ptype == PTYPE_NONWORK, df.num_non_workers-1, df.num_non_workers)" +,num_retirees_not_self,"np.where(df.ptype == PTYPE_RETIRED, df.num_retirees-1, df.num_retirees)" +,num_driving_age_students_not_self,"np.where(df.ptype == PTYPE_DRIVING, df.num_driving_age_students-1, df.num_driving_age_students)" +,num_pre_driving_age_school_kids_not_self,"np.where(df.ptype == PTYPE_SCHOOL, df.num_pre_driving_age_school_kids-1, df.num_pre_driving_age_school_kids)" +,num_pre_school_kids_not_self,"np.where(df.ptype == PTYPE_PRESCHOOL, df.num_pre_school_kids-1, df.num_pre_school_kids)" +,retiredHh,"np.where(df.num_full_time_workers+df.num_part_time_workers+df.num_university_students+df.num_driving_age_students+df.num_pre_driving_age_school_kids+df.num_pre_school_kids == 0,1,0)" \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_DRIVING.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_DRIVING.csv new file mode 100644 index 000000000..7d443b83a --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_DRIVING.csv @@ -0,0 +1,60 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-5.0011,F +coef_discretionary_tour,-2.0687,F +coef_shopping_tour,-16.7785,F +coef_maintenance_tour,-3.2583,F +coef_visiting_or_social_tour,-2.6366,F +coef_eating_out_tour,-18.1598,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_1_plus,-0.4825,F +coef_has_mandatory_tours_and_tour_frequency_is_2_plus,-2.5161,F +coef_number_of_joint_discretionary_tours,-0.2308,F +coef_more_than_one_discretionary_tours,-1.1938,F +coef_low_income_group_and_escorting_tour,1.1208,F +coef_medium_low_income_group_and_escorting_tour,1.1208,F +coef_low_income_group_and_discretionary_tour,-0.8053,F +coef_mediumhigh_income_group_and_discretionary_tour,0.5225,F +coef_high_income_group_and_discretionary_tour,0.8604,F +coef_high_income_group_and_visiting_tour,0.5513,F +coef_mediumhigh_income_group_and_visiting_tour,0.5513,F +coef_female_and_shopping_tour,0.9646,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.4901,F +coef_number_of_full_time_worker_and_shopping_tour,0.3173,F +coef_number_of_part_time_worker_and_shopping_tour,0.3173,F +coef_number_of_non_worker_and_shopping_tour,0.3173,F +coef_number_of_pre_driving_school_kid_and_shopping_tour,0.3133,F +coef_number_of_pre_school_kid_and_shopping_tour,0.3133,F +coef_number_of_part_time_worker_and_discretionary_tour,0.3202,F +coef_number_of_non_worker_and_discretionary_tour,0.3202,F +coef_number_of_university_student_and_discretionary_tour,0.5522,F +coef_school_accessibility_and_tour_frequency_is_2_plus,1.9398,F +coef_retail_accessibility_for_shopping,0.7809,F +coef_retail_accessibility_for_eating_out,1.0093,F +coef_1_escort_tour_constant,-0.052,F +coef_2_plus_escort_tours_constant,0,T +coef_1_shopping_tours_constant,1.025,F +coef_2_plus_shopping_tours_constant,0,T +coef_1_maintenance_tours_constant,-0.294,F +coef_2_plus_maintenance_tours_constant,0,T +coef_1_plus_eating_out_tours_constant,-1.079,F +coef_1_plus_visting_tours_constant,-0.107,F +coef_1_other_discretionary_tours_constant,-0.393,F +coef_2_plus_other_discretionary_tours_constant,-1.086,F +coef_1_escort_tour_constant_tm2,-1.007,F +coef_2_plus_escort_tours_constant_tm2,0,T +coef_1_shopping_tours_constant_tm2,1.027,F +coef_2_plus_shopping_tours_constant_tm2,1.027,F +coef_1_maintenance_tours_constant_tm2,-0.196,F +coef_2_plus_maintenance_tours_constant_tm2,-0.196,F +coef_1_plus_eating_out_tours_constant_tm2,2.909,F +coef_1_plus_visting_tours_constant_tm2,-1.417,F +coef_1_other_discretionary_tours_constant_tm2,-1.519,F +coef_2_plus_other_discretionary_tours_constant_tm2,-1.519,F +coef_mandatory_dap_and_1_non_mand_tour,1.222628436,F +coef_mandatory_dap_and_2_non_mand_tour,0.593278832,F +coef_mandatory_dap_and_3_plus_non_mand_tour,0.070965231,F +coef_non_mandatory_dap_and_1_non_mand_tour,0.756307862,F +coef_non_mandatory_dap_and_2_non_mand_tour,1.396284118,F +coef_non_mandatory_dap_and_3_non_mand_tour,3.551847757,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,-0.058600545,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_FULL.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_FULL.csv new file mode 100644 index 000000000..bfe82bc6b --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_FULL.csv @@ -0,0 +1,103 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-8.005637824,F +coef_discretionary_tour,-4.191895252,F +coef_shopping_tour,-6.093236864,F +coef_maintenance_tour,-4.450826306,F +coef_visiting_or_social_tour,-3.869879887,F +coef_eating_out_tour,-12.62493048,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_1,0,T +coef_total_number_of_tours_is_2,1.328670418,F +coef_total_number_of_tours_is_3,3.027432477,F +coef_total_number_of_tours_is_4,3.547389909,F +coef_has_mandatory_tours_and_tour_frequency_is_2,-1.122394705,F +coef_has_mandatory_tours_and_tour_frequency_is_3,-2.057588493,F +coef_has_mandatory_tours_and_tour_frequency_is_4_plus,-2.057588493,F +coef_has_joint_tours_and_tour_frequency_is_3_plus,-0.477609877,F +coef_number_of_joint_shopping_tours,-0.170864341,F +coef_number_of_joint_discretionary_tours,-1.163664908,F +coef_more_than_one_escorting_tours,0.613851731,F +coef_more_than_one_discretionary_tours,-0.236694132,F +coef_high_income_group_and_escorting_tour,-0.066520907,F +coef_mediumhigh_income_group_and_shopping_tour,0.06372943,F +coef_high_income_group_and_shopping_tour,0.06372943,F +coef_low_income_group_and_maintenance_tour,0.251347332,F +coef_mediumlow_income_group_and_maintenance_tour,0.188910438,F +coef_high_income_group_and_maintenance_tour,-0.231879121,F +coef_low_income_group_and_eating_out_tour,-1.810193362,F +coef_high_income_group_and_eating_out_tour,0.31465606,F +coef_low_income_group_and_discretionary_tour,-0.565623738,F +coef_mediumhigh_income_group_and_discretionary_tour,-0.231043198,F +coef_high_income_group_and_discretionary_tour,0.107170058,F +coef_low_income_group_and_visiting_tour,0.178971977,F +coef_female_and_escorting_tour,0.137391737,F +coef_zero_car_ownership_and_tour_frequency_is_2_plus,-0.935804805,F +coef_car_shortage_vs_workers_and_tour_frequency_is_2_plus,-0.361005701,F +coef_car_surplus_vs_workers_and_tour_frequency_is_3_plus,0.072613168,F +coef_zero_car_ownership_and_escorting_tour,-0.873271814,F +coef_car_shortage_vs_workers_and_number_of_escorting_tours,0.412574716,F +coef_number_of_full_time_worker_and_escorting_tour,0.212097217,F +coef_number_of_part_time_worker_and_escorting_tour,-0.073067961,F +coef_number_of_non_worker_and_escorting_tour,-0.323356663,F +coef_number_of_retiree_and_escorting_tour,-0.558947959,F +coef_number_of_university_student_and_escorting_tour,0.275136763,F +coef_number_of_driving_school_kid_and_escorting_tour,0.579434039,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.639740336,F +coef_go_out_school_kid_and_escorting_tour,0.384950782,F +coef_number_of_driving_school_kid_and_shopping_tour,-0.218745414,F +coef_number_of_pre_driving_school_kid_and_shopping_tour,-0.218745414,F +coef_number_of_pre_school_kid_and_shopping_tour,-0.218745414,F +coef_number_of_full_time_worker_and_maintenance_tour,-0.219097089,F +coef_number_of_part_time_worker_and_maintenance_tour,-0.219097089,F +coef_number_of_non_worker_and_maintenance_tour,-0.219097089,F +coef_number_of_university_student_and_maintenance_tour,-0.219097089,F +coef_number_of_full_time_worker_and_eating_out_tour,-0.764033574,F +coef_number_of_part_time_worker_and_eating_out_tour,-0.764033574,F +coef_number_of_non_worker_and_eating_out_tour,-0.764033574,F +coef_number_of_retiree_and_eating_out_tour,-0.764033574,F +coef_number_of_university_student_and_eating_out_tour,-0.764033574,F +coef_number_of_pre_driving_school_kid_and_eating_out_tour,-0.355618746,F +coef_number_of_pre_school_kid_and_eating_out_tour,-0.355618746,F +coef_number_of_non_worker_and_visiting_tour,-0.444931696,F +coef_number_of_retiree_and_visiting_tour,-0.444931696,F +coef_number_of_university_student_and_visiting_tour,-0.444931696,F +coef_number_of_driving_school_kid_and_discretionary_tour,-0.021518881,F +coef_number_of_pre_driving_school_kid_and_discretionary_tour,-0.021518881,F +coef_number_of_pre_school_kid_and_discretionary_tour,-0.157036558,F +coef_work_accessibility_and_tour_frequency_is_1,0.3286661,F +coef_work_accessibility_and_tour_frequency_is_2,0.71855271,F +coef_work_accessibility_and_tour_frequency_is_3,0.71855271,F +coef_work_accessibility_and_tour_frequency_is_4,0.71855271,F +coef_work_accessibility_and_tour_frequency_is_5_plus,0.71855271,F +coef_work_from_home_and_tour_frequency_is_1,0.915860359,F +coef_work_from_home_and_tour_frequency_is_2,1.100337176,F +coef_work_from_home_and_tour_frequency_is_3,1.100337176,F +coef_work_from_home_and_tour_frequency_is_4,1.100337176,F +coef_work_from_home_and_tour_frequency_is_5_plus,1.100337176,F +coef_retail_accessibility_for_escorting,0.291279719,F +coef_retail_accessibility_for_shopping,0.205237982,F +coef_retail_accessibility_for_maintenance,0.097381625,F +coef_retail_accessibility_for_eating_out,0.678030129,F +coef_walk_accessibility_for_discretionary,0.045591079,F +coef_college_education_for_visiting,-0.671955208,F +coef_college_education_for_discretionary,0.621905223,F +coef_low_education_for_visiting,0.454831607,F +coef_detached_household_and_escorting,0.22019233,F +coef_1_escort_tour_constant,0.390268916,F +coef_2_plus_escort_tours_constant,0.779302172,F +coef_1_shopping_tours_constant,0.264,F +coef_2_plus_shopping_tours_constant,0.383672128,F +coef_1_maintenance_tours_constant,-0.097866802,F +coef_2_plus_maintenance_tours_constant,-0.090890202,F +coef_1_plus_eating_out_tours_constant,-0.974733991,F +coef_1_plus_visting_tours_constant,-0.147867593,F +coef_1_other_discretionary_tours_constant,0.037252469,F +coef_2_plus_other_discretionary_tours_constant,0.221679699,F +coef_mandatory_dap_and_1_non_mand_tour,0.613102892,F +coef_mandatory_dap_and_2_non_mand_tour,1.298340523,F +coef_mandatory_dap_and_3_plus_non_mand_tour,0.294678801,F +coef_non_mandatory_dap_and_1_non_mand_tour,0.40551385,F +coef_non_mandatory_dap_and_2_non_mand_tour,-0.058684635,F +coef_non_mandatory_dap_and_3_non_mand_tour,0.181724483,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,3.456313043,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_NONWORK.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_NONWORK.csv new file mode 100644 index 000000000..4d022be71 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_NONWORK.csv @@ -0,0 +1,90 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-5.5709,F +coef_discretionary_tour,-3.1828,F +coef_shopping_tour,-1.5833,F +coef_maintenance_tour,-2.0214,F +coef_visiting_or_social_tour,-6.6293,F +coef_eating_out_tour,-8.9856,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_3,-0.793922128,F +coef_total_number_of_tours_is_4,-1.117938236,F +coef_has_joint_tours_and_tour_frequency_is_1,-0.968579459,F +coef_has_joint_tours_and_tour_frequency_is_2,-1.808495529,F +coef_has_joint_tours_and_tour_frequency_is_3_plus,-2.59200638,F +coef_number_of_joint_shopping_tours,-0.466843362,F +coef_number_of_joint_maintenance_tours,-0.575337406,F +coef_more_than_one_escorting_tours,1.3605,F +coef_more_than_one_shopping_tours,-0.7454,F +coef_more_than_one_maintenance_tours,-0.1194,F +coef_more_than_one_discretionary_tours,0.1253,F +coef_low_income_group_and_shopping_tour,-0.2599,F +coef_medium_low_income_group_and_shopping_tour,-0.2599,F +coef_low_income_group_and_eating_out_tour,-0.2857,F +coef_high_income_group_and_eating_out_tour,2.223,F +coef_low_income_group_and_discretionary_tour,-0.5775,F +coef_medium_low_income_group_and_discretionary_tour,-0.5775,F +coef_high_income_group_and_visiting_tour,0.2695,F +coef_mediumhigh_income_group_and_visiting_tour,0.2695,F +coef_female_and_escorting_tour,0.6769,F +coef_female_and_shopping_tour,0.5108,F +coef_female_and_visit_tour,0.7494,F +coef_zero_car_ownership_and_tour_frequency_is_2_plus,-1.0038,F +coef_zero_car_ownership_and_escorting_tour,-0.8907,F +coef_car_surplus_vs_workers_and_number_of_escorting_tours,0.1802,F +coef_number_of_full_time_worker_and_escorting_tour,0.2514,F +coef_number_of_part_time_worker_and_escorting_tour,0.2512,F +coef_number_of_non_worker_and_escorting_tour,-0.3489,F +coef_number_of_retiree_and_escorting_tour,0.2841,F +coef_number_of_university_student_and_escorting_tour,0.4583,F +coef_number_of_driving_school_kid_and_escorting_tour,0.7483,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.9378,F +coef_go_out_school_kid_and_escorting_tour,0.9374,F +coef_number_of_non_worker_and_shopping_tour,-0.478,F +coef_number_of_full_time_worker_and_maintenance_tour,0.0904,F +coef_number_of_part_time_worker_and_maintenance_tour,0.0904,F +coef_number_of_pre_driving_school_kid_and_eating_out_tour,-0.6629,F +coef_number_of_pre_school_kid_and_eating_out_tour,-0.6629,F +coef_number_of_pre_driving_school_kid_and_visiting_tour,-0.4021,F +coef_number_of_pre_school_kid_and_visiting_tour,-0.4021,F +coef_number_of_driving_school_kid_and_discretionary_tour,-0.2039,F +coef_number_of_pre_driving_school_kid_and_discretionary_tour,-0.2039,F +coef_number_of_pre_school_kid_and_discretionary_tour,-0.2039,F +coef_retail_accessibility_for_escorting,0.1609,F +coef_retail_accessibility_for_maintenance,0.0194,F +coef_retail_accessibility_for_discretionary,0.0632,F +coef_retail_accessibility_for_visiting,0.2883,F +coef_walk_accessibility_for_eatout,0.6073,F +coef_college_education_for_discretionary,0.981,F +coef_college_education_for_shopping,0.3677,F +coef_college_education_for_maintenance,0.5982,F +coef_college_education_for_eatout,0.7979,F +coef_low_education_for_visiting,-1.6201,F +coef_low_education_for_discretionary,-0.837,F +coef_low_education_for_escorting,0.1748,F +coef_low_education_for_shopping,-0.3525,F +coef_low_education_for_eatout,-0.4838,F +coef_1_escort_tour_constant,-2.501,F +coef_2_plus_escort_tours_constant,-1.958,F +coef_1_shopping_tours_constant,-2.666,F +coef_2_plus_shopping_tours_constant,-2.884,F +coef_1_maintenance_tours_constant,-2.908,F +coef_2_plus_maintenance_tours_constant,-2.97,F +coef_1_plus_eating_out_tours_constant,-3.022,F +coef_1_plus_visting_tours_constant,-2.736,F +coef_1_other_discretionary_tours_constant,-2.612,F +coef_2_plus_other_discretionary_tours_constant,-2.663,F +coef_1_escort_tour_constant_tm2,-1.52187411,F +coef_2_plus_escort_tours_constant_tm2,-1.489501032,F +coef_1_shopping_tours_constant_tm2,-1.853328287,F +coef_2_plus_shopping_tours_constant_tm2,-1.853328287,F +coef_1_maintenance_tours_constant_tm2,-0.808408856,F +coef_2_plus_maintenance_tours_constant_tm2,-0.808408856,F +coef_1_plus_eating_out_tours_constant_tm2,0.600524339,F +coef_1_plus_visting_tours_constant_tm2,-0.284937967,F +coef_1_other_discretionary_tours_constant_tm2,-0.504897539,F +coef_2_plus_other_discretionary_tours_constant_tm2,-0.504897539,F +coef_non_mandatory_dap_and_1_non_mand_tour,0.563996011,F +coef_non_mandatory_dap_and_2_non_mand_tour,1.1354493,F +coef_non_mandatory_dap_and_3_non_mand_tour,1.647365455,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,6.448243189,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PART.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PART.csv new file mode 100644 index 000000000..2d32768ef --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PART.csv @@ -0,0 +1,103 @@ +coefficient_name,value,Constrain +coef_unavailable,-999,T +coef_escorting_tour,-6.825870475,F +coef_discretionary_tour,-3.103671535,F +coef_shopping_tour,-2.585699928,F +coef_maintenance_tour,-4.876815454,F +coef_visiting_or_social_tour,-4.787916747,F +coef_eating_out_tour,-8.091973006,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_1,0,T +coef_total_number_of_tours_is_2,1.347662088,F +coef_total_number_of_tours_is_3,1.958684542,F +coef_total_number_of_tours_is_4,3.406917203,F +coef_total_number_of_tours_is_5,3.406917203,F +coef_total_number_of_tours_is_6_plus,3.406917203,F +coef_has_mandatory_tours_and_tour_frequency_is_2,-1.383795025,F +coef_has_mandatory_tours_and_tour_frequency_is_3,-1.383795025,F +coef_has_mandatory_tours_and_tour_frequency_is_4_plus,-2.308089044,F +coef_has_joint_tours_and_tour_frequency_is_4_plus,-0.850963319,F +coef_number_of_joint_discretionary_tours,-0.13985943,F +coef_more_than_one_escorting_tours,0.688722128,F +coef_more_than_one_shopping_tours,-0.806980084,F +coef_more_than_one_discretionary_tours,-1.123565611,F +coef_high_income_group_and_escorting_tour,-0.188741999,F +coef_low_income_group_and_shopping_tour,-0.584603787,F +coef_medium_low_income_group_and_shopping_tour,-0.191476033,F +coef_medium_high_income_group_and_shopping_tour,0.302369299,F +coef_high_income_group_and_shopping_tour,0.302369299,F +coef_low_income_group_and_eating_out_tour,-1.70963028,F +coef_medium_low_income_group_and_eating_out_tour,-1.018936807,F +coef_low_income_group_and_discretionary_tour,-0.697953689,F +coef_mediumhigh_income_group_and_discretionary_tour,0.441095148,F +coef_high_income_group_and_discretionary_tour,0.441095148,F +coef_female_and_escorting_tour,0.827860636,F +coef_female_and_shopping_tour,0.650180816,F +coef_female_and_eatingout_tour,-1.25440798,F +coef_zero_car_ownership_and_tour_frequency_is_2_plus,-2.213461849,F +coef_car_shortage_vs_workers_and_tour_frequency_is_2_plus,-0.490152764,F +coef_car_shortage_vs_workers_and_number_of_escorting_tours,0.245040809,F +coef_car_surplus_vs_workers_and_number_of_escorting_tours,-0.273518269,F +coef_car_shortage_vs_workers_and_number_of_shopping_tours,0.377878264,F +coef_car_surplus_vs_workers_and_number_of_shopping_tours,-0.579935901,F +coef_number_of_full_time_worker_and_escorting_tour,0.097720305,F +coef_number_of_part_time_worker_and_escorting_tour,-0.13505138,F +coef_number_of_non_worker_and_escorting_tour,-0.264726717,F +coef_number_of_university_student_and_escorting_tour,0.324362136,F +coef_number_of_driving_school_kid_and_escorting_tour,0.592250815,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.807393603,F +coef_go_out_school_kid_and_escorting_tour,0.584027557,F +coef_number_of_full_time_worker_and_shopping_tour,-0.571692163,F +coef_number_of_part_time_worker_and_shopping_tour,-0.571692163,F +coef_number_of_non_worker_and_shopping_tour,-0.571692163,F +coef_number_of_full_time_worker_and_maintenance_tour,-0.242545271,F +coef_number_of_part_time_worker_and_maintenance_tour,-0.242545271,F +coef_number_of_non_worker_and_maintenance_tour,-1.173436234,F +coef_number_of_full_time_worker_and_eating_out_tour,-0.273301702,F +coef_number_of_part_time_worker_and_visiting_tour,0.887755866,F +coef_number_of_retiree_and_visiting_tour,0.885418039,F +coef_number_of_driving_school_kid_and_visiting_tour,0.023898086,F +coef_number_of_pre_driving_school_kid_and_visiting_tour,0.023898086,F +coef_number_of_pre_school_kid_and_visiting_tour,0.023898086,F +coef_number_of_driving_school_kid_and_discretionary_tour,0.257383748,F +coef_number_of_pre_driving_school_kid_and_discretionary_tour,0.257383748,F +coef_number_of_pre_school_kid_and_discretionary_tour,-2.431661289,F +coef_work_accessibility_and_tour_frequency_is_1,0.628740481,F +coef_work_accessibility_and_tour_frequency_is_2,0.842604039,F +coef_work_accessibility_and_tour_frequency_is_3_plus,0.814255739,F +coef_retail_accessibility_for_escorting,0.199705264,F +coef_retail_accessibility_for_maintenance,0.189588653,F +coef_retail_accessibility_for_eating_out,0.387577711,F +coef_walk_accessibility_for_discretionary,0.032230313,F +coef_origin_population_density_for_visiting,0.048808797,F +coef_college_education_for_discretionary,0.256548173,F +coef_low_education_for_discretionary,-0.974189529,F +coef_detached_household_and_escorting,0.290441415,F +coef_detached_household_and_eating_out,-0.227906236,F +coef_1_escort_tour_constant,0.444537569,F +coef_2_plus_escort_tours_constant,1.45203917,F +coef_1_shopping_tours_constant,0.19959348,F +coef_2_plus_shopping_tours_constant,0.365593218,F +coef_1_maintenance_tours_constant,-0.050890967,F +coef_2_plus_maintenance_tours_constant,0.025818889,F +coef_1_plus_eating_out_tours_constant,-0.688218447,F +coef_1_plus_visting_tours_constant,-0.761523103,F +coef_1_other_discretionary_tours_constant,0.151171319,F +coef_2_plus_other_discretionary_tours_constant,0.349908582,F +coef_1_escort_tour_constant_tm2,-1.041387049,F +coef_2_plus_escort_tours_constant_tm2,-1.209189663,F +coef_1_shopping_tours_constant_tm2,-1.496588445,F +coef_2_plus_shopping_tours_constant_tm2,-1.496588445,F +coef_1_maintenance_tours_constant_tm2,-0.067949689,F +coef_2_plus_maintenance_tours_constant_tm2,-0.067949689,F +coef_1_plus_eating_out_tours_constant_tm2,0.534488324,F +coef_1_plus_visting_tours_constant_tm2,-0.010969663,F +coef_1_other_discretionary_tours_constant_tm2,-0.530568731,F +coef_2_plus_other_discretionary_tours_constant_tm2,-0.530568731,F +coef_mandatory_dap_and_1_non_mand_tour,0.435298756,F +coef_mandatory_dap_and_2_non_mand_tour,1.193250166,F +coef_mandatory_dap_and_3_plus_non_mand_tour,1.803605616,F +coef_non_mandatory_dap_and_1_non_mand_tour,0.612888101,F +coef_non_mandatory_dap_and_2_non_mand_tour,0.745415157,F +coef_non_mandatory_dap_and_3_non_mand_tour,1.266755805,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,2.308013647,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PRESCHOOL.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PRESCHOOL.csv new file mode 100644 index 000000000..e3f9dce15 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_PRESCHOOL.csv @@ -0,0 +1,47 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-7.2688,F +coef_discretionary_tour,-4.2006,F +coef_shopping_tour,-43.4464,F +coef_maintenance_tour,-3.3790,F +coef_visiting_or_social_tour,-4.0352,F +coef_eating_out_tour,-5.2924,F +coef_total_number_of_tours_is_0_prior_tours,0.0000,T +coef_total_number_of_tours_is_2,-0.7216,F +coef_total_number_of_tours_is_3,-0.9586,F +coef_has_mandatory_tours_and_tour_frequency_is_2_plus,-2.1108,F +coef_more_than_one_escorting_tours,2.3269,F +coef_high_income_group_and_escorting_tour,-0.6921,F +coef_zero_car_ownership_and_escorting_tour,-0.9936,F +coef_car_shortage_vs_workers_and_number_of_escorting_tours,-0.9936,F +coef_number_of_part_time_worker_and_escorting_tour,0.7831,F +coef_number_of_non_worker_and_escorting_tour,0.7831,F +coef_number_of_university_student_and_escorting_tour,0.8044,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.5152,F +coef_go_out_school_kid_and_escorting_tour,0.6072,F +coef_retail_accessibility_for_escorting,0.2739,F +coef_retail_accessibility_for_shopping,2.7431,F +coef_1_escort_tour_constant,-8.402,F +coef_2_plus_escort_tours_constant,-9.519,F +coef_1_shopping_tours_constant,-3.856,F +coef_2_plus_shopping_tours_constant,0.000,T +coef_1_maintenance_tours_constant,-7.785,F +coef_2_plus_maintenance_tours_constant,-6.925,F +coef_1_plus_eating_out_tours_constant,-7.585,F +coef_1_plus_visting_tours_constant,-7.599,F +coef_1_other_discretionary_tours_constant,-7.462,F +coef_2_plus_other_discretionary_tours_constant,-15.000,F +coef_1_escort_tour_constant_tm2,-1.496,F +coef_2_plus_escort_tours_constant_tm2,-1.588,F +coef_1_shopping_tours_constant_tm2,0.031,F +coef_2_plus_shopping_tours_constant_tm2,0.031,F +coef_1_maintenance_tours_constant_tm2,-1.011,F +coef_2_plus_maintenance_tours_constant_tm2,-1.011,F +coef_1_plus_eating_out_tours_constant_tm2,-1.923,F +coef_1_plus_visting_tours_constant_tm2,-1.085,F +coef_1_other_discretionary_tours_constant_tm2,-1.126,F +coef_2_plus_other_discretionary_tours_constant_tm2,-1.126,F +coef_non_mandatory_dap_and_1_non_mand_tour,1.113941467,F +coef_non_mandatory_dap_and_2_non_mand_tour,0.375527882,F +coef_non_mandatory_dap_and_3_non_mand_tour,2.691413911,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,8.404994214,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_RETIRED.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_RETIRED.csv new file mode 100644 index 000000000..896947920 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_RETIRED.csv @@ -0,0 +1,84 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-10.4405,F +coef_discretionary_tour,-6.1189,F +coef_shopping_tour,-4.6661,F +coef_maintenance_tour,-2.4724,F +coef_visiting_or_social_tour,-3.677,F +coef_eating_out_tour,-2.5648,F +coef_total_number_of_tours_is_0_prior_tours,-1.140675606,F +coef_has_joint_tours_and_tour_frequency_is_1,-1.601015729,F +coef_has_joint_tours_and_tour_frequency_is_2_plus,-2.105529269,F +coef_number_of_joint_shopping_tours,-0.6377,F +coef_number_of_joint_maintenance_tours,-0.4348,F +coef_number_of_joint_eating_out_tours,-0.7839,F +coef_number_of_joint_discretionary_tours,-0.085,F +coef_more_than_one_escorting_tours,2.0794,F +coef_more_than_one_shopping_tours,-1.1624,F +coef_more_than_one_maintenance_tours,-0.5943,F +coef_mediumhigh_income_group_and_shopping_tour,0.4056,F +coef_high_income_group_and_shopping_tour,0.4056,F +coef_low_income_group_and_maintenance_tour,-0.2202,F +coef_mediumlow_income_group_and_maintenance_tour,-0.2202,F +coef_low_income_group_and_eating_out_tour,-1.0384,F +coef_medium_low_income_group_and_eating_out_tour,-0.4217,F +coef_low_income_group_and_discretionary_tour,-0.3758,F +coef_mediumhigh_income_group_and_discretionary_tour,0.1222,F +coef_high_income_group_and_discretionary_tour,0.1222,F +coef_high_income_group_and_visiting_tour,-1.104,F +coef_female_and_shopping_tour,-0.0455,F +coef_female_and_maintenance_tour,-0.2926,F +coef_female_and_eatingout_tour,-0.2472,F +coef_female_and_discretionary_tour,-0.0647,F +coef_number_of_full_time_worker_and_escorting_tour,-0.1294,F +coef_number_of_part_time_worker_and_escorting_tour,-0.1294,F +coef_number_of_non_worker_and_escorting_tour,-0.1294,F +coef_number_of_driving_school_kid_and_escorting_tour,0.6054,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.7285,F +coef_number_of_retiree_and_shopping_tour,-0.4462,F +coef_number_of_retiree_and_maintenance_tour,-0.4112,F +coef_number_of_retiree_and_visiting_tour,-0.2327,F +coef_retired_hh_and_escorting_tour,-0.8133,F +coef_retired_hh_and_shopping_tour,0.2715,F +coef_retired_hh_and_eating_out_tour,0.2011,F +coef_retired_hh_and_discretionary_tour,0.2624,F +coef_retail_accessibility_for_escorting,0.5109,F +coef_retail_accessibility_for_shopping,0.2262,F +coef_retail_accessibility_for_maintenance,0.1154,F +coef_retail_accessibility_for_discretionary,0.3252,F +coef_retail_accessibility_for_visiting,0.0533,F +coef_college_education_for_escorting,0.1522,F +coef_college_education_for_visiting,0.2179,F +coef_college_education_for_discretionary,0.3046,F +coef_college_education_for_shopping,0.2046,F +coef_low_education_for_discretionary,-0.8504,F +coef_low_education_for_escorting,-0.8443,F +coef_low_education_for_shopping,-0.5676,F +coef_low_education_for_maintenance,-0.6861,F +coef_detached_household_and_escorting,0.3809,F +coef_detached_household_and_eating_out,-0.3389,F +coef_detached_household_and_discretionary,-0.3286,F +coef_1_escort_tour_constant,-2.342,F +coef_2_plus_escort_tours_constant,-1.988,F +coef_1_shopping_tours_constant,-2.414,F +coef_2_plus_shopping_tours_constant,-2.101,F +coef_1_maintenance_tours_constant,-2.869,F +coef_2_plus_maintenance_tours_constant,-3.015,F +coef_1_plus_eating_out_tours_constant,-2.979,F +coef_1_plus_visting_tours_constant,-2.806,F +coef_1_other_discretionary_tours_constant,-3.196,F +coef_2_plus_other_discretionary_tours_constant,-3.482,F +coef_1_escort_tour_constant_tm2,-0.287618769,F +coef_2_plus_escort_tours_constant_tm2,0.65554552,F +coef_1_shopping_tours_constant_tm2,-1.385280597,F +coef_2_plus_shopping_tours_constant_tm2,-1.385280597,F +coef_1_maintenance_tours_constant_tm2,-1.480017973,F +coef_2_plus_maintenance_tours_constant_tm2,-1.480017973,F +coef_1_plus_eating_out_tours_constant_tm2,-1.385672408,F +coef_1_plus_visting_tours_constant_tm2,-1.218799144,F +coef_1_other_discretionary_tours_constant_tm2,0.538161829,F +coef_2_plus_other_discretionary_tours_constant_tm2,0.538161829,F +coef_non_mandatory_dap_and_1_non_mand_tour,1.152725777,F +coef_non_mandatory_dap_and_2_non_mand_tour,0.022553605,F +coef_non_mandatory_dap_and_3_non_mand_tour,6.338227151,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,6.237997735,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_SCHOOL.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_SCHOOL.csv new file mode 100644 index 000000000..405ec48a1 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_SCHOOL.csv @@ -0,0 +1,72 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-10.3136,F +coef_discretionary_tour,-8.0543,F +coef_shopping_tour,-17.8882,F +coef_maintenance_tour,-14.5925,F +coef_visiting_or_social_tour,-2.9744,F +coef_eating_out_tour,-42.1591,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_2,-0.7045,F +coef_total_number_of_tours_is_3,-0.7045,F +coef_has_mandatory_tours_and_tour_frequency_is_1,-1.8596,F +coef_has_mandatory_tours_and_tour_frequency_is_2_plus,-6.1247,F +coef_has_joint_tours_and_tour_frequency_is_1_plus,-1.0154,F +coef_number_of_joint_discretionary_tours,-1.2257,F +coef_more_than_one_escorting_tours,0.3358,F +coef_more_than_one_discretionary_tours,-0.8724,F +coef_high_income_group_and_shopping_tour,1.0878,F +coef_mediumhigh_income_group_and_maintenance_tour,1.0499,F +coef_high_income_group_and_maintenance_tour,1.0499,F +coef_low_income_group_and_discretionary_tour,-2.1495,F +coef_medium_low_income_group_and_discretionary_tour,-0.9706,F +coef_high_income_group_and_discretionary_tour,0.6655,F +coef_low_income_group_and_visiting_tour,-1.6227,F +coef_medium_low_income_group_and_visiting_tour,-1.6227,F +coef_high_income_group_and_visiting_tour,1.1424,F +coef_car_surplus_vs_workers_and_number_of_maintenance_tours,0.4721,F +coef_car_surplus_vs_workers_and_number_of_discretionary_tours,0.1531,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.4372,F +coef_number_of_driving_school_kid_and_shopping_tour,-0.1631,F +coef_number_of_pre_driving_school_kid_and_shopping_tour,-0.1631,F +coef_number_of_pre_school_kid_and_shopping_tour,-0.1631,F +coef_number_of_driving_school_kid_and_visiting_tour,0.3656,F +coef_number_of_pre_driving_school_kid_and_visiting_tour,0.3656,F +coef_number_of_pre_school_kid_and_visiting_tour,0.3656,F +coef_number_of_driving_school_kid_and_discretionary_tour,0.2287,F +coef_number_of_pre_driving_school_kid_and_discretionary_tour,0.2287,F +coef_number_of_pre_school_kid_and_discretionary_tour,0.2287,F +coef_school_accessibility_and_tour_frequency_is_1,0.6512,F +coef_school_accessibility_and_tour_frequency_is_2_plus,3.8532,F +coef_retail_accessibility_for_escorting,0.5583,F +coef_retail_accessibility_for_shopping,0.9818,F +coef_retail_accessibility_for_maintenance,0.8866,F +coef_retail_accessibility_for_eating_out,2.8733,F +coef_retail_accessibility_for_discretionary,0.5082,F +coef_1_escort_tour_constant,-0.405,F +coef_2_plus_escort_tours_constant,-0.688,F +coef_1_shopping_tours_constant,1.708,F +coef_2_plus_shopping_tours_constant,0,T +coef_1_maintenance_tours_constant,-1.042,F +coef_2_plus_maintenance_tours_constant,0,T +coef_1_plus_eating_out_tours_constant,-3.915,F +coef_1_plus_visting_tours_constant,-0.653,F +coef_1_other_discretionary_tours_constant,-1.095,F +coef_2_plus_other_discretionary_tours_constant,-2.257,F +coef_1_escort_tour_constant_tm2,-0.491,F +coef_2_plus_escort_tours_constant_tm2,-0.491,F +coef_1_shopping_tours_constant_tm2,0.246,F +coef_2_plus_shopping_tours_constant_tm2,0.246,F +coef_1_maintenance_tours_constant_tm2,1.445,F +coef_2_plus_maintenance_tours_constant_tm2,1.445,F +coef_1_plus_eating_out_tours_constant_tm2,0.005,F +coef_1_plus_visting_tours_constant_tm2,-2.381,F +coef_1_other_discretionary_tours_constant_tm2,0.614,F +coef_2_plus_other_discretionary_tours_constant_tm2,0.614,F +coef_mandatory_dap_and_1_non_mand_tour,2.692763095,F +coef_mandatory_dap_and_2_non_mand_tour,5.492779247,F +coef_mandatory_dap_and_3_plus_non_mand_tour,1.891501612,F +coef_non_mandatory_dap_and_1_non_mand_tour,4.002447263,F +coef_non_mandatory_dap_and_2_non_mand_tour,2.426047336,F +coef_non_mandatory_dap_and_3_non_mand_tour,-5.579294246,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,-3.501958214,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_UNIVERSITY.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_UNIVERSITY.csv new file mode 100644 index 000000000..8c8809347 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_coefficients_PTYPE_UNIVERSITY.csv @@ -0,0 +1,81 @@ +coefficient_name,value,constrain +coef_unavailable,-999,T +coef_escorting_tour,-3.151460752,F +coef_discretionary_tour,-4.548188518,F +coef_shopping_tour,-2.772689119,F +coef_maintenance_tour,-2.262570738,F +coef_visiting_or_social_tour,-4.212581954,F +coef_eating_out_tour,-14.69186496,F +coef_total_number_of_tours_is_0_prior_tours,0,T +coef_total_number_of_tours_is_1,-0.257343536,F +coef_has_mandatory_tours_and_tour_frequency_is_2_plus,-1.072062082,F +coef_has_joint_tours_and_tour_frequency_is_1,-0.336245855,F +coef_has_joint_tours_and_tour_frequency_is_2_plus,-0.388633303,F +coef_more_than_one_escorting_tours,2.72245229,F +coef_low_income_group_and_escorting_tour,0.202123266,F +coef_medium_low_income_group_and_escorting_tour,0.202123266,F +coef_medium_high_income_group_and_escorting_tour,-0.060806947,F +coef_high_income_group_and_escorting_tour,-0.060806947,F +coef_medium_high_income_group_and_shopping_tour,0.685514685,F +coef_high_income_group_and_shopping_tour,0.702798296,F +coef_mediumhigh_income_group_and_maintenance_tour,-0.252582535,F +coef_high_income_group_and_maintenance_tour,-0.252582535,F +coef_medium_high_income_group_and_eating_out_tour,1.584951486,F +coef_high_income_group_and_eating_out_tour,1.584951486,F +coef_low_income_group_and_discretionary_tour,-0.174583696,F +coef_mediumhigh_income_group_and_discretionary_tour,0.61551534,F +coef_high_income_group_and_discretionary_tour,0.61551534,F +coef_low_income_group_and_visiting_tour,0.709390489,F +coef_medium_low_income_group_and_visiting_tour,0.709390489,F +coef_high_income_group_and_visiting_tour,-0.174583696,F +coef_female_and_escorting_tour,0.187876356,F +coef_female_and_shopping_tour,0.986977296,F +coef_female_and_maintenance_tour,0.203259744,F +coef_female_and_visit_tour,1.063972932,F +coef_car_surplus_vs_workers_and_tour_frequency_is_1_plus,0.427064876,F +coef_number_of_full_time_worker_and_escorting_tour,-0.30107932,F +coef_number_of_part_time_worker_and_escorting_tour,-0.457600247,F +coef_number_of_non_worker_and_escorting_tour,-0.457600247,F +coef_number_of_retiree_and_escorting_tour,-0.637017887,F +coef_number_of_university_student_and_escorting_tour,0.420147909,F +coef_go_out_pre_driving_school_kid_and_escorting_tour,0.767818174,F +coef_go_out_school_kid_and_escorting_tour,0.578638577,F +coef_number_of_full_time_worker_and_shopping_tour,-0.500867474,F +coef_number_of_part_time_worker_and_shopping_tour,-0.760659628,F +coef_number_of_university_student_and_shopping_tour,-1.440951366,F +coef_number_of_full_time_worker_and_maintenance_tour,-0.540708813,F +coef_number_of_part_time_worker_and_maintenance_tour,-0.540708813,F +coef_number_of_non_worker_and_maintenance_tour,-0.540708813,F +coef_number_of_university_student_and_maintenance_tour,-1.047970628,F +coef_number_of_university_student_and_discretionary_tour,0.089391871,F +coef_school_accessibility_and_tour_frequency_is_1_plus,0.512981401,F +coef_retail_accessibility_for_discretionary,0.146060018,F +coef_walk_accessibility_for_eatout,1.002231311,F +coef_detached_household_and_discretionary,-0.330258504,F +coef_1_escort_tour_constant,0.212419359,F +coef_2_plus_escort_tours_constant,0.941880945,F +coef_1_shopping_tours_constant,0.292005818,F +coef_2_plus_shopping_tours_constant,0.365107316,F +coef_1_maintenance_tours_constant,-0.361543976,F +coef_2_plus_maintenance_tours_constant,0,T +coef_1_plus_eating_out_tours_constant,-0.297763109,F +coef_1_plus_visting_tours_constant,-0.657474419,F +coef_1_other_discretionary_tours_constant,0.941880945,F +coef_2_plus_other_discretionary_tours_constant,-0.390350079,F +coef_1_escort_tour_constant_tm2,-0.367737876,F +coef_2_plus_escort_tours_constant_tm2,-1.248352386,F +coef_1_shopping_tours_constant_tm2,-1.437353532,F +coef_2_plus_shopping_tours_constant_tm2,-1.437353532,F +coef_1_maintenance_tours_constant_tm2,-1.454556703,F +coef_2_plus_maintenance_tours_constant_tm2,-1.454556703,F +coef_1_plus_eating_out_tours_constant_tm2,1.506897479,F +coef_1_plus_visting_tours_constant_tm2,-0.716560806,F +coef_1_other_discretionary_tours_constant_tm2,-0.194927725,F +coef_2_plus_other_discretionary_tours_constant_tm2,-0.194927725,F +coef_mandatory_dap_and_1_non_mand_tour,0.775208618,F +coef_mandatory_dap_and_2_non_mand_tour,1.056946603,F +coef_mandatory_dap_and_3_plus_non_mand_tour,-5.001269397,F +coef_non_mandatory_dap_and_1_non_mand_tour,-0.396651853,F +coef_non_mandatory_dap_and_2_non_mand_tour,-0.794997137,F +coef_non_mandatory_dap_and_3_non_mand_tour,-2.141825245,F +coef_non_mandatory_dap_and_4_plus_non_mand_tour,-5.009271306,F diff --git a/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_extension_probs.csv b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_extension_probs.csv new file mode 100644 index 000000000..830885237 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/non_mandatory_tour_frequency_extension_probs.csv @@ -0,0 +1,193 @@ +ptype,has_mandatory_tour,has_joint_tour,nonmandatory_tour_type,0_tours,1_tours,2_tours +1,0,0,1,0.71087271,0.886861358,1 +2,0,0,1,0.640712953,0.863555773,1 +3,0,0,1,0.726456335,0.726456335,1 +4,0,0,1,0.665679012,0.903816044,1 +5,0,0,1,0.861430335,0.92284115,1 +6,0,0,1,1,1,1 +7,0,0,1,0,1,1 +8,0,0,1,0.754632385,0.918132897,1 +1,1,0,1,0.824975545,1,1 +2,1,0,1,0.881285721,0.964131273,1 +3,1,0,1,0.856158692,1,1 +4,1,0,1,1,1,1 +5,1,0,1,1,1,1 +6,1,0,1,1,1,1 +7,1,0,1,1,1,1 +8,1,0,1,1,1,1 +1,0,0,2,0.918802841,1,1 +2,0,0,2,1,1,1 +3,0,0,2,1,1,1 +4,0,0,2,1,1,1 +5,0,0,2,0.911351921,0.964395496,1 +6,0,0,2,1,1,1 +7,0,0,2,1,1,1 +8,0,0,2,0.91707294,1,1 +1,1,0,2,1,1,1 +2,1,0,2,1,1,1 +3,1,0,2,1,1,1 +4,1,0,2,1,1,1 +5,1,0,2,1,1,1 +6,1,0,2,1,1,1 +7,1,0,2,1,1,1 +8,1,0,2,1,1,1 +1,0,0,3,0.885080064,0.942540032,1 +2,0,0,3,0.832615585,1,1 +3,0,0,3,1,1,1 +4,0,0,3,1,1,1 +5,0,0,3,0.874364173,0.972270724,1 +6,0,0,3,1,1,1 +7,0,0,3,1,1,1 +8,0,0,3,1,1,1 +1,1,0,3,1,1,1 +2,1,0,3,1,1,1 +3,1,0,3,1,1,1 +4,1,0,3,1,1,1 +5,1,0,3,1,1,1 +6,1,0,3,1,1,1 +7,1,0,3,1,1,1 +8,1,0,3,1,1,1 +1,0,0,4,1,1,1 +2,0,0,4,0.99296599,1,1 +3,0,0,4,1,1,1 +4,0,0,4,0.976072814,1,1 +5,0,0,4,0.956476086,0.993572522,1 +6,0,0,4,1,1,1 +7,0,0,4,1,1,1 +8,0,0,4,0.991144007,1,1 +1,1,0,4,0.99740908,1,1 +2,1,0,4,0.939184617,1,1 +3,1,0,4,1,1,1 +4,1,0,4,0.749851433,1,1 +5,1,0,4,1,1,1 +6,1,0,4,1,1,1 +7,1,0,4,1,1,1 +8,1,0,4,0.949874016,1,1 +1,0,0,5,1,1,1 +2,0,0,5,1,1,1 +3,0,0,5,1,1,1 +4,0,0,5,0.954541082,1,1 +5,0,0,5,0.955216408,1,1 +6,0,0,5,1,1,1 +7,0,0,5,1,1,1 +8,0,0,5,0.931183243,1,1 +1,1,0,5,0.970742777,1,1 +2,1,0,5,0.882901912,1,1 +3,1,0,5,1,1,1 +4,1,0,5,0.334132623,1,1 +5,1,0,5,1,1,1 +6,1,0,5,0.934804611,0.934804611,1 +7,1,0,5,0.965932685,1,1 +8,1,0,5,1,1,1 +1,0,0,6,1,1,1 +2,0,0,6,1,1,1 +3,0,0,6,1,1,1 +4,0,0,6,0.86514867,1,1 +5,0,0,6,0.896321835,1,1 +6,0,0,6,1,1,1 +7,0,0,6,1,1,1 +8,0,0,6,1,1,1 +1,1,0,6,1,1,1 +2,1,0,6,1,1,1 +3,1,0,6,1,1,1 +4,1,0,6,1,1,1 +5,1,0,6,1,1,1 +6,1,0,6,1,1,1 +7,1,0,6,1,1,1 +8,1,0,6,1,1,1 +1,0,1,1,1,1,1 +2,0,1,1,1,1,1 +3,0,1,1,1,1,1 +4,0,1,1,1,1,1 +5,0,1,1,1,1,1 +6,0,1,1,1,1,1 +7,0,1,1,1,1,1 +8,0,1,1,1,1,1 +1,1,1,1,1,1,1 +2,1,1,1,1,1,1 +3,1,1,1,1,1,1 +4,1,1,1,1,1,1 +5,1,1,1,1,1,1 +6,1,1,1,1,1,1 +7,1,1,1,1,1,1 +8,1,1,1,1,1,1 +1,0,1,2,1,1,1 +2,0,1,2,1,1,1 +3,0,1,2,1,1,1 +4,0,1,2,1,1,1 +5,0,1,2,1,1,1 +6,0,1,2,1,1,1 +7,0,1,2,1,1,1 +8,0,1,2,1,1,1 +1,1,1,2,1,1,1 +2,1,1,2,1,1,1 +3,1,1,2,1,1,1 +4,1,1,2,1,1,1 +5,1,1,2,1,1,1 +6,1,1,2,1,1,1 +7,1,1,2,1,1,1 +8,1,1,2,1,1,1 +1,0,1,3,1,1,1 +2,0,1,3,1,1,1 +3,0,1,3,1,1,1 +4,0,1,3,1,1,1 +5,0,1,3,1,1,1 +6,0,1,3,1,1,1 +7,0,1,3,1,1,1 +8,0,1,3,1,1,1 +1,1,1,3,1,1,1 +2,1,1,3,1,1,1 +3,1,1,3,1,1,1 +4,1,1,3,1,1,1 +5,1,1,3,1,1,1 +6,1,1,3,1,1,1 +7,1,1,3,1,1,1 +8,1,1,3,1,1,1 +1,0,1,4,1,1,1 +2,0,1,4,1,1,1 +3,0,1,4,1,1,1 +4,0,1,4,1,1,1 +5,0,1,4,1,1,1 +6,0,1,4,1,1,1 +7,0,1,4,1,1,1 +8,0,1,4,1,1,1 +1,1,1,4,1,1,1 +2,1,1,4,1,1,1 +3,1,1,4,1,1,1 +4,1,1,4,1,1,1 +5,1,1,4,1,1,1 +6,1,1,4,1,1,1 +7,1,1,4,1,1,1 +8,1,1,4,1,1,1 +1,0,1,5,1,1,1 +2,0,1,5,1,1,1 +3,0,1,5,1,1,1 +4,0,1,5,1,1,1 +5,0,1,5,1,1,1 +6,0,1,5,1,1,1 +7,0,1,5,1,1,1 +8,0,1,5,1,1,1 +1,1,1,5,1,1,1 +2,1,1,5,1,1,1 +3,1,1,5,1,1,1 +4,1,1,5,1,1,1 +5,1,1,5,1,1,1 +6,1,1,5,1,1,1 +7,1,1,5,1,1,1 +8,1,1,5,1,1,1 +1,0,1,6,1,1,1 +2,0,1,6,1,1,1 +3,0,1,6,1,1,1 +4,0,1,6,1,1,1 +5,0,1,6,1,1,1 +6,0,1,6,1,1,1 +7,0,1,6,1,1,1 +8,0,1,6,1,1,1 +1,1,1,6,1,1,1 +2,1,1,6,1,1,1 +3,1,1,6,1,1,1 +4,1,1,6,1,1,1 +5,1,1,6,1,1,1 +6,1,1,6,1,1,1 +7,1,1,6,1,1,1 +8,1,1,6,1,1,1 diff --git a/test/non_mandatory_tour_frequency/configs/settings.yaml b/test/non_mandatory_tour_frequency/configs/settings.yaml new file mode 100644 index 000000000..4136d0b80 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/settings.yaml @@ -0,0 +1,60 @@ +# input tables +input_table_list: + - tablename: households + filename: households.csv + index_col: household_id + rename_columns: + unique_hh_id: household_id + NP: hhsize + hh_workers_from_esr: num_workers + VEH: auto_ownership + MAZ: home_zone_id + HINCP: income + keep_columns: + - home_zone_id + - income + - hhsize + - HHT + - auto_ownership + - num_workers + - tablename: persons + filename: persons.csv + index_col: person_id + rename_columns: + unique_hh_id: household_id + AGEP: age + SPORDER: PNUM + SEX: sex + employed: pemploy + student_status: pstudent + person_type: ptype + keep_columns: + - household_id + - age + - PNUM + - sex + - pemploy + - pstudent + - ptype + - tablename: land_use + filename: land_use.csv + index_col: zone_id + rename_columns: + MAZ_ORIGINAL: zone_id + CountyID: county_id + TAZ_ORIGINAL: TAZ + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + keep_columns: + - TAZ + - DISTRICT + - SD + - county_id + - TOTHH + - TOTPOP + - TOTACRE + +trace_hh_id: \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/configs/tour_departure_and_duration_alternatives.csv b/test/non_mandatory_tour_frequency/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 000000000..bddab06b9 --- /dev/null +++ b/test/non_mandatory_tour_frequency/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/test/non_mandatory_tour_frequency/data/.gitkeep b/test/non_mandatory_tour_frequency/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/non_mandatory_tour_frequency/test_non_mandatory_tour_frequency.py b/test/non_mandatory_tour_frequency/test_non_mandatory_tour_frequency.py new file mode 100644 index 000000000..1563de756 --- /dev/null +++ b/test/non_mandatory_tour_frequency/test_non_mandatory_tour_frequency.py @@ -0,0 +1,336 @@ +import logging +import pytest +import os +import shutil +import pandas as pd +import numpy as np +from numpy import dot +from numpy.linalg import norm + +# import models is necessary to initalize the model steps with orca +from activitysim.abm import models +from activitysim.core import pipeline, config +from activitysim.core import tracing + +logger = logging.getLogger(__name__) + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def module() -> str: + """ + A pytest fixture that returns the data folder location. + :return: folder location for any necessary data to initialize the tests + """ + return "non_mandatory_tour_frequency" + + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def tables(prepare_module_inputs) -> dict[str, str]: + """ + A pytest fixture that returns the "mock" tables to build pipeline dataframes. The + key-value pair is the name of the table and the index column. + :return: dict + """ + return { + "land_use": "MAZ_ORIGINAL", + "persons": "person_id", + "households": "household_id", + "accessibility": "MAZ_ORIGINAL", + "tours": "tour_id", + } + + +# Used by conftest.py initialize_pipeline method +# Set to true if you need to read skims into the pipeline +@pytest.fixture(scope="module") +def initialize_network_los() -> bool: + """ + A pytest boolean fixture indicating whether network skims should be read from the + fixtures test data folder. + :return: bool + """ + return False + + +@pytest.fixture(scope="module") +def load_checkpoint() -> bool: + """ + checkpoint to be loaded from the pipeline when reconnecting. + """ + return "initialize_households" + + +# make a reconnect_pipeline internal to test module +@pytest.mark.skipif( + os.path.isfile("test/non_mandatory_tour_frequency/output/pipeline.h5"), + reason="no need to recreate pipeline store if alreayd exist", +) +def test_prepare_input_pipeline(initialize_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["initialize_landuse", "initialize_households"]) + + # get the updated pipeline data + person_df = pipeline.get_table("persons") + person_df.to_csv("test/non_mandatory_tour_frequency/output/person.csv", index=False) + + # get the updated pipeline data + household_df = pipeline.get_table("households") + household_df.to_csv( + "test/non_mandatory_tour_frequency/output/household.csv", index=False + ) + + pipeline.close_pipeline() + + +def test_nmtf_from_pipeline(reconnect_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run( + models=["non_mandatory_tour_frequency"], resume_after="initialize_households" + ) + + # get the updated pipeline data + person_df = pipeline.get_table("persons") + + # get the updated pipeline data + household_df = pipeline.get_table("households") + + ############################ + # person nmtf validation + ############################ + # nmtf person result from the model + logger.info("person nmtf pattern validation") + + target_key = "inmf_choice" + simulated_key = "non_mandatory_tour_frequency" + similarity_threshold = 0.99 + + simulated_df = create_summary( + person_df, key=simulated_key, out_col="Simulated_Share" + ) + + # result from the TM2 run + target_df = create_summary(person_df, key=target_key, out_col="Target_Share") + + # compare simulated and target results + similarity_value = compare_simulated_against_target( + target_df, simulated_df, target_key, simulated_key + ) + + # if the cosine_similarity >= threshold then the simulated and target results are "similar" + assert similarity_value >= similarity_threshold + + +# fetch/prepare existing files for model inputs +# e.g. read accessibilities.csv from ctramp result, rename columns, write out to accessibility.csv which is the input to activitysim +@pytest.fixture(scope="module") +def prepare_module_inputs() -> None: + """ + copy input files from sharepoint into test folder + + create unique person id in person file + + :return: None + """ + # https://wsponlinenam.sharepoint.com/sites/US-TM2ConversionProject/Shared%20Documents/Forms/ + # AllItems.aspx?id=%2Fsites%2FUS%2DTM2ConversionProject%2FShared%20Documents%2FTask%203%20ActivitySim&viewid=7a1eaca7%2D3999%2D4d45%2D9701%2D9943cc3d6ab1 + test_dir = os.path.join("test", "non_mandatory_tour_frequency", "data") + + accessibility_file = os.path.join(test_dir, "tm2_outputs", "accessibilities.csv") + household_file = os.path.join(test_dir, "popsyn", "households.csv") + person_file = os.path.join(test_dir, "popsyn", "persons.csv") + landuse_file = os.path.join(test_dir, "landuse", "maz_data_withDensity.csv") + + shutil.copy(accessibility_file, os.path.join(test_dir, "accessibility.csv")) + shutil.copy(household_file, os.path.join(test_dir, "households.csv")) + shutil.copy(person_file, os.path.join(test_dir, "persons.csv")) + shutil.copy(landuse_file, os.path.join(test_dir, "land_use.csv")) + + # add original maz id to accessibility table + land_use_df = pd.read_csv(os.path.join(test_dir, "land_use.csv")) + accessibility_df = pd.read_csv(os.path.join(test_dir, "accessibility.csv")) + + accessibility_df = pd.merge( + accessibility_df, + land_use_df[["MAZ", "MAZ_ORIGINAL"]].rename(columns={"MAZ": "mgra"}), + how="left", + on="mgra", + ) + + accessibility_df.to_csv(os.path.join(test_dir, "accessibility.csv"), index=False) + + # currently household file has to have these two columns, even before annotation + # because annotate person happens before household and uses these two columns + # TODO find a way to get around this + #### + household_df = pd.read_csv(os.path.join(test_dir, "households.csv")) + + household_columns_dict = {"HHID": "household_id", "MAZ": "home_zone_id"} + + household_df.rename(columns=household_columns_dict, inplace=True) + + tm2_simulated_household_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "householdData_1.csv") + ) + tm2_simulated_household_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + household_df = pd.merge( + household_df, + tm2_simulated_household_df[ + [ + "household_id", + "autos", + "automated_vehicles", + "transponder", + "cdap_pattern", + "jtf_choice", + ] + ], + how="inner", # tm2 is not 100% sample run + on="household_id", + ) + + household_df.to_csv(os.path.join(test_dir, "households.csv"), index=False) + + person_df = pd.read_csv(os.path.join(test_dir, "persons.csv")) + + person_columns_dict = {"HHID": "household_id", "PERID": "person_id"} + + person_df.rename(columns=person_columns_dict, inplace=True) + + tm2_simulated_person_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "personData_1.csv") + ) + tm2_simulated_person_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + person_df = pd.merge( + person_df, + tm2_simulated_person_df[ + [ + "household_id", + "person_id", + "person_num", + "type", + "value_of_time", + "activity_pattern", + "imf_choice", + "inmf_choice", + "fp_choice", + "reimb_pct", + "workDCLogsum", + "schoolDCLogsum", + ] + ], + how="inner", # tm2 is not 100% sample run + on=["household_id", "person_id"], + ) + + # get tm2 simulated workplace and school location results + tm2_simulated_wsloc_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "wsLocResults_1.csv") + ) + tm2_simulated_wsloc_df.rename( + columns={"HHID": "household_id", "PersonID": "person_id"}, inplace=True + ) + + person_df = pd.merge( + person_df, + tm2_simulated_wsloc_df[ + [ + "household_id", + "person_id", + "WorkLocation", + "WorkLocationLogsum", # this is the same as `workDCLogsum` in tm2 person output + "SchoolLocation", + "SchoolLocationLogsum", # this is the same as `schoolDCLogsum` in tm2 person output + ] + ], + how="inner", # ctramp might not be 100% sample run + on=["household_id", "person_id"], + ) + + person_df.to_csv(os.path.join(test_dir, "persons.csv"), index=False) + + ## get tour data from tn2 output + + tm2_simulated_indiv_tour_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "indivTourData_1.csv") + ) + tm2_simulated_joint_tour_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "jointTourData_1.csv") + ) + + tm2_simulated_tour_df = pd.concat( + [tm2_simulated_indiv_tour_df, tm2_simulated_joint_tour_df], + sort=False, + ignore_index=True, + ) + + tm2_simulated_tour_df.rename(columns={"hh_id": "household_id"}).to_csv( + os.path.join(test_dir, "tours.csv"), index=False + ) + + #### + + +def create_summary(input_df, key, out_col="Share") -> pd.DataFrame: + """ + Create summary for the input data. + 1. group input data by the "key" column + 2. calculate the percent of input data records in each "key" category. + + :return: pd.DataFrame + """ + + out_df = input_df.groupby(key).size().reset_index(name="Count") + out_df[out_col] = round(out_df["Count"] / out_df["Count"].sum(), 4) + + return out_df[[key, out_col]] + + +def cosine_similarity(a, b): + """ + Computes cosine similarity between two vectors. + + Cosine similarity is used here as a metric to measure similarity between two sequence of numbers. + Two sequence of numbers are represented as vectors (in a multi-dimensional space) and cosine similiarity is defined as the cosine of the angle between them + i.e., dot products of the vectors divided by the product of their lengths. + + :return: + """ + + return dot(a, b) / (norm(a) * norm(b)) + + +def compare_simulated_against_target( + target_df: pd.DataFrame, + simulated_df: pd.DataFrame, + target_key: str, + simulated_key: str, +) -> bool: + """ + compares the simulated and target results by computing the cosine similarity between them. + + :return: + """ + + merged_df = pd.merge( + target_df, simulated_df, left_on=target_key, right_on=simulated_key, how="outer" + ) + merged_df = merged_df.fillna(0) + + logger.info("simulated vs target share:\n%s" % merged_df) + + similarity_value = cosine_similarity( + merged_df["Target_Share"].tolist(), merged_df["Simulated_Share"].tolist() + ) + + logger.info("cosine similarity:\n%s" % similarity_value) + + return similarity_value diff --git a/test/parking_location/.gitkeep b/test/parking_location/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/parking_location/compare-parking-location-results.R b/test/parking_location/compare-parking-location-results.R new file mode 100644 index 000000000..22c607f8d --- /dev/null +++ b/test/parking_location/compare-parking-location-results.R @@ -0,0 +1,62 @@ +library(tidyverse) +library(ggplot2) + +trips_df <- read_csv("./output/trips_after_parking_choice.csv") + +walk_dist_df <- read_csv("./data/ped_distance_maz_maz.csv") + +landuse_df <- read_csv("./data/land_use.csv") + +landuse_df <- landuse_df %>% + select(maz, maz_county_based, TAZ_ORIGINAL) + +work_df <- trips_df %>% + rename(parking_maz_target = parking_mgra) %>% + rename(parking_maz_simulated = parking_zone) %>% + select(trip_id, household_id, person_id, person_num, stop_id, tour_purpose, orig_purpose, dest_purpose, orig_maz = origin, dest_maz = destination, + activity_duration_in_hours, parking_maz_target, parking_maz_simulated) %>% + left_join(landuse_df, by = c("orig_maz" = "maz")) %>% + rename(orig_maz_county_based = maz_county_based, orig_taz = TAZ_ORIGINAL) %>% + left_join(landuse_df, by = c("dest_maz" = "maz")) %>% + rename(dest_maz_county_based = maz_county_based, dest_taz = TAZ_ORIGINAL) %>% + left_join(landuse_df, by = c("parking_maz_target" = "maz")) %>% + rename(parking_maz_county_based_target = maz_county_based, parking_taz_target = TAZ_ORIGINAL) %>% + left_join(landuse_df, by = c("parking_maz_simulated" = "maz")) %>% + rename(parking_maz_county_based_simulated = maz_county_based, parking_taz_simulated = TAZ_ORIGINAL) %>% + left_join(walk_dist_df, by = c("parking_maz_simulated" = "OMAZ", "dest_maz" = "DMAZ")) %>% + rename(parking_distance_simulated = DISTWALK) %>% + left_join(walk_dist_df, by = c("parking_maz_target" = "OMAZ", "dest_maz" = "DMAZ")) %>% + rename(parking_distance_target = DISTWALK) %>% + left_join(walk_dist_df, by = c("parking_maz_target" = "OMAZ", "parking_maz_simulated" = "DMAZ")) %>% + rename(distance_target_simulation = DISTWALK) %>% + select(trip_id, household_id, person_id, stop_id, tour_purpose, orig_purpose, dest_purpose, + orig_maz, dest_maz, orig_maz_county_based, dest_maz_county_based, orig_taz, dest_taz, + parking_maz_target, parking_maz_simulated, parking_taz_target, parking_taz_simulated, + parking_distance_target, parking_distance_simulated, distance_target_simulation) + + +write.csv(work_df, "./output/parking-location-choice-results.csv", row.names = F) + + +summary_df <- work_df %>% + group_by(dest_purpose) %>% + summarise( + trips_count = n(), + min_distance_target = round(min(parking_distance_target, na.rm = T), 3), + min_distance_simulated = round(min(parking_distance_simulated, na.rm = T), 3), + max_distance_target = round(max(parking_distance_target, na.rm = T), 3), + max_distance_simulated = round(max(parking_distance_simulated, na.rm = T), 3), + mean_distance_target = round(mean(parking_distance_target, na.rm = T), 3), + mean_distance_simulated = round(mean(parking_distance_simulated, na.rm = T), 3), + median_distance_target = round(median(parking_distance_target, na.rm = T), 3), + median_distance_simulated = round(median(parking_distance_simulated, na.rm = T), 3) + ) + +#ggplot(work_df, aes(x=distance_target_simulation)) + geom_histogram(binwidth=0.025, color="black", fill="white") + +#ggplot(work_df, aes(x=parking_distance_target)) + geom_histogram(binwidth=0.05, color="black", fill="white") + +#ggplot(work_df, aes(x=parking_distance_simulated)) + geom_histogram(binwidth=0.05, color="black", fill="white") + + + diff --git a/test/parking_location/configs/ParkLocationChoice.xls b/test/parking_location/configs/ParkLocationChoice.xls new file mode 100644 index 000000000..3ea952910 Binary files /dev/null and b/test/parking_location/configs/ParkLocationChoice.xls differ diff --git a/test/parking_location/configs/annotate_households.csv b/test/parking_location/configs/annotate_households.csv new file mode 100644 index 000000000..ac21d3797 --- /dev/null +++ b/test/parking_location/configs/annotate_households.csv @@ -0,0 +1,13 @@ +Description,Target,Expression +#,, annotate households table after import +,_PERSON_COUNT,"lambda query, persons, households: persons.query(query).groupby('household_id').size().reindex(households.index).fillna(0).astype(np.int8)" +number of fulltime workers,num_full_time_workers,"_PERSON_COUNT('ptype == 1', persons, households)" +number of parttime workers,num_part_time_workers,"_PERSON_COUNT('ptype == 2', persons, households)" +number of university student,num_university_students,"_PERSON_COUNT('ptype == 3', persons, households)" +number of non-workers,num_non_workers,"_PERSON_COUNT('ptype == 4', persons, households)" +number of retirees,num_retirees,"_PERSON_COUNT('ptype == 5', persons, households)" +number of driving age students,num_driving_age_students,"_PERSON_COUNT('ptype == 6', persons, households)" +number of pre-driving age school kids,num_pre_driving_age_school_kids,"_PERSON_COUNT('ptype == 7', persons, households)" +number of pre-school kids,num_pre_school_kids,"_PERSON_COUNT('ptype == 8', persons, households)" +number of pre-driving age school kids who go out,num_pre_driving_age_school_kids_go_out,"_PERSON_COUNT('(ptype == 7) & (cdap_activity != \'H\')', persons, households)" +number of pre-school kids who go out,num_pre_school_kids_go_out,"_PERSON_COUNT('(ptype == 8) & (cdap_activity != \'H\')', persons, households)" \ No newline at end of file diff --git a/test/parking_location/configs/annotate_landuse.csv b/test/parking_location/configs/annotate_landuse.csv new file mode 100644 index 000000000..76c722914 --- /dev/null +++ b/test/parking_location/configs/annotate_landuse.csv @@ -0,0 +1,7 @@ +Description,Target,Expression +#,, annotate landuse table after import +household_density,household_density,land_use.TOTHH / land_use.TOTACRE +employment_density,employment_density,land_use.TOTEMP / land_use.TOTACRE +population_density,population_density,land_use.TOTPOP / land_use.TOTACRE +density_index,density_index,(household_density *employment_density) / (household_density + employment_density).clip(lower=1) +is_parking_zone,is_parking_zone,"np.where(land_use.parkarea==1,True,False)" \ No newline at end of file diff --git a/test/parking_location/configs/annotate_persons.csv b/test/parking_location/configs/annotate_persons.csv new file mode 100644 index 000000000..eff11ab68 --- /dev/null +++ b/test/parking_location/configs/annotate_persons.csv @@ -0,0 +1,16 @@ +Description,Target,Expression +#,, annotate persons table after import +age_16_to_19,age_16_to_19,"persons.age.between(16, 19)" +age_16_p,age_16_p,persons.age >= 16 +adult,adult,persons.age >= 18 +male,male,persons.sex == 1 +female,female,persons.sex == 2 +,ptype,0 +,ptype,"np.where(persons.type == 'Full-time worker', 1, ptype)" +,ptype,"np.where(persons.type == 'Part-time worker', 2, ptype)" +,ptype,"np.where(persons.type == 'University student', 3, ptype)" +,ptype,"np.where(persons.type == 'Non-worker', 4, ptype)" +,ptype,"np.where(persons.type == 'Retired', 5, ptype)" +,ptype,"np.where(persons.type == 'Student of driving age', 6, ptype)" +,ptype,"np.where(persons.type == 'Student of non-driving age', 7, ptype)" +,ptype,"np.where(persons.type == 'Child too young for school', 8, ptype)" \ No newline at end of file diff --git a/test/parking_location/configs/annotate_persons_after_hh.csv b/test/parking_location/configs/annotate_persons_after_hh.csv new file mode 100644 index 000000000..0dfa16be6 --- /dev/null +++ b/test/parking_location/configs/annotate_persons_after_hh.csv @@ -0,0 +1,5 @@ +Description,Target,Expression +#,, annotate persons table after annotate_households +#,, adults get full hh_value_of_time and children get 60% +,_hh_vot,"reindex(households.hh_value_of_time, persons.household_id)" +,value_of_time,"_hh_vot.where(persons.age>=18, _hh_vot * 0.667)" \ No newline at end of file diff --git a/test/parking_location/configs/initialize_households.yaml b/test/parking_location/configs/initialize_households.yaml new file mode 100644 index 000000000..15891431e --- /dev/null +++ b/test/parking_location/configs/initialize_households.yaml @@ -0,0 +1,37 @@ +annotate_tables: + - tablename: persons + column_map: + HHID: household_id + PERID: person_id + AGEP: age + SEX: sex + SCHL: education_attainment + OCCP: occupation + WKHP: hours_worked + WKW: weeks_worked + EMPLOYED: employment_status + ESR: esr + SCHG: grade_attending + activity_pattern: cdap_activity + annotate: + SPEC: annotate_persons + DF: persons + TABLES: + - households + - tablename: households + column_map: + HHID: household_id + HHINCADJ: income + NWRKRS_ESR: num_workers + VEH: auto_ownership + NP: hhsize + HHT: hh_type + BLD: building_size + TYPE: hh_unit_type + MTCCountyID: county_id + annotate: + SPEC: annotate_households + DF: households + TABLES: + - persons + - land_use \ No newline at end of file diff --git a/test/parking_location/configs/initialize_landuse.yaml b/test/parking_location/configs/initialize_landuse.yaml new file mode 100644 index 000000000..d30ddb245 --- /dev/null +++ b/test/parking_location/configs/initialize_landuse.yaml @@ -0,0 +1,52 @@ +annotate_tables: + - tablename: land_use + column_map: + CountyID: county_id + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + annotate: + SPEC: annotate_landuse + DF: land_use + - tablename: accessibility + column_map: + column_1: nonmandatory_auto_accessibility + column_2: nonmandatory_transit_accessibility + column_3: nonmandatory_nm_accessibility + column_4: nonmandatory_sov0_accessibility + column_5: nonmandatory_sov1_accessibility + column_6: nonmandatory_sov2_accessibility + column_7: nonmandatory_hov0_accessibility + column_8: nonmandatory_hov1_accessibility + column_9: nonmandatory_hov2_accessibility + column_10: shop_hov_insufficient_accessibility + column_11: shop_hov_sufficient_accessibility + column_12: shop_hov_oversufficient_accessibility + column_13: maint_hov_insufficient_accessibility + column_14: maint_hov_sufficient_accessibility + column_15: maint_hov_oversufficient_accessibility + column_16: eat_hov_insufficient_accessibility + column_17: eat_hov_sufficient_accessibility + column_18: eat_hov_oversufficient_accessibility + column_19: visit_hov_insufficient_accessibility + column_20: visit_hov_sufficient_accessibility + column_21: visit_hov_oversufficient_accessibility + column_22: discr_hov_insufficient_accessibility + column_23: discr_hov_sufficient_accessibility + column_24: discr_hov_oversufficient_accessibility + column_25: escort_hov_insufficient_accessibility + column_26: escort_hov_sufficient_accessibility + column_27: escort_hov_oversufficient_accessibility + column_28: shop_sov_insufficient_accessibility + column_29: shop_sov_sufficient_accessibility + column_30: shop_sov_oversufficient_accessibility + column_31: maint_sov_insufficient_accessibility + column_32: maint_sov_sufficient_accessibility + column_33: maint_sov_oversufficient_accessibility + column_40: discr_sov_insufficient_accessibility + column_41: discr_sov_sufficient_accessibility + column_42: discr_sov_oversufficient_accessibility + column_45: total_emp_accessibility + column_47: hh_walktransit_accessibility \ No newline at end of file diff --git a/test/parking_location/configs/network_los.yaml b/test/parking_location/configs/network_los.yaml new file mode 100644 index 000000000..5603ab859 --- /dev/null +++ b/test/parking_location/configs/network_los.yaml @@ -0,0 +1,24 @@ +# read cached skims (using numpy memmap) from output directory (memmap is faster than omx ) +read_skim_cache: False +# write memmapped cached skims to output directory after reading from omx, for use in subsequent runs +write_skim_cache: False + +zone_system: 2 + +taz_skims: skims.omx + +maz: maz.csv + +maz_to_maz: + tables: + - ped_distance_maz_maz.csv + + # maz_to_maz blending distance (missing or 0 means no blending) + max_blend_distance: + DISTWALK: 0 + +skim_time_periods: + time_window: 1440 + period_minutes: 60 + periods: [0, 3, 5, 9, 14, 18, 24] # 3=3:00-3:59, 5=5:00-5:59, 9=9:00-9:59, 14=2:00-2:59, 18=6:00-6:59 + labels: ['EA', 'EA', 'AM', 'MD', 'PM', 'EV'] \ No newline at end of file diff --git a/test/parking_location/configs/parking_location_choice.csv b/test/parking_location/configs/parking_location_choice.csv new file mode 100644 index 000000000..d9a10c39d --- /dev/null +++ b/test/parking_location/configs/parking_location_choice.csv @@ -0,0 +1,34 @@ +Description,Expression,no_segmentation +Person is worker,_person_is_worker@((df.ptype == 1) | (df.ptype == 2)),1 +Trip is work purpose,_work_trip@(df.purpose == 'work'),1 +Number of hourly stalls,_hourly_stalls@df.hstallsoth,1 +Number of daily stalls,_daily_stalls@df.dstallsoth,1 +Number of monthly stalls,_monthly_stalls@df.mstallsoth,1 +Hourly stalls available,_hourly_stalls_available@_hourly_stalls > 0,1 +Daily stalls available,_daily_stalls_available@_daily_stalls > 0,1 +Monthly stalls available,_monthly_stalls_available@_monthly_stalls > 0,1 +Hourly parking cost cents,_hourly_parking_cost@df.hparkcost * 100,1 +Number of free parking hours,_num_free_hours@df.numfreehrs,1 +Daily parking cost cents,_daily_parking_cost@df.dparkcost * 100,1 +Monthly parking cost cents,_monthly_parking_cost@df.mparkcost * 100,1 +Monthly parking is allowed,_monthly_allowed@_monthly_stalls_available & _work_trip & _person_is_worker,1 +Total hourly parking cost,_total_hourly_parking_cost@(_hourly_parking_cost * (df.activity_duration - _num_free_hours)),1 +Hourly is cheaper than daily,"_hourly_cheaper_than_daily@np.where(_daily_stalls_available, _total_hourly_parking_cost < _daily_parking_cost,True)",1 +Hourly is cheaper than monthly,"_hourly_cheaper_than_monthly@np.where(_monthly_allowed, _total_hourly_parking_cost < _monthly_parking_cost,True)",1 +Hourly parking is best,_hourly_best@(_hourly_stalls_available & _hourly_cheaper_than_daily & _hourly_cheaper_than_monthly),1 +Daily is cheaper than hourly,"_daily_cheaper_than_hourly@np.where(_hourly_stalls_available, _daily_parking_cost < _total_hourly_parking_cost,True)",1 +Daily is cheaper than monthly,"_daily_cheaper_than_monthly@np.where(_monthly_allowed, _daily_parking_cost < _monthly_parking_cost,True)",1 +Daily parking is best,_daily_best@(_daily_stalls_available & _daily_cheaper_than_hourly & _daily_cheaper_than_monthly),1 +Monthly is cheaper than hourly,"_monthly_cheaper_than_hourly@np.where(_hourly_stalls_available, _monthly_parking_cost < _total_hourly_parking_cost,True)",1 +Monthly is cheaper than daily,"_monthly_cheaper_than_daily@np.where(_daily_stalls_available, _monthly_parking_cost < _daily_stalls_available,True)",1 +Monthly parking is best,_monthly_best@(_monthly_allowed & _monthly_cheaper_than_hourly & _monthly_cheaper_than_daily),1 +Parking size,_parking_size@(_hourly_best * _hourly_stalls) + (_daily_best * _daily_stalls) + (_monthly_best * _monthly_stalls),1 +Parking cost,_parking_cost@(_hourly_best * _total_hourly_parking_cost) + (_daily_best * _daily_parking_cost) + (_monthly_best * _monthly_parking_cost),1 +Parking to destination distance skim,_walk_distance@pd_skims['DISTWALK'],1 +# actual utility terms starts from here +Log of parking size,"@np.where(_parking_size>0,np.log(_parking_size),-9999)",1 +Cost work trip,"@np.where(df.purpose == 'work', _parking_cost, 0)",coef_cost_work_trip +Cost other trip,"@np.where(df.purpose != 'work', _parking_cost, 0)",coef_cost_other_trip +Walk distance,@_walk_distance,coef_walk_distance +Walk Unavailability,"@np.where(_walk_distance == 0, 1, 0)",coef_unavailable +Require parking zone to be less than 0.75 mile from dest,"@np.where(_walk_distance > 0.75, 1, 0) * (df.destination != df.parking_zone)",coef_unavailable \ No newline at end of file diff --git a/test/parking_location/configs/parking_location_choice.yaml b/test/parking_location/configs/parking_location_choice.yaml new file mode 100644 index 000000000..e7992c7e6 --- /dev/null +++ b/test/parking_location/configs/parking_location_choice.yaml @@ -0,0 +1,22 @@ +SPECIFICATION: parking_location_choice.csv + +COEFFICIENTS: parking_location_choice_coeffs.csv + +PREPROCESSOR: + SPEC: parking_location_choice_annotate_trips_preprocessor + DF: trips_merged + TABLES: + - land_use + - persons + +# boolean column to filter choosers (True means keep) +CHOOSER_FILTER_COLUMN_NAME: is_park_eligible +CHOOSER_SEGMENT_COLUMN_NAME: parking_segment + +ALTERNATIVE_FILTER_COLUMN_NAME: is_parking_zone +ALT_DEST_COL_NAME: parking_zone + +TRIP_DEPARTURE_PERIOD: 'stop_period' + +TRIP_ORIGIN: origin +TRIP_DESTINATION: destination diff --git a/test/parking_location/configs/parking_location_choice_annotate_trips_preprocessor.csv b/test/parking_location/configs/parking_location_choice_annotate_trips_preprocessor.csv new file mode 100644 index 000000000..a49f48b12 --- /dev/null +++ b/test/parking_location/configs/parking_location_choice_annotate_trips_preprocessor.csv @@ -0,0 +1,6 @@ +Description,Target,Expression +Person Type,ptype,"reindex(persons.ptype, df.person_id)" +Trip mode is drive,drive_trip,df.trip_mode <= 8 +Parking segment,parking_segment,setting('segment') +Parking eligible trip,is_park_eligible,(drive_trip & (df.purpose != "home")) +Activity duration,activity_duration,df.activity_duration_in_hours diff --git a/test/parking_location/configs/parking_location_choice_coeffs.csv b/test/parking_location/configs/parking_location_choice_coeffs.csv new file mode 100644 index 000000000..0edccfbf1 --- /dev/null +++ b/test/parking_location/configs/parking_location_choice_coeffs.csv @@ -0,0 +1,5 @@ +coefficient_name,value,constrain +coef_unavailable,-9999,T +coef_walk_distance,-11.8,F +coef_cost_work_trip,-0.0072,F +coef_cost_other_trip,-0.0041,F diff --git a/test/parking_location/configs/settings.yaml b/test/parking_location/configs/settings.yaml new file mode 100644 index 000000000..1cd739cb4 --- /dev/null +++ b/test/parking_location/configs/settings.yaml @@ -0,0 +1,62 @@ +# input tables +input_table_list: + - tablename: households + filename: households.csv + index_col: household_id + rename_columns: + unique_hh_id: household_id + NP: hhsize + hh_workers_from_esr: num_workers + VEH: auto_ownership + MAZ: home_zone_id + HINCP: income + keep_columns: + - home_zone_id + - income + - hhsize + - HHT + - auto_ownership + - num_workers + - tablename: persons + filename: persons.csv + index_col: person_id + rename_columns: + unique_hh_id: household_id + AGEP: age + SPORDER: PNUM + SEX: sex + employed: pemploy + student_status: pstudent + person_type: ptype + keep_columns: + - household_id + - age + - PNUM + - sex + - pemploy + - pstudent + - ptype + - tablename: land_use + filename: land_use.csv + index_col: zone_id + rename_columns: + MAZ_ORIGINAL: zone_id + CountyID: county_id + TAZ_ORIGINAL: TAZ + DistID: DISTRICT + HH: TOTHH + POP: TOTPOP + ACRES: TOTACRE + emp_total: TOTEMP + keep_columns: + - TAZ + - DISTRICT + - SD + - county_id + - TOTHH + - TOTPOP + - TOTACRE + +trace_hh_id: 5924 + +segment: "no_segmentation" \ No newline at end of file diff --git a/test/parking_location/configs/tour_departure_and_duration_alternatives.csv b/test/parking_location/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 000000000..bddab06b9 --- /dev/null +++ b/test/parking_location/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/test/parking_location/notebook/parking-location-results-summary.twbx b/test/parking_location/notebook/parking-location-results-summary.twbx new file mode 100644 index 000000000..fa837b590 Binary files /dev/null and b/test/parking_location/notebook/parking-location-results-summary.twbx differ diff --git a/test/parking_location/test_parking_location.py b/test/parking_location/test_parking_location.py new file mode 100644 index 000000000..6859c93c4 --- /dev/null +++ b/test/parking_location/test_parking_location.py @@ -0,0 +1,458 @@ +import logging +import pytest +import os +import shutil +import pandas as pd +import numpy as np +from numpy import dot +from numpy.linalg import norm +import orca + +# import models is necessary to initalize the model steps with orca +from activitysim.abm import models +from activitysim.core import pipeline, config +from activitysim.core import tracing + +from activitysim.core import simulate +from activitysim.core import config +from activitysim.abm.models.util import estimation +import yaml + +logger = logging.getLogger(__name__) + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def module() -> str: + """ + A pytest fixture that returns the data folder location. + :return: folder location for any necessary data to initialize the tests + """ + return "parking_location" + + +# Used by conftest.py initialize_pipeline method +@pytest.fixture(scope="module") +def tables(prepare_module_inputs) -> dict[str, str]: + """ + A pytest fixture that returns the "mock" tables to build pipeline dataframes. The + key-value pair is the name of the table and the index column. + :return: dict + """ + return { + "land_use": "maz", + "persons": "person_id", + "households": "household_id", + "accessibility": "maz", + "tours": "tour_id", + "trips": "trip_id", + } + + +# Used by conftest.py initialize_pipeline method +# Set to true if you need to read skims into the pipeline +@pytest.fixture(scope="module") +def initialize_network_los() -> bool: + """ + A pytest boolean fixture indicating whether network skims should be read from the + fixtures test data folder. + :return: boolcls + """ + return True + + +@pytest.fixture(scope="module") +def load_checkpoint() -> bool: + """ + checkpoint to be loaded from the pipeline when reconnecting. + """ + return "initialize_households" + + +# make a reconnect_pipeline internal to test module +@pytest.mark.skipif( + os.path.isfile("test/parking_location/output/pipeline.h5"), + reason="no need to recreate pipeline store if already exist", +) +def test_prepare_input_pipeline(initialize_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["initialize_landuse", "initialize_households"]) + + # save the updated pipeline tables + person_df = pipeline.get_table("persons") + person_df.to_csv("test/parking_location/output/person.csv") + + household_df = pipeline.get_table("households") + household_df.to_csv("test/parking_location/output/household.csv") + + land_use_df = pipeline.get_table("land_use") + land_use_df.to_csv("test/parking_location/output/land_use.csv") + + accessibility_df = pipeline.get_table("accessibility") + accessibility_df.to_csv("test/parking_location/output/accessibility.csv") + + tours_df = pipeline.get_table("tours") + tours_df.to_csv("test/parking_location/output/tours.csv") + + trips_df = pipeline.get_table("trips") + trips_df.to_csv("test/parking_location/output/trips.csv") + + pipeline.close_pipeline() + + +# @pytest.mark.skip +def test_parking_location(reconnect_pipeline: pipeline.Pipeline, caplog): + # Run summarize model + caplog.set_level(logging.INFO) + + # run model step + pipeline.run(models=["parking_location"], resume_after="initialize_households") + + # get the updated trips data + trips_df = pipeline.get_table("trips") + trips_df.to_csv("test/parking_location/output/trips_after_parking_choice.csv") + + +# fetch/prepare existing files for model inputs +# e.g. read accessibilities.csv from ctramp result, rename columns, write out to accessibility.csv which is the input to activitysim +@pytest.fixture(scope="module") +def prepare_module_inputs() -> None: + """ + + copy input files from sharepoint into test folder + + create unique person id in person file + + :return: None + """ + # https://wsponlinenam.sharepoint.com/sites/US-TM2ConversionProject/Shared%20Documents/Forms/ + # AllItems.aspx?id=%2Fsites%2FUS%2DTM2ConversionProject%2FShared%20Documents%2FTask%203%20ActivitySim&viewid=7a1eaca7%2D3999%2D4d45%2D9701%2D9943cc3d6ab1 + test_dir = os.path.join("test", "parking_location", "data") + + accessibility_file = os.path.join( + "test", "parking_location", "data", "accessibilities.csv" + ) + household_file = os.path.join(test_dir, "popsyn", "households.csv") + person_file = os.path.join(test_dir, "popsyn", "persons.csv") + landuse_file = os.path.join(test_dir, "landuse", "maz_data_withDensity.csv") + + shutil.copy(accessibility_file, os.path.join(test_dir, "accessibility.csv")) + shutil.copy(household_file, os.path.join(test_dir, "households.csv")) + shutil.copy(person_file, os.path.join(test_dir, "persons.csv")) + shutil.copy(landuse_file, os.path.join(test_dir, "land_use.csv")) + + # add original maz id to accessibility table + land_use_df = pd.read_csv(os.path.join(test_dir, "land_use.csv")) + + land_use_df.rename( + columns={"MAZ": "maz", "MAZ_ORIGINAL": "maz_county_based"}, inplace=True + ) + + land_use_df.to_csv(os.path.join(test_dir, "land_use.csv"), index=False) + + accessibility_df = pd.read_csv(os.path.join(test_dir, "accessibility.csv")) + + accessibility_df["maz"] = accessibility_df["mgra"] + + accessibility_df.to_csv(os.path.join(test_dir, "accessibility.csv"), index=False) + + # currently household file has to have these two columns, even before annotation + # because annotate person happens before household and uses these two columns + # TODO find a way to get around this + #### + household_df = pd.read_csv(os.path.join(test_dir, "households.csv")) + + household_columns_dict = { + "HHID": "household_id", + "TAZ": "taz", + "MAZ": "maz_county_based", + } + + household_df.rename(columns=household_columns_dict, inplace=True) + + tm2_simulated_household_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "householdData_1.csv") + ) + tm2_simulated_household_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + household_df = pd.merge( + household_df, + tm2_simulated_household_df[ + [ + "household_id", + "autos", + "automated_vehicles", + "transponder", + "cdap_pattern", + "jtf_choice", + ] + ], + how="inner", # tm2 is not 100% sample run + on="household_id", + ) + + household_df.to_csv(os.path.join(test_dir, "households.csv"), index=False) + + person_df = pd.read_csv(os.path.join(test_dir, "persons.csv")) + + person_columns_dict = {"HHID": "household_id", "PERID": "person_id"} + + person_df.rename(columns=person_columns_dict, inplace=True) + + tm2_simulated_person_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "personData_1.csv") + ) + tm2_simulated_person_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + person_df = pd.merge( + person_df, + tm2_simulated_person_df[ + [ + "household_id", + "person_id", + "person_num", + "type", + "value_of_time", + "activity_pattern", + "imf_choice", + "inmf_choice", + "fp_choice", + "reimb_pct", + "workDCLogsum", + "schoolDCLogsum", + ] + ], + how="inner", # tm2 is not 100% sample run + on=["household_id", "person_id"], + ) + + # get tm2 simulated workplace and school location results + tm2_simulated_wsloc_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "wsLocResults_1.csv") + ) + tm2_simulated_wsloc_df.rename( + columns={"HHID": "household_id", "PersonID": "person_id"}, inplace=True + ) + + person_df = pd.merge( + person_df, + tm2_simulated_wsloc_df[ + [ + "household_id", + "person_id", + "WorkLocation", + "WorkLocationLogsum", # this is the same as `workDCLogsum` in tm2 person output + "SchoolLocation", + "SchoolLocationLogsum", # this is the same as `schoolDCLogsum` in tm2 person output + ] + ], + how="inner", # ctramp might not be 100% sample run + on=["household_id", "person_id"], + ) + + person_df.to_csv(os.path.join(test_dir, "persons.csv"), index=False) + + ## get tour data from tm2 output + + tm2_simulated_indiv_tour_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "indivTourData_1.csv") + ) + tm2_simulated_joint_tour_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "jointTourData_1.csv") + ) + + tm2_simulated_tour_df = pd.concat( + [tm2_simulated_indiv_tour_df, tm2_simulated_joint_tour_df], + sort=False, + ignore_index=True, + ) + + tm2_simulated_tour_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + tm2_simulated_tour_df["unique_tour_id"] = range(1, len(tm2_simulated_tour_df) + 1) + + ## get trip data from tm2 output + tm2_simulated_indiv_trip_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "indivTripData_1.csv") + ) + tm2_simulated_joint_trip_df = pd.read_csv( + os.path.join(test_dir, "tm2_outputs", "jointTripData_1.csv") + ) + + tm2_simulated_trip_df = pd.concat( + [tm2_simulated_indiv_trip_df, tm2_simulated_joint_trip_df], + sort=False, + ignore_index=True, + ) + + tm2_simulated_trip_df.rename(columns={"hh_id": "household_id"}, inplace=True) + + tm2_simulated_trip_df["trip_id"] = range(1, len(tm2_simulated_trip_df) + 1) + + tm2_simulated_trip_df = pd.merge( + tm2_simulated_trip_df, + tm2_simulated_tour_df[ + [ + "household_id", + "person_id", + "tour_id", + "tour_purpose", + "unique_tour_id", + "start_period", + "end_period", + ] + ], + how="left", + on=["household_id", "person_id", "tour_id", "tour_purpose"], + ) + # drop tour id and rename unique_tour_id to tour_id + tm2_simulated_tour_df.drop(["tour_id"], axis=1, inplace=True) + tm2_simulated_tour_df.rename(columns={"unique_tour_id": "tour_id"}, inplace=True) + + tm2_simulated_trip_df.drop(["tour_id"], axis=1, inplace=True) + tm2_simulated_trip_df.rename( + columns={ + "unique_tour_id": "tour_id", + "orig_mgra": "origin", + "dest_mgra": "destination", + "start_period": "tour_start_period", + "end_period": "tour_end_period", + }, + inplace=True, + ) + + tm2_simulated_trip_df["purpose"] = tm2_simulated_trip_df["dest_purpose"].str.lower() + + period_map_df = pd.read_csv(os.path.join(test_dir, "period_mapping_mtc.csv")) + + tm2_simulated_trip_df.sort_values( + by=["household_id", "person_id", "person_num", "stop_period", "tour_id"], + inplace=True, + ) + + tm2_simulated_trip_df = pd.merge( + tm2_simulated_trip_df, + period_map_df, + left_on="stop_period", + right_on="period", + how="left", + ) + + tm2_simulated_trip_df["trip_departure_time"] = tm2_simulated_trip_df[ + "minutes_reference" + ] + tm2_simulated_trip_df["trip_arrival_time"] = ( + tm2_simulated_trip_df["trip_departure_time"] + + tm2_simulated_trip_df["TRIP_TIME"] + ) + tm2_simulated_trip_df["next_trip_departure_time"] = tm2_simulated_trip_df.groupby( + ["household_id", "person_id", "person_num"] + )["trip_arrival_time"].shift(-1) + + # activity duration is start of next trip - end of current trip + tm2_simulated_trip_df["activity_duration"] = ( + tm2_simulated_trip_df["next_trip_departure_time"] + - tm2_simulated_trip_df["trip_arrival_time"] + ) + + # set default activity duration to 5 minutes + tm2_simulated_trip_df["activity_duration"] = np.where( + tm2_simulated_trip_df["activity_duration"] > 0, + tm2_simulated_trip_df["activity_duration"], + 5, + ) + + # activity duration in hours + tm2_simulated_trip_df["activity_duration_in_hours"] = ( + tm2_simulated_trip_df["activity_duration"] / 60 + ) + + tm2_simulated_trip_df.drop( + [ + "period", + "start_time", + "end_time", + "minutes_reference", + "trip_departure_time", + "trip_arrival_time", + "next_trip_departure_time", + "activity_duration", + ], + inplace=True, + axis=1, + ) + + # randomly select 100,000 trips to run the parking location choice model + # memory constraint on `logit.interaction_dataset` for large trips table + # tm2_simulated_trip_df = tm2_simulated_trip_df.sample(100000, random_state=1) + + # select only if target parking maz is > 0 + tm2_simulated_trip_df = tm2_simulated_trip_df[ + tm2_simulated_trip_df["parking_mgra"] > 0 + ] + + tm2_simulated_tour_df = tm2_simulated_tour_df[ + tm2_simulated_tour_df.household_id.isin(tm2_simulated_trip_df.household_id) + ] + tm2_simulated_tour_df.to_csv(os.path.join(test_dir, "tours.csv"), index=False) + + tm2_simulated_trip_df.to_csv(os.path.join(test_dir, "trips.csv"), index=False) + + +def create_summary(input_df, key, out_col="Share") -> pd.DataFrame: + """ + Create summary for the input data. + 1. group input data by the "key" column + 2. calculate the percent of input data records in each "key" category. + + :return: pd.DataFrame + """ + + out_df = input_df.groupby(key).size().reset_index(name="Count") + out_df[out_col] = round(out_df["Count"] / out_df["Count"].sum(), 4) + + return out_df[[key, out_col]] + + +def cosine_similarity(a, b): + """ + Computes cosine similarity between two vectors. + + Cosine similarity is used here as a metric to measure similarity between two sequence of numbers. + Two sequence of numbers are represented as vectors (in a multi-dimensional space) and cosine similiarity is defined as the cosine of the angle between them + i.e., dot products of the vectors divided by the product of their lengths. + + :return: + """ + + return dot(a, b) / (norm(a) * norm(b)) + + +def compare_simulated_against_target( + target_df: pd.DataFrame, + simulated_df: pd.DataFrame, + target_key: str, + simulated_key: str, +) -> bool: + """ + compares the simulated and target results by computing the cosine similarity between them. + + :return: + """ + + merged_df = pd.merge( + target_df, simulated_df, left_on=target_key, right_on=simulated_key, how="outer" + ) + merged_df = merged_df.fillna(0) + + logger.info("simulated vs target share:\n%s" % merged_df) + + similarity_value = cosine_similarity( + merged_df["Target_Share"].tolist(), merged_df["Simulated_Share"].tolist() + ) + + logger.info("cosine similarity:\n%s" % similarity_value) + + return similarity_value