The Gaudi Framework
master (53dee381)
Toggle main menu visibility
Loading...
Searching...
No Matches
Validators.cpp
Go to the documentation of this file.
1
/***********************************************************************************\
2
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3
* *
4
* This software is distributed under the terms of the Apache version 2 licence, *
5
* copied verbatim in the file "LICENSE". *
6
* *
7
* In applying this licence, CERN does not waive the privileges and immunities *
8
* granted to it by virtue of its status as an Intergovernmental Organization *
9
* or submit itself to any jurisdiction. *
10
\***********************************************************************************/
11
#include "
Validators.h
"
12
13
#include <algorithm>
14
15
namespace
concurrency
{
16
17
//---------------------------------------------------------------------------
18
bool
NodePropertiesValidator::visit
(
DecisionNode
& node ) {
19
20
if
( node.
m_modeConcurrent
&& node.
m_modePromptDecision
) {
21
22
if
( !
m_foundViolations
)
23
m_status
24
<<
" 'Concurrent'/'Prompt' contradiction(s) found. Settings are mutually exclusive within a task group. "
25
"Discarding 'Prompt' for "
;
26
27
m_status
<< (
m_foundViolations
?
", "
:
""
) << node.
name
();
28
29
if
( !
m_foundViolations
)
m_foundViolations
=
true
;
30
31
return
false
;
32
}
33
34
return
true
;
35
}
36
37
//---------------------------------------------------------------------------
38
bool
ActiveLineageScout::visit
(
DecisionNode
& node ) {
39
40
// Test if this node is already resolved
41
if
(
m_slot
->controlFlowState[node.
getNodeIndex
()] != -1 ) {
42
m_active
=
false
;
43
return
m_active
;
44
}
45
46
// Test if the node that sent this scout is out-of-sequence in this node
47
if
( !node.
m_modeConcurrent
) {
48
49
for
(
auto
& child : node.
getDaughters
() ) {
50
51
if
( child->name() ==
m_previousNodeName
)
break
;
52
53
if
(
m_slot
->controlFlowState[child->getNodeIndex()] == -1 ) {
54
m_active
=
false
;
55
return
m_active
;
56
}
57
}
58
}
59
60
this->
visitParents
( node );
61
62
return
this->
reply
();
63
}
64
65
//---------------------------------------------------------------------------
66
void
ActiveLineageScout::visitParents
(
DecisionNode
& node ) {
67
68
for
(
auto
& parent : node.
m_parents
) {
69
m_active
=
true
;
70
m_previousNodeName
= node.
name
();
71
parent->accept( *
this
);
72
73
// Any active parent means that this node is active
74
if
( this->
reply
() )
break
;
75
}
76
}
77
78
//---------------------------------------------------------------------------
79
void
SubSlotScout::visitParents
(
DecisionNode
& node ) {
80
81
// Leave a sub-slot if this is the exit node
82
const
EventSlot
* oldSlot =
nullptr
;
83
if
(
m_slot
->parentSlot &&
m_slot
->entryPoint == node.
name
() ) {
84
oldSlot =
m_slot
;
85
m_slot
=
m_slot
->parentSlot;
86
m_foundEntryPoint
=
true
;
87
}
88
89
// Examine all parents
90
for
(
auto
& parent : node.
m_parents
) {
91
m_active
=
true
;
92
m_foundEntryPoint
= (
m_slot
->parentSlot == nullptr );
93
m_previousNodeName
= node.
name
();
94
parent->accept( *
this
);
95
96
// Any active parent means that this node is active
97
if
( this->
reply
() )
break
;
98
}
99
100
if
( oldSlot )
m_slot
= oldSlot;
101
}
102
103
//---------------------------------------------------------------------------
104
bool
ConditionalLineageFinder::visit
(
DecisionNode
& node ) {
105
106
auto
propValidator =
NodePropertiesValidator
();
107
propValidator.visit( node );
108
109
// check if the visitor found a conditional path
110
if
( node.
m_modePromptDecision
&& propValidator.passed() ) {
111
m_positive
=
true
;
112
return
true
;
113
}
114
115
// check if the visitor found an unconditional path
116
if
( node.
m_parents
.empty() ) {
117
m_negative
=
true
;
118
return
true
;
119
}
120
121
for
(
const
auto
& parent : node.
m_parents
) {
122
this->
visit
( *parent );
123
// check if a node is on both conditional and unconditional branches
124
// and stop since further navigation won't change the conclusion
125
if
( this->
positive
() && this->
negative
() )
break
;
126
}
127
128
return
true
;
129
}
130
131
//---------------------------------------------------------------------------
132
bool
ConditionalLineageFinder::visit
(
AlgorithmNode
& node ) {
133
134
for
(
const
auto
& parent : node.
getParentDecisionHubs
() ) {
135
this->
visit
( *parent );
136
if
( this->
positive
() && this->
negative
() )
break
;
137
}
138
139
return
true
;
140
}
141
142
//---------------------------------------------------------------------------
143
bool
ProductionAmbiguityFinder::visit
(
DataNode
& node ) {
144
145
if
( node.
getProducers
().size() > 1 ) {
146
147
if
( !
m_foundViolations
)
m_foundViolations
=
true
;
148
149
auto
scout =
ConditionalLineageFinder
();
150
151
for
(
const
auto
& producer : node.
getProducers
() ) {
152
153
producer->accept( scout );
154
155
if
( scout.negative() ) {
156
// register unconditional violation
157
auto
pr =
m_unconditionalProducers
.try_emplace( &node );
158
pr.first->second.insert( producer );
159
}
else
{
160
// register conditional violation
161
auto
pr =
m_conditionalProducers
.try_emplace( &node );
162
pr.first->second.insert( producer );
163
}
164
165
scout.reset();
166
}
167
}
168
169
return
true
;
170
}
171
172
//---------------------------------------------------------------------------
173
bool
ProductionAmbiguityFinder::visit
(
ConditionNode
& node ) {
174
175
if
( node.
getProducers
().size() > 1 ) {
176
177
if
( !
m_foundViolations
)
m_foundViolations
=
true
;
178
179
// all violations related to Condition Node are unconditional as
180
// Condition Algorithms are detached from the CF realm
181
for
(
const
auto
& producer : node.
getProducers
() ) {
182
// register unconditional violation
183
auto
pr =
m_unconditionalProducers
.try_emplace( &node );
184
pr.first->second.insert( producer );
185
}
186
}
187
188
return
true
;
189
}
190
191
//---------------------------------------------------------------------------
192
std::string
ProductionAmbiguityFinder::reply
()
const
{
193
194
std::ostringstream status{
" No topology violations found in the DF realm"
};
195
196
if
(
m_foundViolations
) {
197
status <<
" Conditional (C) and/or unconditional (U) topology violations found in the DF realm:\n\n"
;
198
199
for
(
const
auto
& upr :
m_unconditionalProducers
) {
200
201
// add unconditional violations to the report
202
status <<
" (U): "
<< upr.first->name() <<
" <---- |"
;
203
for
(
const
auto
& algo : upr.second )
204
status <<
" "
<< algo->name() <<
" (U)"
205
<<
" |"
;
206
207
// add conditional violations to the report
208
auto
result =
m_conditionalProducers
.find( upr.first );
209
if
( result !=
m_conditionalProducers
.end() ) {
210
for
(
const
auto
& algo : result->second )
211
status <<
" "
<< algo->name() <<
" (C)"
212
<<
" |"
;
213
}
214
215
status <<
"\n"
;
216
}
217
218
// add remaining conditional violations to the report
219
for
(
const
auto
& cpr :
m_conditionalProducers
) {
220
221
if
(
m_unconditionalProducers
.find( cpr.first ) !=
m_unconditionalProducers
.end() )
continue
;
222
223
status <<
" (C): "
<< cpr.first->name() <<
" <---- |"
;
224
for
(
const
auto
& algo : cpr.second )
225
status <<
" "
<< algo->name() <<
" (C)"
226
<<
" |"
;
227
status <<
"\n"
;
228
}
229
}
230
231
return
status.str();
232
}
233
234
//---------------------------------------------------------------------------
235
bool
TarjanSCCFinder::visit
(
AlgorithmNode
& nodeAt ) {
236
237
// DFS ******************************************************
238
239
// put the node on stack
240
m_stack
.push_back( &nodeAt );
241
242
// initialize and cache the low-link value of this node
243
m_nodes_count
+= 1;
244
unsigned
int
lowlink_init{
m_nodes_count
};
245
// record initial low-link value of this node
246
m_lowlinks
.insert( { &nodeAt, { lowlink_init, lowlink_init } } );
247
auto
& lowlink =
m_lowlinks
[&nodeAt].second;
248
249
for
(
const
auto
& output : nodeAt.
getOutputDataNodes
() ) {
250
for
(
const
auto
& consumer : output->getConsumers() ) {
251
consumer->accept( *
this
);
252
// DFS callback ******************************************
253
// propagate the low-link value back
254
if
(
on_stack
( *consumer ) ) {
255
if
( lowlink >
m_lowlinks
[consumer].second ) lowlink =
m_lowlinks
[consumer].second;
256
// this allows to detect loops (i.e., a cycle consisting of a single algorithm node: A->d->A),
257
// but there is a protection against this case at Algorithm::initialize()
258
if
( consumer == &nodeAt )
m_scc
.insert( { lowlink, { &nodeAt } } );
259
}
260
}
261
}
262
263
// If an SCC is found, book-keep it and take it off the stack
264
if
( lowlink_init == lowlink ) {
265
if
(
m_scc
.find( lowlink ) ==
m_scc
.end() )
m_scc
.insert( { lowlink, {} } );
266
267
for
(
auto
stackNodeRIter =
m_stack
.rbegin(); stackNodeRIter !=
m_stack
.rend(); ++stackNodeRIter ) {
268
269
bool
lastSCCNodeOnStack{ *stackNodeRIter == &nodeAt };
270
if
( lowlink ==
m_lowlinks
[*stackNodeRIter].second )
m_scc
[lowlink].push_back( *stackNodeRIter );
271
272
m_stack
.pop_back();
273
if
( lastSCCNodeOnStack )
break
;
274
}
275
}
276
277
return
true
;
278
}
279
280
//---------------------------------------------------------------------------
281
std::string
TarjanSCCFinder::reply
() {
282
283
if
( !
passed
() ) {
284
285
m_status
<<
" Strongly connected components found in DF realm:"
;
286
287
for
(
auto
& pr :
m_scc
) {
288
if
( pr.second.size() > 1 ) {
289
m_status
<<
"\n o [lowlink:"
<< std::to_string( pr.first ) <<
"] |"
;
290
291
// rotate SCCs to get reproducible order
292
std::vector sortedSCC( pr.second.begin(), pr.second.end() );
293
std::sort( sortedSCC.begin(), sortedSCC.end(),
CompareNodes<AlgorithmNode*>
() );
294
std::rotate( pr.second.begin(), std::find( pr.second.begin(), pr.second.end(), sortedSCC.front() ),
295
pr.second.end() );
296
297
for
(
const
auto
& algoPtr : pr.second )
m_status
<<
" "
<< algoPtr->name() <<
" |"
;
298
}
299
}
300
}
301
302
return
m_status
.str();
303
}
304
305
}
// namespace concurrency
Validators.h
concurrency::ActiveLineageScout::m_slot
const EventSlot * m_slot
Definition
Validators.h:76
concurrency::ActiveLineageScout::m_active
bool m_active
Definition
Validators.h:78
concurrency::ActiveLineageScout::reply
virtual bool reply() const
Definition
Validators.h:71
concurrency::ActiveLineageScout::visit
bool visit(DecisionNode &) override
Definition
Validators.cpp:38
concurrency::ActiveLineageScout::visitParents
virtual void visitParents(DecisionNode &)
Definition
Validators.cpp:66
concurrency::ActiveLineageScout::m_previousNodeName
std::string m_previousNodeName
Definition
Validators.h:79
concurrency::AlgorithmNode
Definition
PrecedenceRulesGraph.h:491
concurrency::AlgorithmNode::getParentDecisionHubs
const std::vector< DecisionNode * > & getParentDecisionHubs() const
Get all parent decision hubs.
Definition
PrecedenceRulesGraph.h:508
concurrency::AlgorithmNode::getOutputDataNodes
const std::vector< DataNode * > & getOutputDataNodes() const
Get all supplier nodes.
Definition
PrecedenceRulesGraph.h:515
concurrency::ConditionNode
Definition
PrecedenceRulesGraph.h:598
concurrency::ConditionalLineageFinder
Definition
Validators.h:106
concurrency::ConditionalLineageFinder::m_positive
bool m_positive
Definition
Validators.h:126
concurrency::ConditionalLineageFinder::m_negative
bool m_negative
Definition
Validators.h:127
concurrency::ConditionalLineageFinder::visit
bool visit(DecisionNode &) override
Definition
Validators.cpp:104
concurrency::ConditionalLineageFinder::positive
bool positive() const
Definition
Validators.h:117
concurrency::ConditionalLineageFinder::negative
bool negative() const
Definition
Validators.h:118
concurrency::ControlFlowNode::getNodeIndex
const unsigned int & getNodeIndex() const
Get node index.
Definition
PrecedenceRulesGraph.h:434
concurrency::ControlFlowNode::name
const std::string & name() const
Get node name.
Definition
PrecedenceRulesGraph.h:436
concurrency::DataNode
Definition
PrecedenceRulesGraph.h:560
concurrency::DataNode::getProducers
const std::vector< AlgorithmNode * > & getProducers() const
Get all data object producers.
Definition
PrecedenceRulesGraph.h:585
concurrency::DecisionNode
Definition
PrecedenceRulesGraph.h:446
concurrency::DecisionNode::getDaughters
const std::vector< ControlFlowNode * > & getDaughters() const
Get children nodes.
Definition
PrecedenceRulesGraph.h:466
concurrency::DecisionNode::m_modeConcurrent
bool m_modeConcurrent
Whether all daughters will be evaluated concurrently or sequentially.
Definition
PrecedenceRulesGraph.h:472
concurrency::DecisionNode::m_modePromptDecision
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
Definition
PrecedenceRulesGraph.h:475
concurrency::DecisionNode::m_parents
std::vector< DecisionNode * > m_parents
Direct parent nodes.
Definition
PrecedenceRulesGraph.h:485
concurrency::NodePropertiesValidator
Definition
Validators.h:27
concurrency::NodePropertiesValidator::visit
bool visit(DecisionNode &) override
Definition
Validators.cpp:18
concurrency::NodePropertiesValidator::m_foundViolations
bool m_foundViolations
Definition
Validators.h:47
concurrency::NodePropertiesValidator::m_status
std::ostringstream m_status
Definition
Validators.h:46
concurrency::ProductionAmbiguityFinder::reply
std::string reply() const
Definition
Validators.cpp:192
concurrency::ProductionAmbiguityFinder::m_unconditionalProducers
visitor_book m_unconditionalProducers
Definition
Validators.h:159
concurrency::ProductionAmbiguityFinder::m_foundViolations
bool m_foundViolations
Definition
Validators.h:154
concurrency::ProductionAmbiguityFinder::m_conditionalProducers
visitor_book m_conditionalProducers
Definition
Validators.h:158
concurrency::ProductionAmbiguityFinder::visit
bool visit(DataNode &) override
Definition
Validators.cpp:143
concurrency::SubSlotScout::reply
bool reply() const override
Definition
Validators.h:97
concurrency::SubSlotScout::visitParents
void visitParents(DecisionNode &) override
Definition
Validators.cpp:79
concurrency::SubSlotScout::m_foundEntryPoint
bool m_foundEntryPoint
Definition
Validators.h:102
concurrency::TarjanSCCFinder::on_stack
bool on_stack(const AlgorithmNode &node) const
Definition
Validators.h:198
concurrency::TarjanSCCFinder::m_nodes_count
unsigned int m_nodes_count
Definition
Validators.h:202
concurrency::TarjanSCCFinder::m_scc
std::map< unsigned int, std::vector< AlgorithmNode * > > m_scc
Definition
Validators.h:205
concurrency::TarjanSCCFinder::m_lowlinks
std::unordered_map< AlgorithmNode *, std::pair< unsigned int, unsigned int > > m_lowlinks
Definition
Validators.h:204
concurrency::TarjanSCCFinder::reply
std::string reply()
Definition
Validators.cpp:281
concurrency::TarjanSCCFinder::passed
bool passed() const
Definition
Validators.h:182
concurrency::TarjanSCCFinder::visit
bool visit(AlgorithmNode &nodeAt) override
Definition
Validators.cpp:235
concurrency::TarjanSCCFinder::m_stack
std::vector< AlgorithmNode * > m_stack
Definition
Validators.h:206
concurrency::TarjanSCCFinder::m_status
std::ostringstream m_status
Definition
Validators.h:208
concurrency
Definition
PrecedenceRulesGraph.cpp:38
EventSlot
Class representing an event slot.
Definition
EventSlot.h:23
concurrency::CompareNodes
Definition
PrecedenceRulesGraph.h:623
GaudiHive
src
PRGraph
Visitors
Validators.cpp
Generated on
for The Gaudi Framework by
1.17.0