blob: 0bc2f57cc40429adde4eb98339d5805eb954ece5 [file] [log] [blame]
Yuheng Long16d7a522013-07-19 16:29:13 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Yuheng Longf20cffa2013-06-03 18:46:00 -07005"""A generation of a set of tasks.
6
Yuheng Long49358b72013-07-10 14:45:29 -07007Part of the Chrome build flags optimization.
8
Yuheng Long8b9c0f12013-07-16 09:38:16 -07009This module contains the base generation class. This class contains the tasks of
10this current generation. The generation will not evolve to the next generation
11until all the tasks in this generation are done executing. It also contains a
12set of tasks that could potentially be used to generate the next generation,
13e.g., in the genetic algorithm, a set of good species will be kept to evolve to
14the successive generations. For the hill climbing algorithm example, the
15candidate_pool will contain a current task t being evaluated and the exe_pool
16will contains all the task t's neighbor.
Yuheng Longf20cffa2013-06-03 18:46:00 -070017"""
18
19__author__ = 'yuhenglong@google.com (Yuheng Long)'
20
21
Yuheng Long8b9c0f12013-07-16 09:38:16 -070022class NoneOverridingError(Exception):
23 """Define an Exception class for subclasses not overriding certain methods."""
24 pass
25
26
Yuheng Longf20cffa2013-06-03 18:46:00 -070027class Generation(object):
28 """A generation of a framework run.
29
Yuheng Long8b9c0f12013-07-16 09:38:16 -070030 The base class of generation. Concrete subclasses, e.g., GAGeneration should
31 override the Next and Improve method to implement algorithm specific
32 applications.
Yuheng Longf20cffa2013-06-03 18:46:00 -070033 """
34
Yuheng Long8b9c0f12013-07-16 09:38:16 -070035 def __init__(self, exe_pool, candidate_pool):
Yuheng Longf20cffa2013-06-03 18:46:00 -070036 """Set up the tasks set of this generation.
37
38 Args:
Yuheng Long8b9c0f12013-07-16 09:38:16 -070039 exe_pool: A set of tasks to be run.
40 candidate_pool: A set of tasks to be considered to be used to generate the
41 next generation.
Yuheng Longf20cffa2013-06-03 18:46:00 -070042 """
Yuheng Long8b9c0f12013-07-16 09:38:16 -070043
44 self._exe_pool = exe_pool
45 self._candidate_pool = candidate_pool
46
47 # Keeping the record of how many tasks are pending. Pending tasks are the
48 # ones that have been sent out to the next stage for execution but have not
49 # finished. A generation is not ready for the reproduction of the new
50 # generations until all its pending tasks have been executed.
51 self._pending = len(exe_pool)
52
53 def Pool(self):
54 """Return the task set of this generation."""
55
56 return self._exe_pool
57
58 def Done(self):
59 """All the tasks in this generation are done.
60
61 Returns:
62 True if all the tasks have been executed. That is the number of pending
63 task is 0.
64 """
65
66 return self._pending == 0
67
68 def UpdateTask(self, task):
69 """Match a task t in this generation that is equal to the input task.
70
71 This method is called when the input task has just finished execution. This
72 method finds out whether there is a pending task t in the current generation
73 that is the same as the input task. Two tasks are the same if their flag
74 options are the same. A task is pending if it has not been performed.
75 If there is a pending task t that matches the input task, task t will be
76 substituted with the input task in this generation. In that case, the input
77 task, as well as its build and test results encapsulated in the task, will
78 be stored in the current generation. These results could be used to produce
79 the next generation.
80 If there is a match, the current generation will have one less pending task.
81 When there is no pending task, the generation can be used to produce the
82 next generation.
83 The caller of this function is responsible for not calling this method on
84 the same task more than once.
85
86 Args:
87 task: A task that has its results ready.
Yuheng Longa5712a22013-07-22 13:51:17 -070088
89 Returns:
90 Whether the input task belongs to this generation.
Yuheng Long8b9c0f12013-07-16 09:38:16 -070091 """
92
Yuheng Longa5712a22013-07-22 13:51:17 -070093 # If there is a match, the input task belongs to this generation.
94 if task not in self._exe_pool:
95 return False
Yuheng Long8b9c0f12013-07-16 09:38:16 -070096
Yuheng Longa5712a22013-07-22 13:51:17 -070097 # Remove the place holder task in this generation and store the new input
98 # task and its result.
99 self._exe_pool.remove(task)
100 self._exe_pool.add(task)
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700101
Yuheng Longa5712a22013-07-22 13:51:17 -0700102 # The current generation will have one less task to wait on.
103 self._pending -= 1
104
105 assert self._pending >= 0
106
107 return True
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700108
109 def Improve(self):
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700110 """True if this generation has improvement upon its parent generation.
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700111
112 Raises:
113 NoneOverridingError: The subclass should override this method.
114 """
115 raise NoneOverridingError('Must be implemented by child class')
Yuheng Longf20cffa2013-06-03 18:46:00 -0700116
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700117 def Next(self, _):
Yuheng Longf20cffa2013-06-03 18:46:00 -0700118 """Calculate the next generation.
119
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700120 This is the core of the framework implementation. It must be overridden by
121 the concrete subclass to implement algorithm specific generations.
Yuheng Longf20cffa2013-06-03 18:46:00 -0700122
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700123 Args:
124 _: A set of tasks that have been generated before. The overridden method
125 in the subclasses can use this so as not to generate task that has been
126 generated before.
127
Yuheng Longf20cffa2013-06-03 18:46:00 -0700128 Returns:
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700129 A set of new generations.
130
131 Raises:
132 NoneOverridingError: The subclass should override this method.
Yuheng Longf20cffa2013-06-03 18:46:00 -0700133 """
134
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700135 raise NoneOverridingError('Must be implemented by child class')