""" Tests the assignment algorithm. Assignment algorithm: find all flights that arrive at the virtual hub within a certain time window of each other and group them by maximizing the available slack. """ from lib.intervals import Interval, group if __name__ == "__main__": print group( [ Interval("G", 0, 2), Interval("B", 2, 4), Interval("C", 1, 3), Interval("D", 3, 5), Interval("A", 1, 3), Interval("E", 4, 6), Interval("F", 2, 4), ] )
def allocate(self, aircraft): p('debug', 'Starting formation allocation for %s' % aircraft) # Do not perform allocation if no hub exists in the flight route. if len(aircraft.route.segments) == 0: return self.formations = [] intervals = [] candidates = self.aircraft_queue hub = aircraft.route.waypoints[0] # This is bad. We don't want to filter anything. # @todo: pre-process at a higher level. # Only consider other aircraft flying to the same hub candidates = filter(lambda a: a.route.waypoints[0] is hub, candidates) p('debug', 'Full candidate set: %s' % candidates) # Only consider aircraft having a maximum heading difference between # the hub and their destination segment = Segment(aircraft.hub, aircraft.destination) leader_heading = segment.get_initial_bearing() def heading_filter(buddy): segment = Segment(buddy.hub, buddy.destination) buddy_heading = segment.get_initial_bearing() phi_obs = abs(leader_heading - buddy_heading) p( 'debug', 'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)' ': %.2f degrees' % ( aircraft, leader_heading, buddy, buddy_heading, phi_obs ) ) return phi_obs <= (config.phi_max/2) candidates = filter(heading_filter, candidates) # Other interesting filters if 'same-airline' in config.restrictions: airline = aircraft.label[0:2] candidates = filter(lambda a: a.label[0:2] == airline, candidates) if 'same-aircraft-type' in config.restrictions: aircraft_type = aircraft.aircraft_type candidates = filter(lambda a: a.aircraft_type == aircraft_type, candidates) p('debug', 'Reduced candidate set: %s' % candidates) for candidate in candidates: # Quick and dirty: recalc position. Instead, pull eta from var. candidate.controller.update_position() tth = candidate.time_to_waypoint() # time to hub hub_eta = sim.time + tth # From the moment the aircraft enters the lock area, the slack # decreases linearly to zero upon hub arrival. if tth < config.lock_time: slack = tth * config.etah_slack / config.lock_time else: slack = config.etah_slack p('Time = %s, Hub (= %s) eta %s for candidate %s' %\ (sim.time, hub, hub_eta, candidate)) intervals.append(Interval( candidate, int(hub_eta) - slack, int(hub_eta) + slack )) for interval_group in group(intervals): formation = Formation() for interval in interval_group: formation.append(interval.obj) self.formations.append(formation)
""" Tests the assignment algorithm. Assignment algorithm: find all flights that arrive at the virtual hub within a certain time window of each other and group them by maximizing the available slack. """ from lib.intervals import Interval, group if __name__ == '__main__': print group([ Interval('G', 0, 2), Interval('B', 2, 4), Interval('C', 1, 3), Interval('D', 3, 5), Interval('A', 1, 3), Interval('E', 4, 6), Interval('F', 2, 4), ])
def allocate(self, aircraft): p('debug', 'Starting formation allocation for %s' % aircraft) # Do not perform allocation if no hub exists in the flight route. if len(aircraft.route.segments) == 0: return self.formations = [] intervals = [] candidates = self.aircraft_queue hub = aircraft.route.waypoints[0] # This is bad. We don't want to filter anything. # @todo: pre-process at a higher level. # Only consider other aircraft flying to the same hub candidates = filter(lambda a: a.route.waypoints[0] is hub, candidates) p('debug', 'Full candidate set: %s' % candidates) # Only consider aircraft having a maximum heading difference between # the hub and their destination segment = Segment(aircraft.hub, aircraft.destination) leader_heading = segment.get_initial_bearing() def heading_filter(buddy): segment = Segment(buddy.hub, buddy.destination) buddy_heading = segment.get_initial_bearing() phi_obs = abs(leader_heading - buddy_heading) p( 'debug', 'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)' ': %.2f degrees' % (aircraft, leader_heading, buddy, buddy_heading, phi_obs)) return phi_obs <= (config.phi_max / 2) candidates = filter(heading_filter, candidates) # Other interesting filters if 'same-airline' in config.restrictions: airline = aircraft.label[0:2] candidates = filter(lambda a: a.label[0:2] == airline, candidates) if 'same-aircraft-type' in config.restrictions: aircraft_type = aircraft.aircraft_type candidates = filter(lambda a: a.aircraft_type == aircraft_type, candidates) p('debug', 'Reduced candidate set: %s' % candidates) for candidate in candidates: # Quick and dirty: recalc position. Instead, pull eta from var. candidate.controller.update_position() tth = candidate.time_to_waypoint() # time to hub hub_eta = sim.time + tth # From the moment the aircraft enters the lock area, the slack # decreases linearly to zero upon hub arrival. if tth < config.lock_time: slack = tth * config.etah_slack / config.lock_time else: slack = config.etah_slack p('Time = %s, Hub (= %s) eta %s for candidate %s' %\ (sim.time, hub, hub_eta, candidate)) intervals.append( Interval(candidate, int(hub_eta) - slack, int(hub_eta) + slack)) for interval_group in group(intervals): formation = Formation() for interval in interval_group: formation.append(interval.obj) self.formations.append(formation)