| The Gaudi Framework v28r2-patches (bc4ad17a)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

ControlFlow.py
Go to the documentation of this file.
1 '''
2 Classes for the implementation of the Control Flow Structure Syntax.
3
4 @see: https://github.com/lhcb/scheduling-event-model/tree/master/controlflow_syntax
5 '''
6
7
8 class ControlFlowNode(object):
9 '''
10 Basic entry in the control flow graph.
11 '''
12 def __and__(self, rhs):
13 if rhs is CFTrue:
14 return self
15 elif rhs is CFFalse:
16 return CFFalse
17 return AndNode(self, rhs)
18
19 def __or__(self, rhs):
20 if rhs is CFFalse:
21 return self
22 elif rhs is CFTrue:
23 return CFTrue
24 return OrNode(self, rhs)
25
26 def __invert__(self):
27 return InvertNode(self)
28
29 def __rshift__(self, rhs):
30 return OrderedNode(self, rhs)
31
32 def visitNode(self, visitor):
33 visitor.enter(self)
34 self._visitSubNodes(visitor)
35 visitor.leave(self)
36
37 def _visitSubNodes(self, visitor):
38 pass
39
40 def __eq__(self, other):
41 return (repr(self) == repr(other))
42
43 def getFullName(self):
44 '''
45 Allow use of an expression as an algorihtm/sequence in a Gaudi job
46 configuration.
47
48 Convert the expression in nested sequencers and return the full name of
49 the top one.
50 '''
51 if not hasattr(self, '_fullname'):
52 from GaudiKernel.Configurable import makeSequences
53 self._fullname = makeSequences(self).getFullName()
54 return self._fullname
55
56
57 class ControlFlowLeaf(ControlFlowNode):
58 '''
59 Class used to identify a note without sub-nodes.
60 '''
61 pass
62
63
64 class ControlFlowBool(ControlFlowLeaf):
65 def __init__(self, value):
66 self.value = value
67 def __and__(self, rhs):
68 return rhs if self.value else self
69 def __or__(self, rhs):
70 return self if self.value else rhs
71 def __invert__(self):
72 return CFFalse if self.value else CFTrue
73 def __repr__(self):
74 return 'CFTrue' if self.value else 'CFFalse'
75
76 CFTrue = ControlFlowBool(True)
77 CFFalse = ControlFlowBool(False)
78 del ControlFlowBool
79
80 class OrderedNode(ControlFlowNode):
81 '''
82 Represent order of execution of nodes.
83 '''
84 def __init__(self, lhs, rhs):
85 self.lhs = lhs
86 self.rhs = rhs
87
88 def __repr__(self):
89 return "(%r >> %r)" % (self.lhs, self.rhs)
90
91 def _visitSubNodes(self, visitor):
92 self.lhs.visitNode(visitor)
93 self.rhs.visitNode(visitor)
94
95
96 class AndNode(ControlFlowNode):
97 '''
98 And operation between control flow nodes.
99 '''
100 def __init__(self, lhs, rhs):
101 self.lhs = lhs
102 self.rhs = rhs
103
104 def __repr__(self):
105 return "(%r & %r)" % (self.lhs, self.rhs)
106
107 def _visitSubNodes(self, visitor):
108 self.lhs.visitNode(visitor)
109 self.rhs.visitNode(visitor)
110
111
112 class OrNode(ControlFlowNode):
113 '''
114 Or operation between control flow nodes.
115 '''
116 def __init__(self, lhs, rhs):
117 self.lhs = lhs
118 self.rhs = rhs
119
120 def __repr__(self):
121 return "(%r | %r)" % (self.lhs, self.rhs)
122
123 def _visitSubNodes(self, visitor):
124 self.lhs.visitNode(visitor)
125 self.rhs.visitNode(visitor)
126
127
128 class InvertNode(ControlFlowNode):
129 '''
130 Invert logic (negation) of a control flow node.
131 '''
132 def __init__(self, item):
133 self.item = item
134
135 def __repr__(self):
136 return "~%r" % self.item
137
138 def _visitSubNodes(self, visitor):
139 self.item.visitNode(visitor)
140
141
142 class ignore(ControlFlowNode):
143 '''
144 Treat a control flow node as always successful, equivalent to (a | ~ a).
145 '''
146 def __init__(self, item):
147 self.item = item
148
149 def __repr__(self):
150 return "ignore(%r)" % self.item
151
152 def _visitSubNodes(self, visitor):
153 self.item.visitNode(visitor)
154
155
156 class par(ControlFlowNode):
157 def __init__(self, item):
158 self.item = item
159
160 def __repr__(self):
161 return "par(%r)" % self.item
162
163 def _visitSubNodes(self, visitor):
164 self.item.visitNode(visitor)
165
166
167 class seq(ControlFlowNode):
168 def __init__(self, item):
169 self.item = item
170
171 def __repr__(self):
172 return "seq(%r)" % self.item
173
174 def _visitSubNodes(self, visitor):
175 self.item.visitNode(visitor)
176
177
178 class line(object):
179 def __init__(self, name, item):
180 self.name = name
181 self.item = item
182
183 def __repr__(self):
184 return "line(%r, %r)" % (self.name, self.item)
185
186 def _visitSubNodes(self, visitor):
187 self.item.visitNode(visitor)
188
189
190 class _TestVisitor(object):
191 def __init__(self):
192 self.depths = 0
193
194 def enter(self, visitee):
195 self.depths += 1
196 print "%sEntering %s" % (self.depths*" ", type(visitee))
197 if isinstance(visitee, ControlFlowLeaf):
198 print "%s Algorithm name: %s" % (" "*self.depths, visitee)
199
200 def leave(self, visitee):
201 print "%sLeaving %s" % (self.depths * " ", type(visitee))
202 self.depths -= 1
203
204
205 class _TestAlgorithm(ControlFlowLeaf):
206 def __init__(self, name):
207 self._name = name
208
209 def __repr__(self):
210 return self._name
211
212 def name(self):
213 return self._name
214
215
216 class DotVisitor(object):
217 def __init__(self):
218 self.nodes = []
219 self.edges = []
220 self.number = 0
221 self.stack = []
222 self.ids = {}
223
224 def enter(self, visitee):
225 if visitee not in self.ids:
226 self.number += 1
227 dot_id = self.ids[visitee] = 'T%s' % self.number
228 dot_id = self.ids[visitee]
229 mother = None
230 if self.is_needed(visitee):
231 if isinstance(visitee, ControlFlowLeaf):
232 entry = '%s [label="%s", shape=box]' % (dot_id, visitee.name())
233 elif isinstance(visitee, OrNode):
234 entry = '%s [label="OR", shape=invhouse]' % dot_id
235 elif isinstance(visitee, AndNode):
236 entry = '%s [label="AND", shape=invhouse]' % dot_id
237 elif isinstance(visitee, OrderedNode):
238 entry = '%s [label=">>", shape=point]' % dot_id
239 elif isinstance(visitee, InvertNode):
240 entry = '%s [label="NOT", shape=circle, color=red]' % dot_id
241 elif isinstance(visitee, par):
242 entry = '%s [label="PAR", shape=circle]' % dot_id
243 elif isinstance(visitee, seq):
244 entry = '%s [label="SEQ", shape=circle]' % dot_id
245 else:
246 entry = '%s [label="%s", shape=circle]' % (dot_id, type(visitee))
247 self.nodes.append(entry)
248 if len(self.stack) != 0:
249 mother = self.collapse_identical_ancestors(type(self.stack[-1][0]))
250 if not mother:
251 mother = self.stack[-1][1]
252 edge = "%s->%s" % (dot_id, mother)
253 self.edges.append(edge)
254 self.stack.append((visitee, dot_id))
255
256 def leave(self, visitee):
257 self.stack.pop()
258
259 def collapse_identical_ancestors(self, thetype):
260 '''
261 If AND nodes are inside AND nodes, the graph could be simplified
262 to not contain those (same true for OR and ordered)
263 '''
264 counter = 0
265 if len(self.stack) != 0:
266 mother = self.stack[-1][1]
267 for entry in self.stack[::-1]:
268 if type(entry[0]) != thetype:
269 break
270 mother = entry[1]
271 return mother
272 return None
273
274 def is_needed(self, visitee):
275 '''
276 Check whether this node is actually needed
277 '''
278 if len(self.stack) != 0:
279 return not isinstance(visitee, type(self.stack[-1][0]))
280 return True
281
282 def write(self, filename):
283 output = """
284 digraph graphname {
285 rankdir=LR
286
287 %s
288
289 %s
290
291 }
292 """ % ("\n".join(self.nodes), "\n".join(self.edges))
293
294 with open(filename, "w") as outfile:
295 outfile.write(output)
296
297
298 def test():
299 Algorithm = _TestAlgorithm
300
301 a = Algorithm("a")
302 b = Algorithm("b")
303 c = Algorithm("c")
304 d = Algorithm("d")
305 e = Algorithm("e")
306 f = Algorithm("f")
307 g = Algorithm("g")
308 sequence = seq(b >> a >> f)
309 expression = sequence | ~c & par(d & e & g)
310 a = (expression == expression)
311 aLine = line("MyTriggerPath", expression)
312 visitor = _TestVisitor()
313 visitor2 = DotVisitor()
314 print "\nPrinting trigger line:"
315 print aLine
316 print "\nPrinting expression:"
317 print expression
318 print "\nTraversing through expression:\n"
319 expression.visitNode(visitor)
320 expression.visitNode(visitor2)
321 visitor2.write("out.dot")
GaudiConfig.ControlFlow.DotVisitor
Definition: ControlFlow.py:216
GaudiConfig.ControlFlow.OrNode.lhs
lhs
Definition: ControlFlow.py:117
GaudiConfig.ControlFlow._TestVisitor
Definition: ControlFlow.py:190
GaudiConfig.ControlFlow.DotVisitor.stack
stack
Definition: ControlFlow.py:221
GaudiConfig.ControlFlow.line._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:186
GaudiConfig.ControlFlow.AndNode
Definition: ControlFlow.py:96
GaudiConfig.ControlFlow.OrNode
Definition: ControlFlow.py:112
GaudiConfig.ControlFlow.OrderedNode.__repr__
def __repr__(self)
Definition: ControlFlow.py:88
GaudiConfig.ControlFlow.par.__init__
def __init__(self, item)
Definition: ControlFlow.py:157
GaudiConfig.ControlFlow.DotVisitor.edges
edges
Definition: ControlFlow.py:219
GaudiConfig.ControlFlow.ControlFlowBool.__and__
def __and__(self, rhs)
Definition: ControlFlow.py:67
GaudiConfig.ControlFlow.ControlFlowBool.__repr__
def __repr__(self)
Definition: ControlFlow.py:73
GaudiConfig.ControlFlow.ControlFlowBool.value
value
Definition: ControlFlow.py:66
GaudiConfig.ControlFlow.DotVisitor.number
number
Definition: ControlFlow.py:220
GaudiConfig.ControlFlow._TestAlgorithm.__init__
def __init__(self, name)
Definition: ControlFlow.py:206
GaudiConfig.ControlFlow.AndNode.lhs
lhs
Definition: ControlFlow.py:101
GaudiConfig.ControlFlow.line.item
item
Definition: ControlFlow.py:181
GaudiKernel.Configurable.makeSequences
def makeSequences(expression)
Definition: Configurable.py:1609
GaudiConfig.ControlFlow.par.item
item
Definition: ControlFlow.py:158
GaudiConfig.ControlFlow.ControlFlowBool.__init__
def __init__(self, value)
Definition: ControlFlow.py:65
GaudiConfig.ControlFlow.line.__init__
def __init__(self, name, item)
Definition: ControlFlow.py:179
GaudiConfig.ControlFlow.OrNode.__repr__
def __repr__(self)
Definition: ControlFlow.py:120
GaudiConfig.ControlFlow._TestVisitor.enter
def enter(self, visitee)
Definition: ControlFlow.py:194
GaudiConfig.ControlFlow._TestAlgorithm.__repr__
def __repr__(self)
Definition: ControlFlow.py:209
GaudiConfig.ControlFlow.seq.item
item
Definition: ControlFlow.py:169
GaudiConfig.ControlFlow.InvertNode
Definition: ControlFlow.py:128
GaudiConfig.ControlFlow.OrderedNode.rhs
rhs
Definition: ControlFlow.py:86
GaudiConfig.ControlFlow._TestVisitor.leave
def leave(self, visitee)
Definition: ControlFlow.py:200
GaudiConfig.ControlFlow.par
Definition: ControlFlow.py:156
GaudiConfig.ControlFlow.ControlFlowNode.__invert__
def __invert__(self)
Definition: ControlFlow.py:26
GaudiConfig.ControlFlow.DotVisitor.collapse_identical_ancestors
def collapse_identical_ancestors(self, thetype)
Definition: ControlFlow.py:259
GaudiConfig.ControlFlow.OrderedNode._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:91
GaudiConfig.ControlFlow._TestVisitor.depths
depths
Definition: ControlFlow.py:192
GaudiConfig.ControlFlow.seq
Definition: ControlFlow.py:167
GaudiConfig.ControlFlow.ControlFlowNode.__rshift__
def __rshift__(self, rhs)
Definition: ControlFlow.py:29
GaudiConfig.ControlFlow.ignore.item
item
Definition: ControlFlow.py:147
GaudiConfig.ControlFlow.ControlFlowBool.__invert__
def __invert__(self)
Definition: ControlFlow.py:71
GaudiConfig.ControlFlow.OrderedNode
Definition: ControlFlow.py:80
GaudiConfig.ControlFlow.InvertNode.item
item
Definition: ControlFlow.py:133
GaudiConfig.ControlFlow.InvertNode.__init__
def __init__(self, item)
Definition: ControlFlow.py:132
GaudiConfig.ControlFlow.OrNode.__init__
def __init__(self, lhs, rhs)
Definition: ControlFlow.py:116
GaudiConfig.ControlFlow.OrNode._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:123
GaudiConfig.ControlFlow.line.name
name
Definition: ControlFlow.py:180
GaudiConfig.ControlFlow._TestVisitor.__init__
def __init__(self)
Definition: ControlFlow.py:191
GaudiConfig.ControlFlow.DotVisitor.ids
ids
Definition: ControlFlow.py:222
GaudiConfig.ControlFlow.DotVisitor.enter
def enter(self, visitee)
Definition: ControlFlow.py:224
GaudiConfig.ControlFlow.line
Definition: ControlFlow.py:178
GaudiConfig.ControlFlow.DotVisitor.write
def write(self, filename)
Definition: ControlFlow.py:282
GaudiConfig.ControlFlow.seq.__repr__
def __repr__(self)
Definition: ControlFlow.py:171
GaudiConfig.ControlFlow.ControlFlowBool.__or__
def __or__(self, rhs)
Definition: ControlFlow.py:69
GaudiConfig.ControlFlow.ControlFlowNode.visitNode
def visitNode(self, visitor)
Definition: ControlFlow.py:32
GaudiConfig.ControlFlow.ControlFlowNode.__or__
def __or__(self, rhs)
Definition: ControlFlow.py:19
gaudirun.type
type
Definition: gaudirun.py:125
GaudiConfig.ControlFlow.AndNode._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:107
GaudiConfig.ControlFlow.line.__repr__
def __repr__(self)
Definition: ControlFlow.py:183
GaudiConfig.ControlFlow.DotVisitor.__init__
def __init__(self)
Definition: ControlFlow.py:217
GaudiConfig.ControlFlow.ignore
Definition: ControlFlow.py:142
GaudiConfig.ControlFlow.seq._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:174
GaudiConfig.ControlFlow.OrNode.rhs
rhs
Definition: ControlFlow.py:118
GaudiConfig.ControlFlow.AndNode.__init__
def __init__(self, lhs, rhs)
Definition: ControlFlow.py:100
GaudiConfig.ControlFlow._TestAlgorithm
Definition: ControlFlow.py:205
GaudiConfig.ControlFlow.ControlFlowNode
Definition: ControlFlow.py:8
GaudiConfig.ControlFlow.ControlFlowNode._fullname
_fullname
Definition: ControlFlow.py:53
GaudiConfig.ControlFlow.par.__repr__
def __repr__(self)
Definition: ControlFlow.py:160
GaudiConfig.ControlFlow.InvertNode._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:138
GaudiKernel.Configurable
Definition: Configurable.py:1
GaudiConfig.ControlFlow.ControlFlowNode.__and__
def __and__(self, rhs)
Definition: ControlFlow.py:12
GaudiConfig.ControlFlow.DotVisitor.is_needed
def is_needed(self, visitee)
Definition: ControlFlow.py:274
GaudiConfig.ControlFlow.ControlFlowNode.getFullName
def getFullName(self)
Definition: ControlFlow.py:43
GaudiConfig.ControlFlow.OrderedNode.lhs
lhs
Definition: ControlFlow.py:85
Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
GaudiConfig.ControlFlow.ignore.__repr__
def __repr__(self)
Definition: ControlFlow.py:149
GaudiConfig.ControlFlow.ignore.__init__
def __init__(self, item)
Definition: ControlFlow.py:146
GaudiConfig.ControlFlow.ControlFlowBool
Definition: ControlFlow.py:64
GaudiConfig.ControlFlow.test
def test()
Definition: ControlFlow.py:298
GaudiConfig.ControlFlow.ControlFlowLeaf
Definition: ControlFlow.py:57
GaudiConfig.ControlFlow.OrderedNode.__init__
def __init__(self, lhs, rhs)
Definition: ControlFlow.py:84
GaudiConfig.ControlFlow.AndNode.__repr__
def __repr__(self)
Definition: ControlFlow.py:104
GaudiConfig.ControlFlow.seq.__init__
def __init__(self, item)
Definition: ControlFlow.py:168
GaudiConfig.ControlFlow.InvertNode.__repr__
def __repr__(self)
Definition: ControlFlow.py:135
GaudiConfig.ControlFlow.DotVisitor.leave
def leave(self, visitee)
Definition: ControlFlow.py:256
GaudiConfig.ControlFlow.ControlFlowNode._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:37
GaudiConfig.ControlFlow.par._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:163
GaudiConfig.ControlFlow._TestAlgorithm._name
_name
Definition: ControlFlow.py:207
GaudiConfig.ControlFlow.AndNode.rhs
rhs
Definition: ControlFlow.py:102
GaudiConfig.ControlFlow.ignore._visitSubNodes
def _visitSubNodes(self, visitor)
Definition: ControlFlow.py:152
GaudiConfig.ControlFlow.ControlFlowNode.__eq__
def __eq__(self, other)
Definition: ControlFlow.py:40
GaudiConfig.ControlFlow._TestAlgorithm.name
def name(self)
Definition: ControlFlow.py:212
GaudiConfig.ControlFlow.DotVisitor.nodes
nodes
Definition: ControlFlow.py:218