Skip to content

Commit

Permalink
Merge pull request #3790 from LBNL-UCB-STI/inm/ride_hail_transit_fix_…
Browse files Browse the repository at this point in the history
…3781

Fix: ride hail transit re-enable
  • Loading branch information
nikolayilyin authored Oct 4, 2023
2 parents 96516d4 + 1a90713 commit 9686a0b
Show file tree
Hide file tree
Showing 42 changed files with 719 additions and 60 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ beam-gui/build
/test/input/sf-light/counts/preprocessing/2015_all/
gc_*.log
/test/input/sf-light/sf-light-calibration/experiments/
/test/input/beamville/graphhopper
/test/input/sf-light/graphhopper
/test/input/sf-light/sf-light-calibration-test/experiments/
test/input/siouxfalls/*.xml
test/input/siouxfalls/r5/*.zip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,21 +652,21 @@ trait ChoosesMode {
}
}

val driveTransitTrip = theRouterResult.itineraries.find(_.tripClassifier == DRIVE_TRANSIT)
val rhTransitTrip = theRouterResult.itineraries.find(_.tripClassifier == RIDE_HAIL_TRANSIT)
// If there's a drive-transit trip AND we don't have an error RH2Tr response (due to no desire to use RH) then seek RH on access and egress
val newPersonData =
if (
shouldAttemptRideHail2Transit(
driveTransitTrip,
rhTransitTrip,
choosesModeData.rideHail2TransitAccessResult
)
) {
val accessSegment =
driveTransitTrip.get.legs.view
rhTransitTrip.get.legs.view
.takeWhile(!_.beamLeg.mode.isMassTransit)
.map(_.beamLeg)
val egressSegment =
driveTransitTrip.get.legs.view.reverse.takeWhile(!_.beamLeg.mode.isTransit).reverse.map(_.beamLeg)
rhTransitTrip.get.legs.view.reverse.takeWhile(!_.beamLeg.mode.isTransit).reverse.map(_.beamLeg)
val accessId =
if (accessSegment.map(_.travelPath.distanceInM).sum > 0) {
makeRideHailRequestFromBeamLeg(accessSegment)
Expand All @@ -680,7 +680,7 @@ trait ChoosesMode {
None
}
choosesModeData.copy(
rideHail2TransitRoutingResponse = Some(driveTransitTrip.get),
rideHail2TransitRoutingResponse = Some(rhTransitTrip.get),
rideHail2TransitAccessInquiryId = accessId,
rideHail2TransitEgressInquiryId = egressId,
rideHail2TransitAccessResult = if (accessId.isEmpty) {
Expand Down
14 changes: 11 additions & 3 deletions src/main/scala/beam/sim/population/PopulationAdjustment.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ trait PopulationAdjustment extends LazyLogging {
populationWithAttributes
}

// required for testing purposes
def logInfo(message: String): Unit = logger.info(message)

// required for testing purposes
def logError(message: String): Unit = logger.error(message)

/**
* Verified if all individuals have the excluded modes attribute and logs the count of each excluded mode.
*
Expand All @@ -79,15 +85,17 @@ trait PopulationAdjustment extends LazyLogging {
.flatMap(_.split(","))

if (allExcludedModes.nonEmpty) {
logger.info(s"Modes excluded:")
logInfo(s"Modes excluded:")
allExcludedModes
.groupBy(identity)
.foreach { case (mode, modes) => logger.info(s"$mode -> ${modes.size}") }
.foreach { case (mode, modes) => logInfo(s"$mode -> ${modes.size}") }
} else {
logInfo(s"There are no excluded modes.")
}

// log error if excluded modes attributes is missing for at least one person in the population
if (persons.size != excludedModesPerPerson.size) {
logger.error("Not all agents have person attributes - is attributes file missing ?")
logError("Not all agents have person attributes - is attributes file missing ?")
}
}

Expand Down
208 changes: 193 additions & 15 deletions src/test/scala/beam/integration/ModeChoiceSpec.scala
Original file line number Diff line number Diff line change
@@ -1,26 +1,204 @@
package beam.integration

import beam.sim.BeamHelper
import beam.utils.TestConfigUtils.testConfig
import com.typesafe.config.{Config, ConfigValueFactory}
import org.scalatest.AppendedClues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

/**
* Created by fdariasm on 29/08/2017
*/
class ModeChoiceSpec extends AnyWordSpecLike with Matchers with BeamHelper with IntegrationSpecCommon {

// "Running beam with modeChoiceClass ModeChoiceDriveIfAvailable" must {
// "prefer mode choice car type than other modes" in {
// val theRun = new StartWithCustomConfig(
// baseConfig.withValue(TestConstants.KEY_AGENT_MODAL_BEHAVIORS_MODE_CHOICE_CLASS, ConfigValueFactory.fromAnyRef
// ("ModeChoiceDriveIfAvailable"))
// )
// val testModeCount = theRun.groupedCount.getOrElse("car", 0)
// val otherModesCount = theRun.groupedCount.getOrElse("ride_hail", 0) +
// theRun.groupedCount.getOrElse("walk_transit", 0) + theRun.groupedCount.getOrElse("drive_transit", 0) +
// theRun.groupedCount.getOrElse("bike", 0)
// testModeCount should be >= otherModesCount
// }
// }
class ModeChoiceSpec
extends AnyWordSpecLike
with Matchers
with BeamHelper
with IntegrationSpecCommon
with AppendedClues {

def getModesOtherThan(excludedMode: String, simulationModes: Map[String, Int]): Int = {
simulationModes.foldLeft(0) {
case (countOfModes, (mode, _)) if mode == excludedMode => countOfModes
case (countOfModes, (_, count)) => countOfModes + count
}
}

def getClueText(simulationModes: Map[String, Int]): String = {
val allModesString = simulationModes.map { case (mode, count) => s"$mode:$count" }.mkString(", ")
s", all modes are: $allModesString"
}

def baseBeamvilleUrbansimConfig: Config = testConfig("test/input/beamville/beam-urbansimv2-modechoicespec.conf")
// .withValue("beam.agentsim.lastIteration", ConfigValueFactory.fromAnyRef("0"))
// .withValue("beam.urbansim.fractionOfModesToClear.allModes", ConfigValueFactory.fromAnyRef("1.0"))
// .withValue("beam.outputs.events.fileOutputFormats", ConfigValueFactory.fromAnyRef("xml"))
// .withValue("beam.agentsim.agents.vehicles.fractionOfInitialVehicleFleet", ConfigValueFactory.fromAnyRef("10.0"))
// .withValue("beam.agentsim.agents.vehicles.fractionOfPeopleWithBicycle", ConfigValueFactory.fromAnyRef("10.0"))

// these should be as low as possible
val test_mode_multiplier = 2
val test_mode_transit_multiplier = 20

def resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor(
selectedMode: String,
router: String,
highIntercept: Int = 999999
): Config = {
baseBeamvilleUrbansimConfig
.withValue(
s"beam.agentsim.agents.modalBehaviors.multinomialLogit.params.$selectedMode",
ConfigValueFactory.fromAnyRef(highIntercept)
)
.withValue(
s"beam.routing.carRouter",
ConfigValueFactory.fromAnyRef(router)
)
.resolve()
}

"Running beam with high intercepts for drive transit" must {
"use drive transit with R5 router" ignore {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("drive_transit_intercept", "R5")
)

val driveTransitModeCount = theRun.groupedCount.getOrElse("drive_transit", 0)
val theRestModes = getModesOtherThan("drive_transit", theRun.groupedCount)
driveTransitModeCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(
theRun.groupedCount
)
}

"use drive transit with GH router" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("drive_transit_intercept", "staticGH")
)

val driveTransitModeCount = theRun.groupedCount.getOrElse("drive_transit", 0)
val theRestModes = getModesOtherThan("drive_transit", theRun.groupedCount)
driveTransitModeCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(
theRun.groupedCount
)
}
}

"Running beam with high intercepts for RH transit" must {
"use RH transit with R5 router" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("ride_hail_transit_intercept", "R5")
)

val RHTransitCount = theRun.groupedCount.getOrElse("ride_hail_transit", 0)
val theRestModes = getModesOtherThan("ride_hail_transit", theRun.groupedCount)
RHTransitCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}
}

"Running beam with high intercepts for CAV" must {
"use cav with R5 router" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("cav_intercept", "R5")
)

val cavModeCount = theRun.groupedCount.getOrElse("cav", 0)
val theRestModes = getModesOtherThan("cav", theRun.groupedCount)
cavModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}
}

"Running beam with high intercepts for bike transit" must {
"use bike transit with R5 router" ignore {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("bike_transit_intercept", "R5")
)

val bikeTransitModeCount = theRun.groupedCount.getOrElse("bike_transit", 0)
val theRestModes = getModesOtherThan("bike_transit", theRun.groupedCount)
bikeTransitModeCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(
theRun.groupedCount
)
}
}

"Running beam with high intercepts for CAR" must {
"prefer mode choice car more than other modes (with ModeChoiceDriveIfAvailable)" in {
val theRun = new StartWithCustomConfig(
baseBeamvilleUrbansimConfig
.withValue(
TestConstants.KEY_AGENT_MODAL_BEHAVIORS_MODE_CHOICE_CLASS,
ConfigValueFactory.fromAnyRef("ModeChoiceDriveIfAvailable")
)
.resolve()
)

val carModeCount = theRun.groupedCount.getOrElse("car", 0)
val theRestModes = getModesOtherThan("car", theRun.groupedCount)
carModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}

"use car with R5 router" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("car_intercept", "R5")
)

val carModeCount = theRun.groupedCount.getOrElse("car", 0)
val theRestModes = getModesOtherThan("car", theRun.groupedCount)
carModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}
}

"Running beam with specified intercept" must {
"prefer mode choice bike more than other modes" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("bike_intercept", "R5")
)

val bikeModeCount = theRun.groupedCount.getOrElse("bike", 0)
val theRestModes = getModesOtherThan("bike", theRun.groupedCount)
bikeModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}

"prefer mode choice walk more than other modes" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("walk_intercept", "R5")
)

val walkModeCount = theRun.groupedCount.getOrElse("walk", 0)
val theRestModes = getModesOtherThan("walk", theRun.groupedCount)
walkModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}

"prefer mode choice RH more than other modes" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("ride_hail_intercept", "R5")
)

val RHModeCount = theRun.groupedCount.getOrElse("ride_hail", 0)
val theRestModes = getModesOtherThan("ride_hail", theRun.groupedCount)
RHModeCount * test_mode_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}

"prefer mode choice walk transit more than other modes" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("walk_transit_intercept", "R5")
)

val walkTransitModeCount = theRun.groupedCount.getOrElse("walk_transit", 0)
val theRestModes = getModesOtherThan("walk_transit", theRun.groupedCount)
walkTransitModeCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(
theRun.groupedCount
)
}

"prefer mode choice RH pooled more than other modes" in {
val theRun: StartWithCustomConfig = new StartWithCustomConfig(
resolvedBaseBeamvilleUrbansimConfigWithHighInterceptFor("ride_hail_pooled_intercept", "R5")
)

val RHPooledCount = theRun.groupedCount.getOrElse("ride_hail_pooled", 0)
val theRestModes = getModesOtherThan("ride_hail_pooled", theRun.groupedCount)
RHPooledCount * test_mode_transit_multiplier should be >= theRestModes withClue getClueText(theRun.groupedCount)
}
}
}
Loading

0 comments on commit 9686a0b

Please sign in to comment.