From 48208032e2091954dc86eef21a47495dff88ecf9 Mon Sep 17 00:00:00 2001 From: Eloi Charpentier Date: Wed, 18 Dec 2024 16:28:24 +0100 Subject: [PATCH] core: stdcm: limit the loop where we look for possible delays We would keep looking for different "openings" even very far in the future. This limits both conflict detection calls and the early steps of edge building. Signed-off-by: Eloi Charpentier --- .../fr/sncf/osrd/stdcm/graph/DelayManager.kt | 19 ++++++++++++++++++- .../sncf/osrd/stdcm/graph/STDCMEdgeBuilder.kt | 2 +- .../sncf/osrd/stdcm/graph/STDCMPathfinding.kt | 3 ++- .../fr/sncf/osrd/stdcm/graph/TimeData.kt | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/DelayManager.kt b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/DelayManager.kt index e72490f4d61..600a789e9a5 100644 --- a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/DelayManager.kt +++ b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/DelayManager.kt @@ -9,6 +9,8 @@ import fr.sncf.osrd.utils.units.Distance.Companion.fromMeters import fr.sncf.osrd.utils.units.Offset import fr.sncf.osrd.utils.units.meters import java.util.* +import kotlin.math.max +import kotlin.math.min /** * This class contains all the methods used to handle delays (how much we can add, how much we need @@ -29,14 +31,17 @@ internal constructor( */ fun minimumDelaysPerOpening( infraExplorerWithNewEnvelope: InfraExplorerWithEnvelope, - startTime: Double, + timeData: TimeData, envelope: Envelope, startOffset: Offset, ): NavigableSet { + val startTime = timeData.earliestReachableTime + val maximumDelay = computeMaximumDelay(timeData) val res = TreeSet() val endOffset = startOffset + fromMeters(envelope.endPos) var time = startTime while (java.lang.Double.isFinite(time)) { + if (time - startTime > maximumDelay) break val availability = getLastBlockAvailability( infraExplorerWithNewEnvelope, @@ -58,6 +63,18 @@ internal constructor( return res } + /** + * Compute how much delay we may add here. Prevents the generation of edges very far in the + * future that would necessarily be discarded. + */ + private fun computeMaximumDelay(data: TimeData): Double { + val maxExtraRunTime = maxRunTime - data.totalRunningTime + val maxDelayForMaxRunTime = data.maxDepartureDelayingWithoutConflict + maxExtraRunTime + val maxDelayWithLocalConflict = + data.timeOfNextConflictAtLocation - data.earliestReachableTime + return max(0.0, min(maxDelayForMaxRunTime, maxDelayWithLocalConflict)) + } + /** Returns the start time of the next occupancy for the block */ fun findNextOccupancy( infraExplorer: InfraExplorerWithEnvelope, diff --git a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMEdgeBuilder.kt b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMEdgeBuilder.kt index 4119df66c0d..9075342b437 100644 --- a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMEdgeBuilder.kt +++ b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMEdgeBuilder.kt @@ -132,7 +132,7 @@ internal constructor( private fun getDelaysPerOpening(): Set { return graph.delayManager.minimumDelaysPerOpening( getExplorerWithNewEnvelope()!!, - prevNode.timeData.earliestReachableTime, + prevNode.timeData, envelope!!, startOffset, ) diff --git a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMPathfinding.kt b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMPathfinding.kt index 7402610f4f3..c3bfd93143b 100644 --- a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMPathfinding.kt +++ b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/STDCMPathfinding.kt @@ -25,6 +25,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan import java.time.Duration import java.time.Instant import java.util.* +import kotlin.Double.Companion.POSITIVE_INFINITY import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -272,7 +273,7 @@ class STDCMPathfinding( earliestReachableTime = startTime, maxDepartureDelayingWithoutConflict = maxDepartureDelay, departureTime = startTime, - timeOfNextConflictAtLocation = 0.0, + timeOfNextConflictAtLocation = POSITIVE_INFINITY, totalRunningTime = 0.0, stopTimeData = listOf(), maxFirstDepartureDelaying = maxDepartureDelay, diff --git a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/TimeData.kt b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/TimeData.kt index 011186d68d4..f033df64176 100644 --- a/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/TimeData.kt +++ b/core/src/main/kotlin/fr/sncf/osrd/stdcm/graph/TimeData.kt @@ -89,6 +89,9 @@ data class TimeData( var maxDepartureDelayingWithoutConflict = maxDepartureDelayingWithoutConflict val nextEarliestReachableTime = earliestReachableTime + extraTravelTime + (extraStopTime ?: 0.0) + var timeOfNextConflict = timeOfNextConflictAtLocation + if (maxAdditionalStopTime != null) + timeOfNextConflict = nextEarliestReachableTime + maxAdditionalStopTime if (extraStopTime != null) { val stopDataCopy = newStopData.toMutableList() stopDataCopy.add( @@ -108,6 +111,7 @@ data class TimeData( maxDepartureDelayingWithoutConflict = maxDepartureDelayingWithoutConflict, maxFirstDepartureDelaying = min(maxFirstDepartureDelaying, (maxAdditionalStopTime ?: POSITIVE_INFINITY)), + timeOfNextConflictAtLocation = timeOfNextConflict, ) }