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.Sequence = None
|
||||
|
||||
def qualifyDelay(delay, node, runway):
|
||||
if 0.0 > delay.total_seconds():
|
||||
delay = timedelta(seconds = 0)
|
||||
|
||||
# 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)
|
||||
# Implements function (5)
|
||||
def heuristicInformation(self, current : int):
|
||||
_, eta, _ = self.RunwayManager.selectArrivalRunway(self.Nodes[current], self.Configuration.EarliestArrivalTime)
|
||||
inboundDelay = eta - self.Nodes[current].Inbound.InitialArrivalTime
|
||||
|
||||
# calculate the fraction with a mix of the unused runway time and the delay of single aircrafts
|
||||
fraction = self.Configuration.RunwayOccupasionRatio * unusedRunwayTime.total_seconds()
|
||||
fraction += (1.0 - self.Configuration.RunwayOccupasionRatio) * inboundDelay.total_seconds()
|
||||
fraction += self.SequenceDelay.total_seconds()
|
||||
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)
|
||||
heuristic = inboundDelay.total_seconds() / 60.0
|
||||
heuristic = (1.0 / (heuristic or 1)) ** self.Configuration.Beta
|
||||
return heuristic
|
||||
|
||||
# Implements functions (3), (6)
|
||||
def selectNextLandingIndex(self, preceedingIndex : int):
|
||||
def selectNextLandingIndex(self):
|
||||
q = float(random.randint(0, 100)) / 100
|
||||
weights = []
|
||||
|
||||
if q <= self.Configuration.PseudoRandomSelectionRate:
|
||||
for i in range(0, len(self.InboundSelected)):
|
||||
if False == self.InboundSelected[i]:
|
||||
weights.append(self.heuristicInformation(preceedingIndex, i))
|
||||
weights.append(self.heuristicInformation(i))
|
||||
else:
|
||||
# roulette selection strategy
|
||||
pheromoneScale = 0.0
|
||||
for i in range(0, len(self.InboundSelected)):
|
||||
if False == self.InboundSelected[i]:
|
||||
pheromoneScale += self.heuristicInformation(preceedingIndex, i)
|
||||
pheromoneScale += self.heuristicInformation(i)
|
||||
|
||||
for i in range(0, len(self.InboundSelected)):
|
||||
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)
|
||||
cumdist = list(itertools.accumulate(weights)) + [total]
|
||||
@@ -89,7 +69,7 @@ class Ant:
|
||||
|
||||
def associateInbound(self, node : Node, earliestArrivalTime : datetime):
|
||||
# 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)
|
||||
|
||||
node.Inbound.PlannedRunway = rwy
|
||||
@@ -110,20 +90,18 @@ class Ant:
|
||||
|
||||
# select the first inbound
|
||||
self.InboundSelected[first] = True
|
||||
delay, rwy = self.associateInbound(self.Nodes[first], self.Configuration.EarliestArrivalTime)
|
||||
self.InboundScore[0] = Ant.qualifyDelay(delay, self.Nodes[first], rwy)
|
||||
delay, _ = self.associateInbound(self.Nodes[first], self.Configuration.EarliestArrivalTime)
|
||||
self.Sequence.append(first)
|
||||
self.SequenceDelay += delay
|
||||
|
||||
while 1:
|
||||
index = self.selectNextLandingIndex(self.Sequence[-1])
|
||||
index = self.selectNextLandingIndex()
|
||||
if None == index:
|
||||
break
|
||||
|
||||
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.InboundScore[len(self.Sequence)] = Ant.qualifyDelay(delay, self.Nodes[index], rwy)
|
||||
self.Sequence.append(index)
|
||||
|
||||
# update the local pheromone
|
||||
@@ -134,7 +112,4 @@ class Ant:
|
||||
# validate that nothing went wrong
|
||||
if len(self.Sequence) != len(self.Nodes):
|
||||
self.SequenceDelay = None
|
||||
self.SequenceScore = None
|
||||
self.Sequence = None
|
||||
else:
|
||||
self.SequenceScore = np.median(self.InboundScore)
|
||||
|
||||
Reference in New Issue
Block a user