blob: 331c810592d7f598be0402877bb9dc6dc16bfadc [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
Yuheng Longc0123222013-08-11 12:24:32 -070015candidate_pool will contain a current task t being evaluated and the exe_set
Yuheng Long8b9c0f12013-07-16 09:38:16 -070016will 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
Yuheng Longc0123222013-08-11 12:24:32 -070031 override the Next and IsImproved method to implement algorithm specific
Yuheng Long8b9c0f12013-07-16 09:38:16 -070032 applications.
Yuheng Longf20cffa2013-06-03 18:46:00 -070033 """
34
Yuheng Longc0123222013-08-11 12:24:32 -070035 def __init__(self, exe_set, candidate_pool):
Yuheng Longf20cffa2013-06-03 18:46:00 -070036 """Set up the tasks set of this generation.
37
38 Args:
Yuheng Longc0123222013-08-11 12:24:32 -070039 exe_set: A set of tasks to be run.
Yuheng Long8b9c0f12013-07-16 09:38:16 -070040 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
Yuheng Longc0123222013-08-11 12:24:32 -070044 self._exe_set = exe_set
Yuheng Long8b9c0f12013-07-16 09:38:16 -070045 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.
Yuheng Longc0123222013-08-11 12:24:32 -070051 self._pending = len(exe_set)
Yuheng Long8b9c0f12013-07-16 09:38:16 -070052
Yuheng Long057ad5c2013-08-07 08:48:05 -070053 def CandidatePool(self):
54 """Return the candidate tasks of this generation."""
55
56 return self._candidate_pool
57
Yuheng Long8b9c0f12013-07-16 09:38:16 -070058 def Pool(self):
59 """Return the task set of this generation."""
60
Yuheng Longc0123222013-08-11 12:24:32 -070061 return self._exe_set
Yuheng Long8b9c0f12013-07-16 09:38:16 -070062
63 def Done(self):
64 """All the tasks in this generation are done.
65
66 Returns:
67 True if all the tasks have been executed. That is the number of pending
68 task is 0.
69 """
70
71 return self._pending == 0
72
73 def UpdateTask(self, task):
74 """Match a task t in this generation that is equal to the input task.
75
76 This method is called when the input task has just finished execution. This
77 method finds out whether there is a pending task t in the current generation
78 that is the same as the input task. Two tasks are the same if their flag
79 options are the same. A task is pending if it has not been performed.
80 If there is a pending task t that matches the input task, task t will be
81 substituted with the input task in this generation. In that case, the input
82 task, as well as its build and test results encapsulated in the task, will
83 be stored in the current generation. These results could be used to produce
84 the next generation.
85 If there is a match, the current generation will have one less pending task.
86 When there is no pending task, the generation can be used to produce the
87 next generation.
88 The caller of this function is responsible for not calling this method on
89 the same task more than once.
90
91 Args:
92 task: A task that has its results ready.
Yuheng Longa5712a22013-07-22 13:51:17 -070093
94 Returns:
95 Whether the input task belongs to this generation.
Yuheng Long8b9c0f12013-07-16 09:38:16 -070096 """
97
Yuheng Longa5712a22013-07-22 13:51:17 -070098 # If there is a match, the input task belongs to this generation.
Yuheng Longc0123222013-08-11 12:24:32 -070099 if task not in self._exe_set:
Yuheng Longa5712a22013-07-22 13:51:17 -0700100 return False
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700101
Yuheng Longa5712a22013-07-22 13:51:17 -0700102 # Remove the place holder task in this generation and store the new input
103 # task and its result.
Yuheng Longc0123222013-08-11 12:24:32 -0700104 self._exe_set.remove(task)
105 self._exe_set.add(task)
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700106
Yuheng Longa5712a22013-07-22 13:51:17 -0700107 # The current generation will have one less task to wait on.
108 self._pending -= 1
109
110 assert self._pending >= 0
111
112 return True
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700113
Yuheng Longc0123222013-08-11 12:24:32 -0700114 def IsImproved(self):
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700115 """True if this generation has improvement upon its parent generation.
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700116
117 Raises:
118 NoneOverridingError: The subclass should override this method.
119 """
120 raise NoneOverridingError('Must be implemented by child class')
Yuheng Longf20cffa2013-06-03 18:46:00 -0700121
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700122 def Next(self, _):
Yuheng Longf20cffa2013-06-03 18:46:00 -0700123 """Calculate the next generation.
124
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700125 This is the core of the framework implementation. It must be overridden by
126 the concrete subclass to implement algorithm specific generations.
Yuheng Longf20cffa2013-06-03 18:46:00 -0700127
Yuheng Longccfaf2f2013-08-02 14:27:45 -0700128 Args:
129 _: A set of tasks that have been generated before. The overridden method
130 in the subclasses can use this so as not to generate task that has been
131 generated before.
132
Yuheng Longf20cffa2013-06-03 18:46:00 -0700133 Returns:
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700134 A set of new generations.
135
136 Raises:
137 NoneOverridingError: The subclass should override this method.
Yuheng Longf20cffa2013-06-03 18:46:00 -0700138 """
139
Yuheng Long8b9c0f12013-07-16 09:38:16 -0700140 raise NoneOverridingError('Must be implemented by child class')