use the shortcut-path as the ITA for the optimization, but use the full path as the ITA itself
This commit is contained in:
@@ -24,55 +24,35 @@ class Ant:
|
|||||||
self.SequenceDelay = timedelta(seconds = 0)
|
self.SequenceDelay = timedelta(seconds = 0)
|
||||||
self.Sequence = None
|
self.Sequence = None
|
||||||
|
|
||||||
def qualifyDelay(delay, node, runway):
|
# Implements function (5)
|
||||||
if 0.0 > delay.total_seconds():
|
def heuristicInformation(self, current : int):
|
||||||
delay = timedelta(seconds = 0)
|
_, eta, _ = self.RunwayManager.selectArrivalRunway(self.Nodes[current], self.Configuration.EarliestArrivalTime)
|
||||||
|
inboundDelay = eta - self.Nodes[current].Inbound.InitialArrivalTime
|
||||||
# calculate the heuristic scaling to punish increased delays for single inbounds
|
|
||||||
scaledDelay = delay.total_seconds() / node.ArrivalCandidates[runway.Name].MaximumTimeToLose.total_seconds()
|
|
||||||
return max(1.0 / (99.0 * (scaledDelay ** 2) + 1), 0.01)
|
|
||||||
|
|
||||||
# Implements function (5), but adapted to the following logic:
|
|
||||||
# An adaption of the heuristic function is used:
|
|
||||||
# - Calculates the unused runway time (time between two consecutive landings)
|
|
||||||
# - Calculates a ratio between the inbound delay and the unused runway time
|
|
||||||
# - Weight the overall ratio based on maximum time to lose to punish high time to lose rates while other flights are gaining time
|
|
||||||
def heuristicInformation(self, preceeding : int, current : int):
|
|
||||||
rwy, eta, unusedRunwayTime = self.RunwayManager.selectArrivalRunway(self.Nodes[current], True, self.Configuration.EarliestArrivalTime)
|
|
||||||
inboundDelay = eta - self.Nodes[current].ArrivalCandidates[rwy.Name].InitialArrivalTime
|
|
||||||
if 0.0 > inboundDelay.total_seconds():
|
|
||||||
inboundDelay = timedelta(seconds = 0)
|
|
||||||
|
|
||||||
# calculate the fraction with a mix of the unused runway time and the delay of single aircrafts
|
# calculate the fraction with a mix of the unused runway time and the delay of single aircrafts
|
||||||
fraction = self.Configuration.RunwayOccupasionRatio * unusedRunwayTime.total_seconds()
|
heuristic = inboundDelay.total_seconds() / 60.0
|
||||||
fraction += (1.0 - self.Configuration.RunwayOccupasionRatio) * inboundDelay.total_seconds()
|
heuristic = (1.0 / (heuristic or 1)) ** self.Configuration.Beta
|
||||||
fraction += self.SequenceDelay.total_seconds()
|
return heuristic
|
||||||
fraction /= 60.0
|
|
||||||
|
|
||||||
# calculate the heuristic scaling to punish increased delays for single inbounds
|
|
||||||
weight = Ant.qualifyDelay(inboundDelay, self.Nodes[current], rwy)
|
|
||||||
|
|
||||||
return weight * self.PheromoneMatrix[preceeding, current] * ((1.0 / (fraction or 1)) ** self.Configuration.Beta)
|
|
||||||
|
|
||||||
# Implements functions (3), (6)
|
# Implements functions (3), (6)
|
||||||
def selectNextLandingIndex(self, preceedingIndex : int):
|
def selectNextLandingIndex(self):
|
||||||
q = float(random.randint(0, 100)) / 100
|
q = float(random.randint(0, 100)) / 100
|
||||||
weights = []
|
weights = []
|
||||||
|
|
||||||
if q <= self.Configuration.PseudoRandomSelectionRate:
|
if q <= self.Configuration.PseudoRandomSelectionRate:
|
||||||
for i in range(0, len(self.InboundSelected)):
|
for i in range(0, len(self.InboundSelected)):
|
||||||
if False == self.InboundSelected[i]:
|
if False == self.InboundSelected[i]:
|
||||||
weights.append(self.heuristicInformation(preceedingIndex, i))
|
weights.append(self.heuristicInformation(i))
|
||||||
else:
|
else:
|
||||||
# roulette selection strategy
|
# roulette selection strategy
|
||||||
pheromoneScale = 0.0
|
pheromoneScale = 0.0
|
||||||
for i in range(0, len(self.InboundSelected)):
|
for i in range(0, len(self.InboundSelected)):
|
||||||
if False == self.InboundSelected[i]:
|
if False == self.InboundSelected[i]:
|
||||||
pheromoneScale += self.heuristicInformation(preceedingIndex, i)
|
pheromoneScale += self.heuristicInformation(i)
|
||||||
|
|
||||||
for i in range(0, len(self.InboundSelected)):
|
for i in range(0, len(self.InboundSelected)):
|
||||||
if False == self.InboundSelected[i]:
|
if False == self.InboundSelected[i]:
|
||||||
weights.append(self.heuristicInformation(preceedingIndex, i) / (pheromoneScale or 1))
|
weights.append(self.heuristicInformation(i) / (pheromoneScale or 1))
|
||||||
|
|
||||||
total = sum(weights)
|
total = sum(weights)
|
||||||
cumdist = list(itertools.accumulate(weights)) + [total]
|
cumdist = list(itertools.accumulate(weights)) + [total]
|
||||||
@@ -89,7 +69,7 @@ class Ant:
|
|||||||
|
|
||||||
def associateInbound(self, node : Node, earliestArrivalTime : datetime):
|
def associateInbound(self, node : Node, earliestArrivalTime : datetime):
|
||||||
# prepare the statistics
|
# prepare the statistics
|
||||||
rwy, eta, _ = self.RunwayManager.selectArrivalRunway(node, True, self.Configuration.EarliestArrivalTime)
|
rwy, eta, _ = self.RunwayManager.selectArrivalRunway(node, self.Configuration.EarliestArrivalTime)
|
||||||
eta = max(earliestArrivalTime, eta)
|
eta = max(earliestArrivalTime, eta)
|
||||||
|
|
||||||
node.Inbound.PlannedRunway = rwy
|
node.Inbound.PlannedRunway = rwy
|
||||||
@@ -110,20 +90,18 @@ class Ant:
|
|||||||
|
|
||||||
# select the first inbound
|
# select the first inbound
|
||||||
self.InboundSelected[first] = True
|
self.InboundSelected[first] = True
|
||||||
delay, rwy = self.associateInbound(self.Nodes[first], self.Configuration.EarliestArrivalTime)
|
delay, _ = self.associateInbound(self.Nodes[first], self.Configuration.EarliestArrivalTime)
|
||||||
self.InboundScore[0] = Ant.qualifyDelay(delay, self.Nodes[first], rwy)
|
|
||||||
self.Sequence.append(first)
|
self.Sequence.append(first)
|
||||||
self.SequenceDelay += delay
|
self.SequenceDelay += delay
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
index = self.selectNextLandingIndex(self.Sequence[-1])
|
index = self.selectNextLandingIndex()
|
||||||
if None == index:
|
if None == index:
|
||||||
break
|
break
|
||||||
|
|
||||||
self.InboundSelected[index] = True
|
self.InboundSelected[index] = True
|
||||||
delay, rwy = self.associateInbound(self.Nodes[index], self.Configuration.EarliestArrivalTime)
|
delay, _ = self.associateInbound(self.Nodes[index], self.Configuration.EarliestArrivalTime)
|
||||||
self.SequenceDelay += delay
|
self.SequenceDelay += delay
|
||||||
self.InboundScore[len(self.Sequence)] = Ant.qualifyDelay(delay, self.Nodes[index], rwy)
|
|
||||||
self.Sequence.append(index)
|
self.Sequence.append(index)
|
||||||
|
|
||||||
# update the local pheromone
|
# update the local pheromone
|
||||||
@@ -134,7 +112,4 @@ class Ant:
|
|||||||
# validate that nothing went wrong
|
# validate that nothing went wrong
|
||||||
if len(self.Sequence) != len(self.Nodes):
|
if len(self.Sequence) != len(self.Nodes):
|
||||||
self.SequenceDelay = None
|
self.SequenceDelay = None
|
||||||
self.SequenceScore = None
|
|
||||||
self.Sequence = None
|
self.Sequence = None
|
||||||
else:
|
|
||||||
self.SequenceScore = np.median(self.InboundScore)
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ from aman.types.Inbound import Inbound
|
|||||||
# This class implements the ant colony of the following paper:
|
# This class implements the ant colony of the following paper:
|
||||||
# https://sci-hub.mksa.top/10.1109/cec.2019.8790135
|
# https://sci-hub.mksa.top/10.1109/cec.2019.8790135
|
||||||
class Colony:
|
class Colony:
|
||||||
def associateInbound(rwyManager : RunwayManager, node : Node, earliestArrivalTime : datetime, useITA : bool):
|
def associateInbound(rwyManager : RunwayManager, node : Node, earliestArrivalTime : datetime):
|
||||||
rwy, eta, _ = rwyManager.selectArrivalRunway(node, useITA, earliestArrivalTime)
|
rwy, eta, _ = rwyManager.selectArrivalRunway(node, earliestArrivalTime)
|
||||||
eta = max(earliestArrivalTime, eta)
|
eta = max(earliestArrivalTime, eta)
|
||||||
|
|
||||||
node.Inbound.PlannedRunway = rwy
|
node.Inbound.PlannedRunway = rwy
|
||||||
@@ -34,7 +34,7 @@ class Colony:
|
|||||||
|
|
||||||
# assume that the nodes are sorted in FCFS order
|
# assume that the nodes are sorted in FCFS order
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
Colony.associateInbound(rwyManager, node, earliestArrivalTime, False)
|
Colony.associateInbound(rwyManager, node, earliestArrivalTime)
|
||||||
overallDelay += node.Inbound.PlannedArrivalTime - node.Inbound.InitialArrivalTime
|
overallDelay += node.Inbound.PlannedArrivalTime - node.Inbound.InitialArrivalTime
|
||||||
|
|
||||||
return overallDelay
|
return overallDelay
|
||||||
@@ -62,6 +62,17 @@ class Colony:
|
|||||||
self.Configuration.ThetaZero = 1.0 / (len(self.Nodes) * (delay.total_seconds() / 60.0))
|
self.Configuration.ThetaZero = 1.0 / (len(self.Nodes) * (delay.total_seconds() / 60.0))
|
||||||
self.PheromoneMatrix = np.ones(( len(self.Nodes), len(self.Nodes) ), dtype=float) * self.Configuration.ThetaZero
|
self.PheromoneMatrix = np.ones(( len(self.Nodes), len(self.Nodes) ), dtype=float) * self.Configuration.ThetaZero
|
||||||
|
|
||||||
|
def sequenceAndPredictInbound(self, rwyManager : RunwayManager, node : Node):
|
||||||
|
self.Result.append(node)
|
||||||
|
Colony.associateInbound(rwyManager, node, self.Configuration.EarliestArrivalTime)
|
||||||
|
|
||||||
|
reqTimeDelta = self.Result[-1].Inbound.InitialArrivalTime - self.Result[-1].Inbound.PlannedArrivalTime
|
||||||
|
self.Result[-1].Inbound.PlannedArrivalRoute[0].PTA = self.Result[-1].Inbound.PlannedArrivalRoute[0].ETA - reqTimeDelta
|
||||||
|
for i in range(1, len(self.Result[-1].Inbound.PlannedArrivalRoute)):
|
||||||
|
prev = self.Result[-1].Inbound.PlannedArrivalRoute[i - 1]
|
||||||
|
current = self.Result[-1].Inbound.PlannedArrivalRoute[i]
|
||||||
|
current.PTA = prev.PTA + (current.ETA - prev.ETA)
|
||||||
|
|
||||||
def optimize(self):
|
def optimize(self):
|
||||||
# FCFS is the best solution
|
# FCFS is the best solution
|
||||||
if None != self.Result:
|
if None != self.Result:
|
||||||
@@ -82,23 +93,21 @@ class Colony:
|
|||||||
ant.findSolution(index)
|
ant.findSolution(index)
|
||||||
|
|
||||||
# fallback to check if findSolution was successful
|
# fallback to check if findSolution was successful
|
||||||
if None == ant.SequenceDelay or None == ant.Sequence or None == ant.SequenceScore:
|
if None == ant.SequenceDelay or None == ant.Sequence:
|
||||||
sys.stderr.write('Invalid ANT run detected!')
|
sys.stderr.write('Invalid ANT run detected!')
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
candidates.append(
|
candidates.append(
|
||||||
[
|
[
|
||||||
ant.SequenceDelay,
|
ant.SequenceDelay,
|
||||||
ant.Sequence,
|
ant.Sequence
|
||||||
ant.SequenceScore,
|
|
||||||
ant.SequenceDelay.total_seconds() / ant.SequenceScore
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# find the best solution in all candidates of this generation
|
# find the best solution in all candidates of this generation
|
||||||
bestCandidate = None
|
bestCandidate = None
|
||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
if None == bestCandidate or candidate[3] < bestCandidate[3]:
|
if None == bestCandidate or candidate[0] < bestCandidate[0]:
|
||||||
bestCandidate = candidate
|
bestCandidate = candidate
|
||||||
|
|
||||||
dTheta = 1.0 / ((candidate[0].total_seconds() / 60.0) or 1.0)
|
dTheta = 1.0 / ((candidate[0].total_seconds() / 60.0) or 1.0)
|
||||||
@@ -112,20 +121,19 @@ class Colony:
|
|||||||
bestSequence = bestCandidate
|
bestSequence = bestCandidate
|
||||||
|
|
||||||
# create the final sequence
|
# create the final sequence
|
||||||
if None != bestSequence:
|
self.Result = []
|
||||||
|
rwyManager = RunwayManager(self.Configuration)
|
||||||
|
|
||||||
|
# use the optimized sequence
|
||||||
|
if None != bestSequence and self.FcfsDelay >= bestSequence[0]:
|
||||||
# create the resulting sequence
|
# create the resulting sequence
|
||||||
self.ResultDelay = bestSequence[0]
|
self.ResultDelay = bestSequence[0]
|
||||||
self.Result = []
|
|
||||||
|
|
||||||
# finalize the sequence
|
# finalize the sequence
|
||||||
rwyManager = RunwayManager(self.Configuration)
|
for idx in bestSequence[1]:
|
||||||
for i in range(0, len(bestSequence[1])):
|
self.sequenceAndPredictInbound(rwyManager, self.Nodes[idx])
|
||||||
self.Result.append(self.Nodes[bestSequence[1][i]])
|
# use the FCFS sequence
|
||||||
Colony.associateInbound(rwyManager, self.Nodes[bestSequence[1][i]], self.Configuration.EarliestArrivalTime, True)
|
else:
|
||||||
|
self.ResultDelay = self.FcfsDelay
|
||||||
reqTimeDelta = self.Result[-1].Inbound.InitialArrivalTime - self.Result[-1].Inbound.PlannedArrivalTime
|
for node in self.Nodes:
|
||||||
self.Result[-1].Inbound.PlannedArrivalRoute[0].PTA = self.Result[-1].Inbound.PlannedArrivalRoute[0].ETA - reqTimeDelta
|
self.sequenceAndPredictInbound(node)
|
||||||
for i in range(1, len(self.Result[-1].Inbound.PlannedArrivalRoute)):
|
|
||||||
prev = self.Result[-1].Inbound.PlannedArrivalRoute[i - 1]
|
|
||||||
current = self.Result[-1].Inbound.PlannedArrivalRoute[i]
|
|
||||||
current.PTA = prev.PTA + (current.ETA - prev.ETA)
|
|
||||||
|
|||||||
@@ -193,11 +193,6 @@ class Node:
|
|||||||
if None != star:
|
if None != star:
|
||||||
flightTime, trackmiles, arrivalRoute, flightTimeOnStar = self.arrivalEstimation(identifier.Runway, star, weatherModel)
|
flightTime, trackmiles, arrivalRoute, flightTimeOnStar = self.arrivalEstimation(identifier.Runway, star, weatherModel)
|
||||||
|
|
||||||
# calculate average speed gain
|
|
||||||
avgSpeed = trackmiles / (flightTime.total_seconds() / 3600.0)
|
|
||||||
avgSpeedDecrease = avgSpeed * 0.80
|
|
||||||
decreasedSpeedFlighttime = (trackmiles / avgSpeedDecrease) * 3600.0 # given in seconds
|
|
||||||
|
|
||||||
# use the the distance to the IAF for optimizations
|
# use the the distance to the IAF for optimizations
|
||||||
timeUntilIAF = flightTime - flightTimeOnStar
|
timeUntilIAF = flightTime - flightTimeOnStar
|
||||||
if 0.0 > timeUntilIAF.total_seconds():
|
if 0.0 > timeUntilIAF.total_seconds():
|
||||||
@@ -213,13 +208,10 @@ class Node:
|
|||||||
ttg = timedelta(seconds = timeUntilIAF.total_seconds() * ttgRatio)
|
ttg = timedelta(seconds = timeUntilIAF.total_seconds() * ttgRatio)
|
||||||
if (ttg.total_seconds() > ttgMax):
|
if (ttg.total_seconds() > ttgMax):
|
||||||
ttg = timedelta(seconds = ttgMax)
|
ttg = timedelta(seconds = ttgMax)
|
||||||
ttl = timedelta(seconds = decreasedSpeedFlighttime - flightTime.total_seconds())
|
|
||||||
ita = self.Inbound.ReportTime + flightTime
|
ita = self.Inbound.ReportTime + flightTime
|
||||||
earliest = ita - ttg
|
earliest = ita - ttg
|
||||||
latest = ita + ttl
|
|
||||||
|
|
||||||
self.ArrivalCandidates[identifier.Runway.Name] = ArrivalData(ttg = ttg, star = star, ita = ita, earliest = earliest,
|
self.ArrivalCandidates[identifier.Runway.Name] = ArrivalData(star = star, ita = earliest, route = arrivalRoute,
|
||||||
ttl = ttl, latest = latest, route = arrivalRoute,
|
|
||||||
trackmiles = trackmiles)
|
trackmiles = trackmiles)
|
||||||
|
|
||||||
ita = self.ArrivalCandidates[identifier.Runway.Name].InitialArrivalTime
|
ita = self.ArrivalCandidates[identifier.Runway.Name].InitialArrivalTime
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class RunwayManager:
|
|||||||
if not runway.Runway.Name in self.RunwayInbounds:
|
if not runway.Runway.Name in self.RunwayInbounds:
|
||||||
self.RunwayInbounds[runway.Runway.Name] = None
|
self.RunwayInbounds[runway.Runway.Name] = None
|
||||||
|
|
||||||
def calculateEarliestArrivalTime(self, runway : str, node : Node, useETA : bool, earliestArrivalTime : datetime):
|
def calculateEarliestArrivalTime(self, runway : str, node : Node, earliestArrivalTime : datetime):
|
||||||
constrainedETA = None
|
constrainedETA = None
|
||||||
|
|
||||||
if None != self.RunwayInbounds[runway]:
|
if None != self.RunwayInbounds[runway]:
|
||||||
@@ -42,40 +42,29 @@ class RunwayManager:
|
|||||||
if None == constrainedETA or candidate > constrainedETA:
|
if None == constrainedETA or candidate > constrainedETA:
|
||||||
constrainedETA = candidate
|
constrainedETA = candidate
|
||||||
|
|
||||||
# get the arrival time on the runway of the inbound
|
|
||||||
if True == useETA:
|
|
||||||
arrivalTime = node.ArrivalCandidates[runway].EarliestArrivalTime
|
|
||||||
else:
|
|
||||||
arrivalTime = node.ArrivalCandidates[runway].InitialArrivalTime
|
|
||||||
|
|
||||||
if None == constrainedETA:
|
if None == constrainedETA:
|
||||||
eta = max(arrivalTime, earliestArrivalTime)
|
eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, earliestArrivalTime)
|
||||||
else:
|
else:
|
||||||
eta = max(arrivalTime, max(constrainedETA, earliestArrivalTime))
|
eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, max(constrainedETA, earliestArrivalTime))
|
||||||
|
|
||||||
return eta, eta - arrivalTime
|
return eta, eta - node.ArrivalCandidates[runway].InitialArrivalTime
|
||||||
|
|
||||||
def selectShallShouldMayArrivalRunway(self, node : Node, runways, useETA : bool, earliestArrivalTime : datetime):
|
def selectShallShouldMayArrivalRunway(self, node : Node, runways, earliestArrivalTime : datetime):
|
||||||
candidate = None
|
candidate = None
|
||||||
delay = None
|
delay = None
|
||||||
|
|
||||||
for runway in runways:
|
for runway in runways:
|
||||||
if True == useETA:
|
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
|
||||||
reference = node.ArrivalCandidates[runway.Runway.Name].EarliestArrivalTime
|
|
||||||
else:
|
|
||||||
reference = node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
|
|
||||||
|
|
||||||
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, useETA, earliestArrivalTime)
|
|
||||||
if None == delay:
|
if None == delay:
|
||||||
delay = eta - reference
|
delay = eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
|
||||||
candidate = runway
|
candidate = runway
|
||||||
elif delay > (eta - reference):
|
elif delay > (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime):
|
||||||
delay = eta- reference
|
delay = eta- node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
|
||||||
candidate = runway
|
candidate = runway
|
||||||
|
|
||||||
return candidate
|
return candidate
|
||||||
|
|
||||||
def executeShallShouldMayAssignment(self, node : Node, useETA : bool, earliestArrivalTime : datetime):
|
def executeShallShouldMayAssignment(self, node : Node, earliestArrivalTime : datetime):
|
||||||
shallRunways = []
|
shallRunways = []
|
||||||
shouldRunways = []
|
shouldRunways = []
|
||||||
mayRunways = []
|
mayRunways = []
|
||||||
@@ -97,46 +86,41 @@ class RunwayManager:
|
|||||||
if node.Inbound.Report.plannedGate in runway.ShouldAssignments[RunwayAssignmentType.GateAssignment]:
|
if node.Inbound.Report.plannedGate in runway.ShouldAssignments[RunwayAssignmentType.GateAssignment]:
|
||||||
shouldRunways.append(runway)
|
shouldRunways.append(runway)
|
||||||
|
|
||||||
if True == useETA:
|
|
||||||
reference = node.ArrivalCandidates[runway.Runway.Name].EarliestArrivalTime
|
|
||||||
else:
|
|
||||||
reference = node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
|
|
||||||
|
|
||||||
# test the may assignments
|
# test the may assignments
|
||||||
if RunwayAssignmentType.AircraftType in runway.MayAssignments:
|
if RunwayAssignmentType.AircraftType in runway.MayAssignments:
|
||||||
if node.Inbound.Report.aircraft.type in runway.MayAssignments[RunwayAssignmentType.AircraftType]:
|
if node.Inbound.Report.aircraft.type in runway.MayAssignments[RunwayAssignmentType.AircraftType]:
|
||||||
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, useETA, earliestArrivalTime)
|
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
|
||||||
if (eta - reference) <= self.Configuration.AirportConfiguration.MaxDelayMay:
|
if (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime) <= self.Configuration.AirportConfiguration.MaxDelayMay:
|
||||||
mayRunways.append(runway)
|
mayRunways.append(runway)
|
||||||
if RunwayAssignmentType.GateAssignment in runway.MayAssignments:
|
if RunwayAssignmentType.GateAssignment in runway.MayAssignments:
|
||||||
if node.Inbound.Report.plannedGate in runway.MayAssignments[RunwayAssignmentType.GateAssignment]:
|
if node.Inbound.Report.plannedGate in runway.MayAssignments[RunwayAssignmentType.GateAssignment]:
|
||||||
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, useETA, earliestArrivalTime)
|
eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
|
||||||
if (eta - reference) <= self.Configuration.AirportConfiguration.MaxDelayMay:
|
if (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime) <= self.Configuration.AirportConfiguration.MaxDelayMay:
|
||||||
mayRunways.append(runway)
|
mayRunways.append(runway)
|
||||||
|
|
||||||
runway = self.selectShallShouldMayArrivalRunway(node, shallRunways, useETA, earliestArrivalTime)
|
runway = self.selectShallShouldMayArrivalRunway(node, shallRunways, earliestArrivalTime)
|
||||||
if None != runway:
|
if None != runway:
|
||||||
return [ runway ]
|
return [ runway ]
|
||||||
runway = self.selectShallShouldMayArrivalRunway(node, shouldRunways, useETA, earliestArrivalTime)
|
runway = self.selectShallShouldMayArrivalRunway(node, shouldRunways, earliestArrivalTime)
|
||||||
if None != runway:
|
if None != runway:
|
||||||
return [ runway ]
|
return [ runway ]
|
||||||
runway = self.selectShallShouldMayArrivalRunway(node, mayRunways, useETA, earliestArrivalTime)
|
runway = self.selectShallShouldMayArrivalRunway(node, mayRunways, earliestArrivalTime)
|
||||||
if None != runway:
|
if None != runway:
|
||||||
return [ runway ]
|
return [ runway ]
|
||||||
|
|
||||||
return self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
return self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
||||||
|
|
||||||
def selectArrivalRunway(self, node : Node, useETA : bool, earliestArrivalTime : datetime):
|
def selectArrivalRunway(self, node : Node, earliestArrivalTime : datetime):
|
||||||
availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
||||||
|
|
||||||
if True == self.Configuration.RunwayConstraints.UseShallShouldMay:
|
if True == self.Configuration.RunwayConstraints.UseShallShouldMay:
|
||||||
availableRunways = self.executeShallShouldMayAssignment(node, useETA, earliestArrivalTime)
|
availableRunways = self.executeShallShouldMayAssignment(node, earliestArrivalTime)
|
||||||
else:
|
else:
|
||||||
availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
|
||||||
|
|
||||||
if 0 == len(availableRunways):
|
if 0 == len(availableRunways):
|
||||||
runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
|
runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
|
||||||
return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, node, useETA, earliestArrivalTime)
|
return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
|
||||||
|
|
||||||
# start with the beginning
|
# start with the beginning
|
||||||
selectedRunway = None
|
selectedRunway = None
|
||||||
@@ -145,7 +129,7 @@ class RunwayManager:
|
|||||||
|
|
||||||
# get the runway with the earliest ETA
|
# get the runway with the earliest ETA
|
||||||
for runway in availableRunways:
|
for runway in availableRunways:
|
||||||
candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, useETA, earliestArrivalTime)
|
candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
|
||||||
if None == eta or eta > candidate:
|
if None == eta or eta > candidate:
|
||||||
selectedRunway = runway.Runway
|
selectedRunway = runway.Runway
|
||||||
lostTime = delta
|
lostTime = delta
|
||||||
|
|||||||
@@ -7,30 +7,12 @@ from aman.types.ArrivalRoute import ArrivalRoute
|
|||||||
class ArrivalData:
|
class ArrivalData:
|
||||||
def __init__(self, **kargs):
|
def __init__(self, **kargs):
|
||||||
self.Star = None
|
self.Star = None
|
||||||
self.MaximumTimeToGain = None
|
|
||||||
self.MaximumTimeToLose = None
|
|
||||||
self.InitialArrivalTime = None
|
self.InitialArrivalTime = None
|
||||||
self.EarliestArrivalTime = None
|
|
||||||
self.LatestArrivalTime = None
|
|
||||||
self.ArrivalRoute = None
|
self.ArrivalRoute = None
|
||||||
self.Trackmiles = None
|
self.Trackmiles = None
|
||||||
|
|
||||||
for key, value in kargs.items():
|
for key, value in kargs.items():
|
||||||
if 'ttg' == key:
|
if 'star' == key:
|
||||||
if True == isinstance(value, timedelta):
|
|
||||||
self.MaximumTimeToGain = value
|
|
||||||
elif True == isinstance(value, (int, float)):
|
|
||||||
self.MaximumTimeToGain = timedelta(seconds = float(value))
|
|
||||||
else:
|
|
||||||
raise Exception('Invalid type for ttg')
|
|
||||||
elif 'ttl' == key:
|
|
||||||
if True == isinstance(value, timedelta):
|
|
||||||
self.MaximumTimeToLose = value
|
|
||||||
elif True == isinstance(value, (int, float)):
|
|
||||||
self.MaximumTimeToLose = timedelta(seconds = float(value))
|
|
||||||
else:
|
|
||||||
raise Exception('Invalid type for ttl')
|
|
||||||
elif 'star' == key:
|
|
||||||
if True == isinstance(value, ArrivalRoute):
|
if True == isinstance(value, ArrivalRoute):
|
||||||
self.Star = value
|
self.Star = value
|
||||||
else:
|
else:
|
||||||
@@ -40,16 +22,6 @@ class ArrivalData:
|
|||||||
self.InitialArrivalTime = value
|
self.InitialArrivalTime = value
|
||||||
else:
|
else:
|
||||||
raise Exception('Invalid type for ita')
|
raise Exception('Invalid type for ita')
|
||||||
elif 'earliest' == key:
|
|
||||||
if True == isinstance(value, datetime):
|
|
||||||
self.EarliestArrivalTime = value
|
|
||||||
else:
|
|
||||||
raise Exception('Invalid type for earliest')
|
|
||||||
elif 'latest' == key:
|
|
||||||
if True == isinstance(value, datetime):
|
|
||||||
self.LatestArrivalTime = value
|
|
||||||
else:
|
|
||||||
raise Exception('Invalid type for latest')
|
|
||||||
elif 'route' == key:
|
elif 'route' == key:
|
||||||
self.ArrivalRoute = value
|
self.ArrivalRoute = value
|
||||||
elif 'trackmiles' == key:
|
elif 'trackmiles' == key:
|
||||||
|
|||||||
Reference in New Issue
Block a user