Skip to content

Commit

Permalink
working with BayDAG_all_contributions
Browse files Browse the repository at this point in the history
  • Loading branch information
dhensle committed Mar 19, 2024
1 parent cf62fb3 commit 5946d27
Show file tree
Hide file tree
Showing 24 changed files with 505 additions and 580 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
output/*
output/*
extentions/__pycache__/
2 changes: 1 addition & 1 deletion configs/common/network_los.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ maz_to_maz:
- maz_maz_walk.csv
- maz_maz_bike.csv
# maz_to_maz blending distance (missing or 0 means no blending)
max_blend_distance: 2
# max_blend_distance: 2


skim_time_periods:
Expand Down
6 changes: 4 additions & 2 deletions configs/resident/disaggregate_accessibility.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Sampling size. 0 = no limit
# can be whole integer value or a sample rate (percent of zones)
# zero or missing defaults to full sample!
DESTINATION_SAMPLE_SIZE: 100
ORIGIN_SAMPLE_SIZE: 5000
# DESTINATION_SAMPLE_SIZE: 100
# ORIGIN_SAMPLE_SIZE: 5000
DESTINATION_SAMPLE_SIZE: 10
ORIGIN_SAMPLE_SIZE: 50

# select origin zones weighted by population (or another landuse variable)
ORIGIN_WEIGHTING_COLUMN: pop
Expand Down
3 changes: 2 additions & 1 deletion configs/resident/logging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ logging:

logfile:
class: logging.FileHandler
filename: !!python/object/apply:activitysim.core.config.log_file_path ['activitysim.log']
filename:
get_log_file_path: 'activitysim.log'
mode: w
formatter: fileFormatter
level: NOTSET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ number of person joint tours,num_person_joint_tours,"reindex_i(joint_tour_partic
# included for school escorting model,,
flag to denote outbound school escort tours,is_outbound_school_escort_tour,"non_mandatory_tours.index.isin(school_escort_tours[school_escort_tours['school_escort_direction'] == 'outbound'].index)"
flag to denote inbound school escort tours,is_inbound_school_escort_tour,"non_mandatory_tours.index.isin(school_escort_tours[school_escort_tours['school_escort_direction'] == 'inbound'].index)"
school escort tour start time,school_escort_tour_start,"reindex(school_escort_tours.start, non_mandatory_tours.index)"
school escort tour next start time,school_escort_tour_next_start,"reindex(school_escort_tours.next_pure_escort_start, non_mandatory_tours.index)"
school escort tour end time,school_escort_tour_end,"reindex(school_escort_tours.end, non_mandatory_tours.index)"
school escort tour start time,school_escort_tour_start,"reindex(school_escort_tours.start, non_mandatory_tours.index).fillna(-1).astype(int)"
school escort tour next start time,school_escort_tour_next_start,"reindex(school_escort_tours.next_pure_escort_start, non_mandatory_tours.index).fillna(-1).astype(int)"
school escort tour end time,school_escort_tour_end,"reindex(school_escort_tours.end, non_mandatory_tours.index).fillna(-1).astype(int)"
8 changes: 4 additions & 4 deletions configs/resident/parking_location_choice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TRIP_DEPARTURE_PERIOD: depart
TRIP_ORIGIN: origin
TRIP_DESTINATION: destination

AUTO_MODES:
- DRIVEALONE
- SHARED2
- SHARED3
# AUTO_MODES:
# - DRIVEALONE
# - SHARED2
# - SHARED3
2 changes: 1 addition & 1 deletion configs/resident/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ distributed_time_factor_nonwork_stddev: 0.6
distributed_time_factor_min: 0.1
distributed_time_factor_max: 10

resume_after:
resume_after: trip_mode_choice

models:
### mp_init_proto_pop (single process)
Expand Down
2 changes: 1 addition & 1 deletion configs/resident/settings_mp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ multiprocess_steps:
slice:
tables:
- accessibility
except: True # this is needed so landuse (i.e. destinations) doesn't get split
exclude: True # this is needed so landuse (i.e. destinations) doesn't get split
- name: mp_households
begin: av_ownership
slice:
Expand Down
1 change: 0 additions & 1 deletion configs/resident/transit_pass_subsidy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ preprocessor:
- accessibility
- land_use

CHOOSER_FILTER_COLUMN_NAME: transit_subsidy_available
2 changes: 2 additions & 0 deletions configs/resident/trip_scheduling.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# e.g. depart_alt_base = 5 means first column (column 0) represents period 5
DEPART_ALT_BASE: 0

logic_version: 2

MAX_ITERATIONS: 100

#FAILFIX: drop_and_cleanup
Expand Down
Binary file added extensions/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
20 changes: 8 additions & 12 deletions extensions/adjust_auto_operating_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,23 @@
import numpy as np
import pandas as pd

from activitysim.core import (
config,
inject,
pipeline,
)
from activitysim.core import workflow

logger = logging.getLogger(__name__)


@inject.step()
def adjust_auto_operating_cost(vehicles):
"""Adjusts the `auto_operating_cost` field in the vehicles table
@workflow.step
def adjust_auto_operating_cost(state: workflow.State, vehicles: pd.DataFrame):
"""
Adjusts the `auto_operating_cost` field in the vehicles table
so that the average is a desired value set as costPerMile in the
settings
Parameters
----------
vehicles : orca.DataFrameWrapper
vehicles : pd.DataFrame
"""
target_auto_operating_cost = config.get_global_constants()["costPerMile"]
vehicles = vehicles.to_frame()
target_auto_operating_cost = state.get_global_constants()["costPerMile"]

adjustment_factor = (
target_auto_operating_cost / vehicles["auto_operating_cost"].mean()
Expand All @@ -35,4 +31,4 @@ def adjust_auto_operating_cost(vehicles):
)
vehicles["auto_operating_cost"] *= adjustment_factor

pipeline.replace_table("vehicles", vehicles)
state.add_table("vehicles", vehicles)
46 changes: 22 additions & 24 deletions extensions/airport_returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,37 @@
import logging

import numpy as np
import pandas as pd

from activitysim.core import tracing
from activitysim.core import config
from activitysim.core import pipeline
from activitysim.core import simulate
from activitysim.core import inject
from activitysim.core import expressions

from activitysim.abm.models.util import estimation
from activitysim.core import (
config,
tracing,
workflow,
)

logger = logging.getLogger(__name__)


@inject.step()
def airport_returns(trips, chunk_size, trace_hh_id):
@workflow.step
def airport_returns(
state: workflow.State,
trips: pd.DataFrame,
model_settings_file_name: str = "airport_returns.yaml",
trace_label: str = "airport_returns",
trace_hh_id: bool = False,
):
"""
This model updates the airport trip list to include return trips for drop off
passengers. The output is a larger trip list duplicating the trips which are dropped
off at the airport to return to their origin.
The main interface to the airport returns model is the airport_returns() function.
"""

trace_label = "airport_returns"
model_settings_file_name = "airport_returns.yaml"

trip_list = trips.to_frame()
logger.info("Running %s with %d trips", trace_label, len(trip_list))
logger.info("Running %s with %d trips", trace_label, len(trips))

model_settings = config.read_model_settings(model_settings_file_name)

returning_modes = model_settings["RETURN_MODE_SEGMENTS"]
print(trips.trip_mode.unique())
trip_returns = trip_list.copy()
trip_returns = trips.copy()
trip_returns = trip_returns[trip_returns.trip_mode.isin(returning_modes)]
trip_returns["return_origin"] = trip_returns["destination"]
trip_returns["return_dest"] = trip_returns["origin"]
Expand All @@ -49,14 +47,14 @@ def airport_returns(trips, chunk_size, trace_hh_id):
)
trip_returns = trip_returns.drop(["return_origin", "return_dest"], axis=1)
trip_returns["trip_id"] = np.arange(
trip_list.index.max() + 1, trip_list.index.max() + 1 + len(trip_returns)
trips.index.max() + 1, trips.index.max() + 1 + len(trip_returns)
)
trip_returns = trip_returns.set_index("trip_id")
trip_list = trip_list.append(trip_returns)
trips = trips.append(trip_returns)

pipeline.replace_table("trips", trip_list)
state.replace_table("trips", trips)

# tracing.print_summary('airport_returns', trips.returns, value_counts=True)
tracing.print_summary("airport_returns", trips.returns, value_counts=True)

if trace_hh_id:
tracing.trace_df(trip_list, label=trace_label, warn_if_empty=True)
if state.settings.trace_hh_id:
tracing.trace_df(trips, label=trace_label, warn_if_empty=True)
110 changes: 82 additions & 28 deletions extensions/av_ownership.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,95 @@
import logging

import numpy as np

from activitysim.abm.models.util import estimation
from activitysim.core import config, expressions, inject, pipeline, simulate, tracing
import pandas as pd

from activitysim.core import (
config,
expressions,
estimation,
simulate,
tracing,
workflow,
)
from activitysim.core.configuration.base import PreprocessorSettings, PydanticReadable
from activitysim.core.configuration.logit import LogitComponentSettings

logger = logging.getLogger("activitysim")


@inject.step()
def av_ownership(households_merged, households, chunk_size, trace_hh_id):
class AVOwnershipSettings(LogitComponentSettings, extra="forbid"):
"""
Settings for the `transit_pass_subsidy` component.
"""

preprocessor: PreprocessorSettings | None = None
"""Setting for the preprocessor."""

AV_OWNERSHIP_ALT: int = 0
"""The column index number of the spec file for owning an autonomous vehicle."""

# iterative what-if analysis example
# omit these settings to not iterate
AV_OWNERSHIP_ITERATIONS: int | None = 1
"""Maximum number of auto-calibration iterations to run."""
AV_OWNERSHIP_TARGET_PERCENT: float | None = 0.0
"""Target percent of households owning an autonomous vehicle."""
AV_OWNERSHIP_TARGET_PERCENT_TOLERANCE: float | None = 0.01
"""
Tolerance for the target percent of households owning an autonomous vehicle.
Auto-calibration iterations will stop after achieving tolerance or hitting the max number.
"""
AV_OWNERSHIP_COEFFICIENT_CONSTANT: str | None = "coef_av_target_share"
"""Name of the coefficient to adjust in each auto-calibration iteration."""


@workflow.step
def av_ownership(
state: workflow.State,
households_merged: pd.DataFrame,
households: pd.DataFrame,
model_settings: AVOwnershipSettings | None = None,
model_settings_file_name: str = "av_ownership.yaml",
trace_label: str = "av_ownership",
trace_hh_id: bool = False,
) -> None:
"""
This model predicts whether a household owns an autonomous vehicle.
The output from this model is TRUE or FALSE.
"""

trace_label = "av_ownership"
model_settings_file_name = "av_ownership.yaml"

choosers = households_merged.to_frame()
model_settings = config.read_model_settings(model_settings_file_name)
if model_settings is None:
model_settings = AVOwnershipSettings.read_settings_file(
state.filesystem,
model_settings_file_name,
)

choosers = households_merged
logger.info("Running %s with %d households", trace_label, len(choosers))

estimator = estimation.manager.begin_estimation("av_ownership")
estimator = estimation.manager.begin_estimation(state, "av_ownership")

constants = config.get_model_constants(model_settings)
av_ownership_alt = model_settings.get("AV_OWNERSHIP_ALT", 0)
av_ownership_alt = model_settings.AV_OWNERSHIP_ALT

# - preprocessor
preprocessor_settings = model_settings.get("preprocessor", None)
preprocessor_settings = model_settings.preprocessor
if preprocessor_settings:

locals_d = {}
if constants is not None:
locals_d.update(constants)

expressions.assign_columns(
state,
df=choosers,
model_settings=preprocessor_settings,
locals_dict=locals_d,
trace_label=trace_label,
)

model_spec = simulate.read_model_spec(file_name=model_settings["SPEC"])
coefficients_df = simulate.read_model_coefficients(model_settings)
model_spec = state.filesystem.read_model_spec(file_name=model_settings.SPEC)
coefficients_df = state.filesystem.read_model_coefficients(model_settings)
nest_spec = config.get_logit_model_settings(model_settings)

if estimator:
Expand All @@ -56,15 +101,24 @@ def av_ownership(households_merged, households, chunk_size, trace_hh_id):
estimator.write_choosers(choosers)

# - iterative single process what-if adjustment if specified
iterations = model_settings.get("AV_OWNERSHIP_ITERATIONS", 1)
iterations_coefficient_constant = model_settings.get(
"AV_OWNERSHIP_COEFFICIENT_CONSTANT", None
)
iterations_target_percent = model_settings.get("AV_OWNERSHIP_TARGET_PERCENT", None)
iterations_target_percent_tolerance = model_settings.get(
"AV_OWNERSHIP_TARGET_PERCENT_TOLERANCE", 0.01
iterations = model_settings.AV_OWNERSHIP_ITERATIONS
iterations_coefficient_constant = model_settings.AV_OWNERSHIP_COEFFICIENT_CONSTANT
iterations_target_percent = model_settings.AV_OWNERSHIP_TARGET_PERCENT
iterations_target_percent_tolerance = (
model_settings.AV_OWNERSHIP_TARGET_PERCENT_TOLERANCE
)

# check to make sure all required settings are specified
assert (
iterations_coefficient_constant is not None if (iterations > 0) else True
), "AV_OWNERSHIP_COEFFICIENT_CONSTANT required if AV_OWNERSHIP_ITERATIONS is specified"
assert (
iterations_target_percent is not None if (iterations > 0) else True
), "AV_OWNERSHIP_TARGET_PERCENT required if AV_OWNERSHIP_ITERATIONS is specified"
assert (
iterations_target_percent_tolerance is not None if (iterations > 0) else True
), "AV_OWNERSHIP_TARGET_PERCENT_TOLERANCE required if AV_OWNERSHIP_ITERATIONS is specified"

for iteration in range(iterations):

logger.info(
Expand All @@ -75,22 +129,23 @@ def av_ownership(households_merged, households, chunk_size, trace_hh_id):
)

# re-read spec to reset substitution
model_spec = simulate.read_model_spec(file_name=model_settings["SPEC"])
model_spec = simulate.eval_coefficients(model_spec, coefficients_df, estimator)
model_spec = state.filesystem.read_model_spec(file_name=model_settings.SPEC)
model_spec = simulate.eval_coefficients(
state, model_spec, coefficients_df, estimator
)

choices = simulate.simple_simulate(
state,
choosers=choosers,
spec=model_spec,
nest_spec=nest_spec,
locals_d=constants,
chunk_size=chunk_size,
trace_label=trace_label,
trace_choice_name="av_ownership",
estimator=estimator,
)

if iterations_target_percent is not None:
# choices_for_filter = choices[choosers[iterations_chooser_filter]]

current_percent = (choices == av_ownership_alt).sum() / len(choosers)
logger.info(
Expand Down Expand Up @@ -139,12 +194,11 @@ def av_ownership(households_merged, households, chunk_size, trace_hh_id):
estimator.write_override_choices(choices)
estimator.end_estimation()

households = households.to_frame()
households["av_ownership"] = (
choices.reindex(households.index).fillna(0).astype(bool)
)

pipeline.replace_table("households", households)
state.add_table("households", households)

tracing.print_summary("av_ownership", households.av_ownership, value_counts=True)

Expand Down
Loading

0 comments on commit 5946d27

Please sign in to comment.