In [ ]:
%pylab inline
from collections import deque
import time

In [ ]:
lambda_ = 10. / 60 # ten planes per 60 minutes
beta = 1. / lambda_
arrival_times = np.random.exponential(scale=beta, size=10000)
plt.hist(arrival_times, bins=np.linspace(0, 60, 13))
plt.xlabel("Time / Minutes")
plt.show()

In [ ]:
waiting_times = [1., 2., 3., 4.]

class Airport:
    def __init__(self, name, verbose=False):
        self.name = name
        self.queue = deque() # double ended queue
        self.planes_landed = 0
        self.verbose = verbose
        
    def accept_plane(self, time, plane):
        old_len = len(self.queue)
        # check if there are planes in the queue that have landed by now
        while len(self.queue) > 0 and self.queue[0] < time:
            self.queue.popleft()
            self.planes_landed += 1
        if self.verbose:
            print "{}) {} planes have landed successfully".format(self.name, old_len - len(self.queue))
        if len(self.queue) == 0:
            self.queue.append(time + waiting_times[plane])
        else:
            self.queue.append(self.queue[-1] + waiting_times[plane])
        
        if self.verbose:
            print "{}: At the moment (time {}), {} planes are queueing.".format(self.name, time, self.queue_len())
            if self.waiting_time == 0:
                print "{}: Next free slot available now.".format(self.name)
            else:
                print "{}: Next free slot available at time {}.".format(self.name, self.queue[-1])

    def queue_len(self):
        return len(self.queue)
    
    def waiting_time(self, time):
        if len(self.queue) > 0:
            return self.queue[-1] - time
        else:
            return 0
       

def simulate_arrivals(arrivals_per_minute, selector_fct, arrivals=10000, verbose=False):
    beta = 1. / arrivals_per_minute
    arrival_times = np.random.exponential(scale=beta, size=arrivals)
    qlen_a1, qlen_a2 = [], []
    waiting_time_a1, waiting_time_a2 = [], []
    current_time = 0
    a1, a2 = Airport("A1", verbose=verbose), Airport("A2", verbose=verbose)
    for i, arrival in enumerate(arrival_times):
        plane_type = np.random.randint(4)
        current_time += arrival
        if verbose:
            print "Step {}) Plane of type {} arrives at time {}".format(i, plane_type, current_time)
            
        selector_fct(a1, a2, current_time, plane_type, verbose=verbose)
        
        waiting_time_a1.append(a1.waiting_time(current_time))
        waiting_time_a2.append(a2.waiting_time(current_time))
        
        print "\n"
    return np.cumsum(arrival_times), waiting_time_a1, waiting_time_a2, a1.planes_landed + a2.planes_landed
            

def select_lowest_waiting_time(a1, a2, current_time, plane_type, verbose=False):
    if verbose:
        print "Time:", current_time
        print "Planes queueing for airport 1:", len(a1.queue)
        print "Landing times:", ", ".join(map(str, a1.queue))
        print "Planes queueing for airport 2:", len(a2.queue)
        print "Landing times:", ", ".join(map(str, a2.queue))
    if a1.waiting_time(current_time) <= a2.waiting_time(current_time):
        if verbose:
            print "I choose airport 1 for this plane"
        a1.accept_plane(current_time, plane_type)
    else:
        if verbose:
            print "I choose airport 2 for this plane"
        a2.accept_plane(current_time, plane_type)        

def select_plane_type(a1, a2, current_time, plane_type, verbose=False):
    if plane_type < 2:
        a1.accept_plane(current_time, plane_type)
    else:
        a2.accept_plane(current_time, plane_type)

In [ ]:
t, a1, a2, planes_landed = simulate_arrivals(arrivals_per_minute=.9, selector_fct=select_lowest_waiting_time, 
                                             arrivals=20, verbose=True)

plt.plot(t, a1, t, a2)
plt.show()
print planes_landed, planes_landed / t[-1]

In [ ]: