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