generation.py revision 8b9c0f140b48253cdbcc7c050f115c5e3bda6d88
1"""A generation of a set of tasks. 2 3Part of the Chrome build flags optimization. 4 5This module contains the base generation class. This class contains the tasks of 6this current generation. The generation will not evolve to the next generation 7until all the tasks in this generation are done executing. It also contains a 8set of tasks that could potentially be used to generate the next generation, 9e.g., in the genetic algorithm, a set of good species will be kept to evolve to 10the successive generations. For the hill climbing algorithm example, the 11candidate_pool will contain a current task t being evaluated and the exe_pool 12will contains all the task t's neighbor. 13""" 14 15__author__ = 'yuhenglong@google.com (Yuheng Long)' 16 17 18class NoneOverridingError(Exception): 19 """Define an Exception class for subclasses not overriding certain methods.""" 20 pass 21 22 23class Generation(object): 24 """A generation of a framework run. 25 26 The base class of generation. Concrete subclasses, e.g., GAGeneration should 27 override the Next and Improve method to implement algorithm specific 28 applications. 29 """ 30 31 def __init__(self, exe_pool, candidate_pool): 32 """Set up the tasks set of this generation. 33 34 Args: 35 exe_pool: A set of tasks to be run. 36 candidate_pool: A set of tasks to be considered to be used to generate the 37 next generation. 38 """ 39 40 self._exe_pool = exe_pool 41 self._candidate_pool = candidate_pool 42 43 # Keeping the record of how many tasks are pending. Pending tasks are the 44 # ones that have been sent out to the next stage for execution but have not 45 # finished. A generation is not ready for the reproduction of the new 46 # generations until all its pending tasks have been executed. 47 self._pending = len(exe_pool) 48 49 def Pool(self): 50 """Return the task set of this generation.""" 51 52 return self._exe_pool 53 54 def Done(self): 55 """All the tasks in this generation are done. 56 57 Returns: 58 True if all the tasks have been executed. That is the number of pending 59 task is 0. 60 """ 61 62 return self._pending == 0 63 64 def UpdateTask(self, task): 65 """Match a task t in this generation that is equal to the input task. 66 67 This method is called when the input task has just finished execution. This 68 method finds out whether there is a pending task t in the current generation 69 that is the same as the input task. Two tasks are the same if their flag 70 options are the same. A task is pending if it has not been performed. 71 If there is a pending task t that matches the input task, task t will be 72 substituted with the input task in this generation. In that case, the input 73 task, as well as its build and test results encapsulated in the task, will 74 be stored in the current generation. These results could be used to produce 75 the next generation. 76 If there is a match, the current generation will have one less pending task. 77 When there is no pending task, the generation can be used to produce the 78 next generation. 79 The caller of this function is responsible for not calling this method on 80 the same task more than once. 81 82 Args: 83 task: A task that has its results ready. 84 """ 85 86 # If there is a match. 87 if task in self._exe_pool: 88 # Remove the place holder task in this generation and store the new input 89 # task and its result. 90 self._exe_pool.remove(task) 91 self._exe_pool.add(task) 92 93 # The current generation will have one less task to wait on. 94 self._pending -= 1 95 96 assert self._pending >= 0 97 98 def Improve(self): 99 """True if this generation has improvement over its parent generation. 100 101 Raises: 102 NoneOverridingError: The subclass should override this method. 103 """ 104 raise NoneOverridingError('Must be implemented by child class') 105 106 def Next(self): 107 """Calculate the next generation. 108 109 This is the core of the framework implementation. It must be overridden by 110 the concrete subclass to implement algorithm specific generations. 111 112 Returns: 113 A set of new generations. 114 115 Raises: 116 NoneOverridingError: The subclass should override this method. 117 """ 118 119 raise NoneOverridingError('Must be implemented by child class') 120