def __init__(self, event_file): """ This function initialises the simulator. :param event_file: the file containing the "events" received by flight control """ self._queue = AdaptableHeapPriorityQueue() self._locator = {} self._event_file = event_file
def MST_PrimJarnik(g): """Compute a minimum spanning tree of weighted graph g. Return a list of edges that comprise the MST (in arbitrary order). """ d = {} # d[v] is bound on distance to tree tree = [] # list of edges in spanning tree pq = AdaptableHeapPriorityQueue() # d[v] maps to value (v, e=(u,v)) pqlocator = {} # map from vertex to its pq locator # for each vertex v of the graph, add an entry to the priority queue, with # the source having distance 0 and all others having infinite distance for v in g.vertices(): if len(d) == 0: # this is the first node d[v] = 0 # make it the root else: d[v] = float('inf') # positive infinity pqlocator[v] = pq.add(d[v], (v, None)) while not pq.is_empty(): key, value = pq.remove_min() u, edge = value # unpack tuple from pq del pqlocator[u] # u is no longer in pq if edge is not None: tree.append(edge) # add edge to tree for link in g.incident_edges(u): v = link.opposite(u) if v in pqlocator: # thus v not yet in tree # see if edge (u, v) better connects v to the growing tree wgt = link.element() if wgt < d[v]: # better edge to v? d[v] = wgt # update the distance pq.update(pqlocator[v], d[v], (v, link)) # update the pq entry return tree
def shortest_path_lengths(g, src): """Compute shortest-path distances from src to reachable vertices of g. Graph g can be undirected or directed, but must be weighted such that e.element() returns a numeric weight for each edge e. Return dictionary mapping each reachable vertex to its distance from src. """ d = {} # d[v] is upper bound from s to v cloud = {} # map reachable v to its d[v] value pq = AdaptableHeapPriorityQueue() # vertex v will have key d[v] pqlocator = {} # map from vertex to its pq locator # for each vertex v of the graph, add an entry to the priority queue, with # the source having distance 0 and all others having infinite distance for v in g.vertices(): if v is src: d[v] = 0 else: d[v] = float('inf') # syntax for positive infinity pqlocator[v] = pq.add(d[v], v) # save locator for future updates while not pq.is_empty(): key, u = pq.remove_min() cloud[u] = key # its correct d[u] value print(pqlocator[u]) # print distance from origin point and current point del pqlocator[u] # u is no longer in pq for e in g.incident_edges(u): # outgoing edges (u,v) v = e.opposite(u) if v not in cloud: # perform relaxation step on edge (u,v) wgt = e.element() if d[u] + wgt < d[v]: # better path to v? d[v] = d[u] + wgt # update the distance pq.update(pqlocator[v], d[v], v) # update the pq entry return cloud # only includes reachable vertices
def dijkstra(g, s): q = AdaptableHeapPriorityQueue() dist = {} locators = {} for v in g.vertices(): if v == s: v.dist = 0 else: v.dist = infinity l = q.add(v.dist, v) v.locator = l while q.__len__() > 0: (key, u) = q.remove_min() print("***", key, u) for e in g.incident_edges(u): w = g.opposite(u, e) print(u.__dict__) if w.dist > u.dist + e.element(): w.dist = u.dist + e.element() q.update(w.locator, w.dist, w)
def shortest_path_lengths(g, src): """Compute shortest-path distances from src to reachable vertices of g. Graph g can be undirected or directed, but must be weighted such that e.element() returns a numeric weight for each edge e. Return dictionary mapping each reachable vertex to its distance from src. """ d = { } # d[v] is upper bound from s to v # map reachable v to its d[v] value cloud = {} pq = AdaptableHeapPriorityQueue() # vertex v will have key d[v] pqlocator = {} # map from vertex to its pq locator # for each vertex v of the graph, add an entry to the priority queue, with # the source having distance 0 and all others having infinite distance for v in g.vertices(): if v is src: d[v] = 0 else: # syntax for positive infinity d[v] = float('inf') # save locator for future updates pqlocator[v] = pq.add(d[v], v) while not pq.is_empty(): key, u = pq.remove_min() cloud[u] = key # its correct d[u] value del pqlocator[u] # u is no longer in pq for e in g.incident_edges(u): # outgoing edges (u,v) v = e.opposite(u) if v not in cloud: # perform relaxation step on edge (u,v) wgt = e.element() if d[u] + wgt < d[v]: # better path to v? d[v] = d[u] + wgt # update the distance pq.update(pqlocator[v], d[v], v) # update the pq entry return cloud # only includes reachable vertices
""" This is a simple example that demonstrates how to use the heap-based priority queue """ from adaptable_heap_priority_queue import AdaptableHeapPriorityQueue if __name__ == '__main__': """ Note: it is a min-heap: highest priority means lowest priority key""" AH = AdaptableHeapPriorityQueue() # create new queue loc1 = AH.add(3, "event 1") # add some events in the queue loc2 = AH.add(1, "event 2") loc3 = AH.add(5, "event 3") loc4 = AH.add(4, "event 4") print("This is the current highest priority event: {0}".format( AH.min())) # only check, does not return the value print(AH.__len__()) # check length of queue print("Dequeue next event: {0}".format( AH.remove_min())) # removes and returns the highest priority event print(AH.__len__()) # check length of queue print("This is the current highest priority event: {0}".format( AH.min())) # only check, does not return the value AH.update(loc3, 0, "event 3") # updates the priority of one event print("This is the current highest priority event: {0}".format( AH.min())) # only check, does not return the value print("Dequeue next event: {0}".format(AH.remove_min())) print("Dequeue next event: {0}".format(AH.remove_min())) print("Dequeue next event: {0}".format(AH.remove_min())) print(AH.__len__()) # check length of queue
class FlightLandingControl(): def __init__(self, event_file): """ This function initialises the simulator. :param event_file: the file containing the "events" received by flight control """ self._queue = AdaptableHeapPriorityQueue() self._locator = {} self._event_file = event_file def _add_flight(self, priority, flight_no): """ This function adds a flight to the queue. :param priority: the priority level of the flight :param flight_no: the flight :return: """ loc = self._queue.add(priority, flight_no) self._locator[flight_no] = [loc, priority] def _update(self, new_priority, flight_no): """ This function updates the level of priority of a flight in the queue :param new_priority: the new level of priority :param flight_no: the flight """ loc = self._locator[flight_no] self._queue.update(loc[0], new_priority, flight_no) def _land(self): """ This function simulates the landing of a flight by printing a message e.g.: "Flight AZ1100 landed!" """ print("Flight {0} landed!".format(self._queue.remove_min())) def _process_event(self, line): """ This function should process one event contained in one "line" of the events file. :param line: a string representing the event, e.g. KK8989,sick passenger; flight,land; AZ1012,national etc. """ values = list(line.split(',')) flight_no = values[0] event = values[1] if event == "short": self._add_flight(2, flight_no) elif event == "long": self._add_flight(4, flight_no) elif event == "national": self._add_flight(6, flight_no) elif event == "land": self._land() elif event == "sick passenger": self._update(1, flight_no) elif event == "fuel low": self._update(1, flight_no) elif len(values) == 3: if values[2] == 'start': for loc in self._locator: if loc[0] == 'A' and loc[1] == 'Z': dat = self._locator[loc] self._queue.update(dat[0], dat[1] - 2, flight_no) if values[2] == 'stop': for loc in self._locator: if loc[0] == 'A' and loc[1] == 'Z': dat = self._locator[loc] self._queue.update(dat[0], dat[1] + 2, flight_no) def process_event_file(self): # open event file for reading file = open(self._event_file, "r") # each line is a new event for line in file.readlines(): print( "******************** Processing new event: {0}".format(line)) self._process_event(line) time.sleep(0.5)
class Scheduler: '''This class is a batch job scheduler that implements heap priority queue.''' def __init__(self): self.__jobHeap = AdaptableHeapPriorityQueue() def load_jobs(self, filename): '''Loads jobs from input file.''' with open(filename, 'r') as file: for line in file: if not line.startswith('JOB,PRIORITY,LENGTH'): data = line.rstrip().split(',') job = Job(data[0], int(data[1]), int(data[2])) self.__jobHeap.add((job.get_priority(), job.get_length()), job) file.close() def run(self): try: # Print current status current_key, current_job = self.__jobHeap.min() current_job.prnt_job() # Update if current_job.get_length() > 1: new_length = current_job.get_length() - 1 current_job.set_length(new_length) else: self.__jobHeap.remove_min() return True except Empty: return False def halt(self): print("\nScheduler has been halted:") # Update the min with the remaining length current_key, current_job = self.__jobHeap.remove_min() self.__jobHeap.add((current_key[0], current_job.get_length()), current_job) # tmpHeap stores the job that is removed from the jobHeap tmpHeap = AdaptableHeapPriorityQueue() # nameDict is a dictionary that stores job names as keys and locators as values nameDict = {} # listJobs is a python list used to sort jobs listJobs = [] # prompt the user for how the table should be sorted srt = input("Sort by (j/p/l/h): ") print(self) try: while True: # Remove from jobHeap and print the job data if heap order is selected tmpKey, tmpJob = self.__jobHeap.remove_min() name = tmpJob.get_name() priority = tmpJob.get_priority() length = tmpJob.get_length() if(srt == 'h'): print(tmpJob) # Add the job from the jobHeap to the tmpHeap nameDict[name] = tmpHeap.add(tmpKey, tmpJob) # Add the job to the listJobs listJobs.append((name, priority, length)) except Empty: pass # Print the jobs based on the user input if other than heap order if srt == 'j': for j in sorted(listJobs, key=lambda jobs: jobs[0]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) elif srt == 'p': for j in sorted(listJobs, key=lambda jobs: jobs[1]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) elif srt == 'l': for j in sorted(listJobs, key=lambda jobs: jobs[2]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) # Add new job newJob = input("New job? (y/n): ") if newJob == 'y': name = input("New job name: ") priority = int(input("New job priority: ")) length = int(input("New job length: ")) newJob = Job(name, priority, length) tmpHeap.add((priority, length), newJob) # Alter a job alter = input("Alter priority? (y/n): ") if alter == 'y': name = input("Job name: ") priority = int(input("New priority: ")) tmpKey, tmpJob = tmpHeap.remove(nameDict[name]) tmpJob.set_priority(priority) tmpHeap.add((priority, tmpKey[1]), tmpJob) # Restart the scheduler print("Restarting scheduler...") self.__jobHeap = tmpHeap def __repr__(self): output = '{0:<20} {1:>10} {2:>10}'.format('Name', 'Priority', 'Length') output += '\n' + '-'*45 + '\n' return output
def halt(self): print("\nScheduler has been halted:") # Update the min with the remaining length current_key, current_job = self.__jobHeap.remove_min() self.__jobHeap.add((current_key[0], current_job.get_length()), current_job) # tmpHeap stores the job that is removed from the jobHeap tmpHeap = AdaptableHeapPriorityQueue() # nameDict is a dictionary that stores job names as keys and locators as values nameDict = {} # listJobs is a python list used to sort jobs listJobs = [] # prompt the user for how the table should be sorted srt = input("Sort by (j/p/l/h): ") print(self) try: while True: # Remove from jobHeap and print the job data if heap order is selected tmpKey, tmpJob = self.__jobHeap.remove_min() name = tmpJob.get_name() priority = tmpJob.get_priority() length = tmpJob.get_length() if(srt == 'h'): print(tmpJob) # Add the job from the jobHeap to the tmpHeap nameDict[name] = tmpHeap.add(tmpKey, tmpJob) # Add the job to the listJobs listJobs.append((name, priority, length)) except Empty: pass # Print the jobs based on the user input if other than heap order if srt == 'j': for j in sorted(listJobs, key=lambda jobs: jobs[0]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) elif srt == 'p': for j in sorted(listJobs, key=lambda jobs: jobs[1]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) elif srt == 'l': for j in sorted(listJobs, key=lambda jobs: jobs[2]): output = '{0:<20} '.format(j[0]) output += '{0:>10} '.format(j[1]) output += '{0:>10} '.format(j[2]) print(output) # Add new job newJob = input("New job? (y/n): ") if newJob == 'y': name = input("New job name: ") priority = int(input("New job priority: ")) length = int(input("New job length: ")) newJob = Job(name, priority, length) tmpHeap.add((priority, length), newJob) # Alter a job alter = input("Alter priority? (y/n): ") if alter == 'y': name = input("Job name: ") priority = int(input("New priority: ")) tmpKey, tmpJob = tmpHeap.remove(nameDict[name]) tmpJob.set_priority(priority) tmpHeap.add((priority, tmpKey[1]), tmpJob) # Restart the scheduler print("Restarting scheduler...") self.__jobHeap = tmpHeap
def __init__(self): self.__jobHeap = AdaptableHeapPriorityQueue()