Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Hl/#1654 H3 Skimmer + Simple relocation algorithm for veh sharing #2264

Merged
merged 41 commits into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f8e7368
WIP
haitamlaarabi Jun 28, 2019
f14ce36
WIP
haitamlaarabi Jun 29, 2019
4b2c0bc
WIP
haitamlaarabi Jul 3, 2019
3f9f052
first prototype works fine for now
haitamlaarabi Jul 3, 2019
e7fab93
fmt
haitamlaarabi Jul 3, 2019
6b51266
move Event class into compagnion
haitamlaarabi Jul 3, 2019
0980eaa
typo
haitamlaarabi Jul 3, 2019
7850e27
backing off from abstraction
haitamlaarabi Jul 12, 2019
47276b9
changes
haitamlaarabi Aug 10, 2019
fc7e5ce
update
haitamlaarabi Oct 25, 2019
f5130ae
fix merge
haitamlaarabi Oct 25, 2019
80b8a1f
fix
haitamlaarabi Oct 25, 2019
c265942
removing abstraction
haitamlaarabi Oct 26, 2019
aed3402
fix carshare repositiong test fail
haitamlaarabi Oct 31, 2019
b09c23f
refractoring beamskimmer WIP
haitamlaarabi Nov 2, 2019
7ae9be8
design issue WIP
haitamlaarabi Nov 2, 2019
0c7eb1c
read only skim
haitamlaarabi Nov 2, 2019
571938f
Skimmer & ODSkimmer operational but still WIP
haitamlaarabi Nov 5, 2019
e47e372
fmt
haitamlaarabi Nov 5, 2019
9d498dd
beamconfig merge
haitamlaarabi Nov 5, 2019
f73e617
fix
haitamlaarabi Nov 5, 2019
8149372
WIP
haitamlaarabi Nov 8, 2019
9204df4
WIP
haitamlaarabi Nov 13, 2019
a6204ac
fmt
haitamlaarabi Nov 13, 2019
762822c
Skimmer restructured
haitamlaarabi Nov 14, 2019
2e374ab
bug fixed
haitamlaarabi Nov 15, 2019
0f2ba60
Merge remote-tracking branch 'origin/develop' into HL/#1654-beam-h3-bis
haitamlaarabi Nov 15, 2019
edff0fc
fix default configuration for skimmer
haitamlaarabi Nov 18, 2019
e3a11ae
fmt
haitamlaarabi Nov 19, 2019
7b7bd26
WIP
haitamlaarabi Nov 23, 2019
29640f6
tests are passing now
haitamlaarabi Nov 26, 2019
4841103
fixes after JustinPihony comments
haitamlaarabi Nov 26, 2019
6a25765
Merge remote-tracking branch 'origin/develop' into HL/#1654-beam-h3-bis
haitamlaarabi Nov 26, 2019
5ee8cd8
I have just finished refractoring both BeamSkimmer & TravelTimeObserved
haitamlaarabi Nov 27, 2019
6d330b6
renaming CountSkimmer to TAZSkimmer and TravelTimeSkimmer to DriveTim…
haitamlaarabi Nov 28, 2019
68b4b52
fix test
haitamlaarabi Nov 28, 2019
dc75e17
fmt
haitamlaarabi Nov 28, 2019
a115128
roll back
haitamlaarabi Nov 28, 2019
2245558
Fixed the test by expecting new messages like `ODSkimmerEvent` and `D…
REASY Nov 28, 2019
ad2f4c9
spec passing locally
haitamlaarabi Dec 2, 2019
2580294
Merge branch 'develop' into HL/#1654-beam-h3-bis
haitamlaarabi Jan 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ dependencies {

compile "com.sigopt:sigopt-java:4.9.0"

compile("com.uber:h3:3.4.1")

testCompile group: 'junit', name: 'junit', version: '4.8'
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.27.0'
testCompile group: "org.mockito", name: "mockito-core", version: "2.+"
Expand Down
44 changes: 42 additions & 2 deletions src/main/resources/beam-template.conf
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ beam.agentsim.agents.rideHail.allocationManager.repositionLowWaitingTimes.waitin
beam.agentsim.agents.rideHail.allocationManager.repositionLowWaitingTimes.demandWeight = "double | 4.0"
beam.agentsim.agents.rideHail.allocationManager.repositionLowWaitingTimes.produceDebugImages = true
beam.agentsim.agents.rideHail.allocationManager.alonsoMora.waitingTimeInSec = "int | 360"
beam.agentsim.agents.rideHail.allocationManager.alonsoMora.travelTimeDelayAsFraction= "double | 0.2"
beam.agentsim.agents.rideHail.allocationManager.alonsoMora.solutionSpaceSizePerVehicle = "int | 5"
beam.agentsim.agents.rideHail.allocationManager.alonsoMora.excessRideTimeAsFraction= "double | 0.2"
beam.agentsim.agents.rideHail.allocationManager.alonsoMora.numRequestsPerVehicle = "int | 5"
beam.agentsim.agents.rideHail.pooledToRegularRideCostRatio = 0.6

# human value of time taken from # https://theicct.org/sites/default/files/publications/Electric_shared_mobility_20190114.pdf
Expand Down Expand Up @@ -289,6 +289,46 @@ beam.beamskimmer.writeAllModeSkimsForPeakNonPeakPeriodsInterval = "int | 0"
beam.beamskimmer.writeObservedSkimsPlusInterval = "int | 0" # Generic skimmer with a "label" and a "value" of type Double
beam.beamskimmer.writeFullSkimsInterval = "int | 0"

#h3
beam.h3.resolution = "int | 10"
beam.h3.lowerBoundResolution = "int | 10"

#skims
beam.router.skim = {
keepKLatestSkims = "int | 1"
aggregateFunction = "String | AVG"
writeSkimsInterval = "int | 0"
writeAggregatedSkimsInterval = "int | 0"
skimmers = [
{
#@optional
od-skimmer {
name = "origin-destination-skimmer"
skimType = "od-skimmer"
skimFileBaseName = "skimsOD"
writeAllModeSkimsForPeakNonPeakPeriodsInterval = "int | 0"
writeFullSkimsInterval = "int | 0"
}
#@optional
count-skimmer {
name = "count-skimmer"
skimType = "count-skimmer"
skimFileBaseName = "skimsCount"
}
}
]
}

#SkimManager
beam.abstractSkimmer.keepKLatestSkims = "int | 1"
beam.abstractSkimmer.aggregateFunction = "String | LATEST_SKIM"
beam.abstractSkimmer.writeSkimsInterval = "int | 0"
beam.abstractSkimmer.writeAggregatedSkimsInterval = "int | 0"
#SkimManager - skimmer
haitamlaarabi marked this conversation as resolved.
Show resolved Hide resolved
#SkimManager - od skimmer
beam.abstractSkimmer.odSkimmer.writeAllModeSkimsForPeakNonPeakPeriodsInterval = "int | 0"
beam.abstractSkimmer.odSkimmer.writeFullSkimsInterval = "int | 0"

##################################################################
# Warm Mode
##################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AlonsoMoraPoolingAlgForRideHail(
// Methods below should be kept as def (instead of val) to allow automatic value updating
private def alonsoMora: AllocationManager.AlonsoMora =
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora
private def solutionSpaceSizePerVehicle: Int = alonsoMora.solutionSpaceSizePerVehicle
private def solutionSpaceSizePerVehicle: Int = alonsoMora.numRequestsPerVehicle
private def waitingTimeInSec: Int = alonsoMora.waitingTimeInSec

val rvG = RVGraph(classOf[RideHailTrip])
Expand Down Expand Up @@ -284,7 +284,7 @@ object AlonsoMoraPoolingAlgForRideHail {
val alonsoMora: AllocationManager.AlonsoMora =
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora
val waitingTimeInSec = alonsoMora.waitingTimeInSec
val travelTimeDelayAsFraction = alonsoMora.travelTimeDelayAsFraction
val travelTimeDelayAsFraction = alonsoMora.excessRideTimeAsFraction

val p1Act1: Activity = PopulationUtils.createActivityFromCoord(s"${vehiclePersonId.personId}Act1", src)
p1Act1.setEndTime(departureTime)
Expand Down Expand Up @@ -347,7 +347,7 @@ object AlonsoMoraPoolingAlgForRideHail {
val alonsoMora: AllocationManager.AlonsoMora =
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora
val waitingTimeInSec = alonsoMora.waitingTimeInSec
val travelTimeDelayAsFraction = alonsoMora.travelTimeDelayAsFraction
val travelTimeDelayAsFraction = alonsoMora.excessRideTimeAsFraction

veh.currentPassengerSchedule.foreach {
_.schedule.foreach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AsyncAlonsoMoraAlgForRideHail(
) {

private val solutionSpaceSizePerVehicle =
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.solutionSpaceSizePerVehicle
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.numRequestsPerVehicle

private val waitingTimeInSec =
beamServices.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.waitingTimeInSec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class VehicleCentricMatchingForRideHail(
skimmer: BeamSkimmer
) {
private val solutionSpaceSizePerVehicle =
services.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.solutionSpaceSizePerVehicle
services.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.numRequestsPerVehicle
private val waitingTimeInSec =
services.beamConfig.beam.agentsim.agents.rideHail.allocationManager.alonsoMora.waitingTimeInSec
private val searchRadius = waitingTimeInSec * BeamSkimmer.speedMeterPerSec(BeamMode.CAV)
Expand Down
131 changes: 131 additions & 0 deletions src/main/scala/beam/agentsim/infrastructure/taz/H3TAZ.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package beam.agentsim.infrastructure.taz

import beam.agentsim.infrastructure.taz.H3TAZ.{fillBox, HexIndex}
import beam.sim.config.BeamConfig
import beam.utils.matsim_conversion.ShapeUtils.QuadTreeBounds
import com.uber.h3core.util.GeoCoord
import com.vividsolutions.jts.geom.{Coordinate, Geometry, GeometryFactory}
import org.matsim.api.core.v01.network.Network
import org.matsim.api.core.v01.{Coord, Id}
import org.matsim.core.utils.geometry.geotools.MGC
import org.matsim.core.utils.geometry.transformations.GeotoolsTransformation
import org.matsim.core.utils.gis.{PolygonFeatureFactory, ShapeFileWriter}

import scala.collection.JavaConverters._
import scala.collection.mutable

case class H3TAZ(network: Network, tazTreeMap: TAZTreeMap, beamConfig: BeamConfig) {
private val transformToH3Proj =
new GeotoolsTransformation(beamConfig.matsim.modules.global.coordinateSystem, H3TAZ.H3Projection)

private val boundingBox: QuadTreeBounds = H3TAZ.quadTreeExtentFromShapeFile(
network.getNodes.values().asScala.map(n => transformToH3Proj.transform(n.getCoord))
)
private val resolution = beamConfig.beam.h3.resolution
private val lowerBoundResolution = beamConfig.beam.h3.lowerBoundResolution
private val tazToH3TAZMapping: mutable.HashMap[HexIndex, Id[TAZ]] = mutable.HashMap()
fillBox(boundingBox, resolution).foreach { hex =>
val hexCentroid = H3TAZ.hexToCoord(hex)
val hexCentroidBis =
new GeotoolsTransformation(H3TAZ.H3Projection, beamConfig.matsim.modules.global.coordinateSystem)
.transform(hexCentroid)
val tazId = tazTreeMap.getTAZ(hexCentroidBis.getX, hexCentroidBis.getY).tazId
tazToH3TAZMapping.put(hex, tazId)
}

def getAll: Iterable[HexIndex] = {
tazToH3TAZMapping.keys
}

def getHRHex(x: Double, y: Double): HexIndex = {
val coord = H3TAZ.toGeoCoord(transformToH3Proj.transform(new Coord(x, y)))
H3TAZ.H3.geoToH3Address(coord.lat, coord.lng, resolution)
}

def getHRHex(tazId: Id[TAZ]): Iterable[HexIndex] = {
tazToH3TAZMapping.filter(_._2 == tazId).keys
}

def getTAZ(hex: HexIndex): Id[TAZ] = {
tazToH3TAZMapping.getOrElse(hex, TAZTreeMap.emptyTAZId)
}

}

object H3TAZ {
type HexIndex = String
private val H3 = com.uber.h3core.H3Core.newInstance
val H3Projection = "EPSG:4326"

def writeToShp(filename: String, h3Tazs: Iterable[(HexIndex, String, Double)]): Unit = {
val gf = new GeometryFactory()
val hexagons = h3Tazs.map {
case (h, taz, v) =>
val boundary = H3.h3ToGeoBoundary(h).asScala
(h, taz, v, gf.createPolygon(boundary.map(toJtsCoordinate).toArray :+ toJtsCoordinate(boundary.head)))
}
val pf: PolygonFeatureFactory = new PolygonFeatureFactory.Builder()
.setCrs(MGC.getCRS("EPSG:4326"))
.setName("nodes")
.addAttribute("ID", classOf[String])
.addAttribute("TAZ", classOf[String])
.addAttribute("VALUE", classOf[java.lang.Double])
.create()
val shpPolygons = hexagons.map {
case (hex, taz, value, hexagon) =>
pf.createPolygon(hexagon.getCoordinates, Array[Object](hex, taz, value.toString), null)
}
ShapeFileWriter.writeGeometries(shpPolygons.asJavaCollection, filename)
}

// private utilities
private def hexToCoord(hexAddress: String): Coord = {
val coordinate = toJtsCoordinate(H3.h3ToGeo(hexAddress))
new Coord(coordinate.x, coordinate.y)
}
private def toJtsCoordinate(in: GeoCoord): com.vividsolutions.jts.geom.Coordinate = {
new com.vividsolutions.jts.geom.Coordinate(in.lng, in.lat)
}
private def toGeoCoord(in: Coord): GeoCoord = {
new GeoCoord(in.getY, in.getX)
}

private def quadTreeExtentFromShapeFile(coords: Iterable[Coord]): QuadTreeBounds = {
var minX: Double = Double.MaxValue
var maxX: Double = Double.MinValue
var minY: Double = Double.MaxValue
var maxY: Double = Double.MinValue
for (c <- coords) {
minX = Math.min(minX, c.getX)
minY = Math.min(minY, c.getY)
maxX = Math.max(maxX, c.getX)
maxY = Math.max(maxY, c.getY)
}
val gf = new GeometryFactory()
val box = gf
.createPolygon(
Array(
new Coordinate(minX, minY),
new Coordinate(minX, maxY),
new Coordinate(maxX, maxY),
new Coordinate(maxX, minY),
new Coordinate(minX, minY)
)
)
.asInstanceOf[Geometry]
.getEnvelopeInternal
QuadTreeBounds(box.getMinX - 0.01, box.getMinY - 0.01, box.getMaxX + 0.01, box.getMaxY + 0.01)
}

private def fillBox(box: QuadTreeBounds, resolution: Int): Iterable[String] = {
val points = List(
new GeoCoord(box.miny, box.minx),
new GeoCoord(box.maxy, box.minx),
new GeoCoord(box.maxy, box.maxx),
new GeoCoord(box.miny, box.maxx)
).asJava
val holes = List.empty[java.util.List[GeoCoord]].asJava
H3.polyfillAddress(points, holes, resolution).asScala
}

}
Loading