BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
SeededController.cpp
Go to the documentation of this file.
1#include "SeededController.h"
8//#include <iostream>
9
10using namespace BPMNOS::Execution;
11
13 : config(std::move(config))
14 , flattenedGraph(flattenedGraph)
15{
16 // initialize seed
17 seed.resize( flattenedGraph->vertices.size() );
18 std::iota(seed.begin(), seed.end(), 1);
19
21}
22
24 Controller::connect(mediator);
25}
26
32
33bool SeededController::setSeed(const std::vector<size_t> initialSeed) {
34 seed = std::move(initialSeed);
35 if ( seed.size() < flattenedGraph->vertices.size() ) {
36 return false;
37 }
39
40 return true;
41}
42
43std::list< const SeededController::Vertex* >::iterator SeededController::finalizeVertexPosition(const Vertex* vertex) {
44// assert( std::ranges::contains(pendingVertices,vertex) );
45//std::cerr << "finalizeVertexPosition " << vertex->reference() << std::endl;
46 auto it = std::find(pendingVertices.begin(), pendingVertices.end(), vertex);
47 if( it == pendingVertices.end() ) {
48 return pendingVertices.end();
49 }
50
51//std::cerr << "Removed " << vertex->reference() << " from " << pendingVertices.size() << std::endl;
52 processedVertices.push_back(vertex);
53 return pendingVertices.erase(it);
54
55};
56
57void SeededController::fetchPendingPredecessors(std::unordered_set<const Vertex*>& predecessors, const Vertex* vertex) const {
58 for ( auto& [_,predecessor] : vertex->inflows ) {
59//std::cerr << predecessor.reference() << "/" << predecessors.contains(&predecessor) << "/" << std::ranges::contains(pendingVertices,&predecessor) << std::endl;
60 if ( !predecessors.contains(predecessor) && std::ranges::contains(pendingVertices,predecessor) ) {
61//std::cerr << "Added " << predecessor.reference() << std::endl;
62 predecessors.emplace(predecessor);
63 fetchPendingPredecessors(predecessors,predecessor);
64 }
65 }
66 for ( auto predecessor : vertex->predecessors ) {
67 if ( !predecessors.contains(predecessor) && std::ranges::contains(pendingVertices,predecessor) ) {
68//std::cerr << "Added " << predecessor.reference() << std::endl;
69 predecessors.emplace(predecessor);
70 fetchPendingPredecessors(predecessors,predecessor);
71 }
72 }
73}
74
76 std::unordered_set<const Vertex*> pendingPredecessors;
77 fetchPendingPredecessors(pendingPredecessors,vertex);
78//std::cerr << "finalize " << pendingPredecessors.size() << " predecessor positions: " << vertex->reference() << std::endl;
79
80 auto it = pendingPredecessors.begin();
81 while ( it != pendingPredecessors.end() ) {
82 const Vertex* predecessor = *it;
83 if ( !std::ranges::contains(pendingVertices,predecessor) ) {
84 pendingPredecessors.erase(it);
85 it = pendingPredecessors.begin();
86 continue;
87 }
88//std::cerr << "other: " << predecessor->reference() << std::endl;
89 if ( !hasPendingPredecessor(predecessor) ) {
90 if ( flattenedGraph->dummies.contains(predecessor) ) {
91 assert( std::ranges::contains(pendingVertices,predecessor) );
92 finalizeVertexPosition( predecessor );
93 }
94 else if ( predecessor->type == Vertex::Type::ENTRY ) {
95 assert( std::ranges::contains(pendingVertices,predecessor) );
96 finalizeUnvisited( predecessor );
97 }
98 pendingPredecessors.erase(it);
99 it = pendingPredecessors.begin();
100 }
101 else {
102 it++;
103 }
104 }
105
106//std::cerr << "finalizedPredecessorPositions" << vertex->reference() << std::endl;
107}
108
110 assert( vertex == entry(vertex) );
111 std::list<const Vertex*> successors;
112 for ( auto successor : vertex->successors ) {
113 if ( successor == entry(successor) ) {
114 successors.push_back(successor);
115 }
116 }
117 auto it = successors.begin();
118 while ( it != successors.end() ) {
119 assert( std::ranges::contains(pendingVertices,*it) );
120 if ( !hasPendingPredecessor(*it) ) {
121 assert( std::ranges::contains(pendingVertices,*it) );
122 finalizeUnvisited( *it );
123 successors.erase(it);
124 it = successors.begin();
125 }
126 else {
127 it++;
128 }
129 }
130}
131
132std::list< const SeededController::Vertex* >::iterator SeededController::finalizeUnvisited(const Vertex* vertex) {
133 assert( vertex == entry(vertex) );
134 auto it = finalizeVertexPosition(vertex);
135 assert( it != pendingVertices.end() );
136
137 auto finalizeExit = [&]() {
138 if (vertex->node->represents<BPMN::Scope>()) {
140 }
142 };
143
144
145 if ( it == pendingVertices.begin() ) {
146 finalizeExit();
147 it = pendingVertices.begin(); // may have changed
148 }
149 else {
150 it--;
151 finalizeExit();
152 it++;
153 }
154
155 return it;
156}
157
158
160 if ( terminationEvent ) {
161 return;
162 }
163
164//std::cerr << "Finalize position(s): " << token->jsonify() << std::endl;
165 if ( token->state == Token::State::BUSY ) {
166//std::cerr << "ignore busy: " << token->jsonify() << std::endl;
167 return;
168 }
169
170 if ( token->state == Token::State::FAILED ) {
171 terminationEvent = std::make_shared<TerminationEvent>();
172 }
173
174 if ( token->node && token->state == Token::State::WITHDRAWN && token->node->represents<BPMN::TypedStartEvent>() ) {
175 if ( auto vertex = flattenedGraph->getVertex(token) ) {
176//std::cerr << "clear withdrawn start event: " << vertex->reference() << std::endl;
177 assert( std::ranges::contains(pendingVertices,entry(vertex)) );
178 finalizeUnvisited(entry(vertex));
179 }
180 }
181
182 if ( token->state == Token::State::ENTERED ) {
183 if ( withdrawableEntry(token->node) ) {
184//std::cerr << "ignore withdrawable entry: " << token->jsonify() << std::endl;
185 return;
186 }
187
188 if ( auto vertex = flattenedGraph->getVertex(token) ) {
191 if (
192 vertex->entry<BPMN::UntypedStartEvent>() ||
193 vertex->entry<BPMN::Gateway>() ||
194 ( vertex->entry<BPMN::ThrowEvent>() && !vertex->entry<BPMN::SendTask>() )
195 ) {
196//std::cerr << "clear instantaneous exit: " << token->jsonify() << std::endl;
199 }
200 }
201 }
202 else if ( token->node && token->state == Token::State::COMPLETED && token->node->represents<BPMN::TypedStartEvent>() ) {
203 auto vertex = flattenedGraph->getVertex(token);
204 assert( vertex );
205 assert( vertex->exit<BPMN::TypedStartEvent>() );
209 }
210 else if (
211 ( !token->node && token->state == Token::State::COMPLETED ) ||
212 ( token->node && token->node->represents<BPMN::Scope>() && token->state == Token::State::COMPLETED )
213 ) {
214//std::cerr << "Scope completed" << std::endl;
215 // Scope is completed, all pending predecessors are not visited
216 auto vertex = flattenedGraph->getVertex(token);
217 assert( vertex );
218 assert( vertex == exit(vertex) );
220 }
221 else if (
222 ( !token->node && token->state == Token::State::DONE ) // Process
223 ) {
224 auto vertex = flattenedGraph->getVertex(token);
225 assert( vertex );
228 }
229 else if (
230 token->node &&
231 (
232 ( // Activity
233 token->state == Token::State::EXITING &&
235 ) ||
236 (
237 token->state == Token::State::COMPLETED &&
238 token->node->represents<BPMN::CatchEvent>() &&
240 )
241 )
242 ) {
243 if ( auto vertex = flattenedGraph->getVertex(token) ) {
244 if ( !token->node->incoming.empty() && token->node->incoming.front()->source->represents<BPMN::EventBasedGateway>() ) {
245 // unvisit all other events
246 auto entryVertex = entry(vertex);
247 assert( vertex->exit<BPMN::CatchEvent>() );
248 auto gateway = entryVertex->inflows.front().second;
249 for ( auto& [ _, target ] : gateway->outflows ) {
250 if ( target != entryVertex ) {
251 assert( std::ranges::contains(pendingVertices,target) );
252 finalizeUnvisited( target );
253 }
254 }
255 }
258//std::cerr << "cleared exit event: " << vertex->reference() << std::endl;
259 }
260 }
261//std::cerr << "check state" << std::endl;
262
263 if ( !token->node && token->state != Token::State::ENTERED && token->state != Token::State::DONE ) {
264 // token at process, but with irrelevant state
265 return;
266 }
267 if ( token->node && token->state != Token::State::ENTERED && token->state != Token::State::EXITING ) {
268 // token at flow node, but with irrelevant state
269 return;
270 }
271 if ( token->node && token->state != Token::State::COMPLETED && token->node->represents<BPMN::TypedStartEvent>() ) {
272 // token at typed start event, but not triggered
273 return;
274 }
275}
276
277void SeededController::notice(const Observable* observable) {
278//std::cerr << "notice" << std::endl;
279 Controller::notice(observable);
280
282//std::cerr << "synchronizeSolution" << std::endl;
283 synchronizeSolution( static_cast<const Token*>(observable) );
284//std::cerr << "synchronizedSolution" << std::endl;
285 }
287 auto performerToken = static_cast<const SequentialPerformerUpdate*>(observable)->token;
288//std::cerr << "SequentialPerformerUpdate: " << performerToken->jsonify() << (performerToken->performing ? " is busy" : " is idle") << std::endl;
289 if ( performerToken->performing ) {
290 performing[ entry(flattenedGraph->getVertex(performerToken)) ] = entry(flattenedGraph->getVertex(performerToken->performing));
291 }
292 else {
293 performing[ entry(flattenedGraph->getVertex(performerToken)) ] = nullptr;
294 }
295 }
296//std::cerr << "noticed" << std::endl;
297}
298
300//std::cerr << "initialize " << seed.size() << " pending vertices " << &model << std::endl;
301 terminationEvent.reset();
302 pendingVertices.clear();
303 processedVertices.clear();
304 performing.clear();
305
306 std::list<Vertex*> vertices;
307 for ( auto index : seed ) {
308 vertices.push_back( flattenedGraph->vertices[ index - 1 ].get() ); // seed indices start at 1
309 }
310 while ( vertices.size() ) {
311 for ( auto it = vertices.begin(); it != vertices.end(); it++ ) {
312 auto vertex = *it;
313 bool hasPendingPredecessor = false;
314 for ( auto& [_,predecessor] : vertex->inflows ) {
315 if ( !std::ranges::contains(pendingVertices,predecessor) ) {
317 break;
318 }
319 }
320 for ( auto predecessor : vertex->predecessors ) {
321 if ( !std::ranges::contains(pendingVertices,predecessor) ) {
323 break;
324 }
325 }
326 if ( !hasPendingPredecessor ) {
327 pendingVertices.push_back( vertex );
328 vertices.erase(it);
329 break;
330 }
331 }
332 }
333}
334
336 if ( vertex == pendingVertices.front() ) {
337 return false;
338 }
339 for ( auto& [_,predecessor] : vertex->inflows ) {
340 if ( vertex == exit(predecessor) && vertex->exit<BPMN::TypedStartEvent>() ) {
341 continue;
342 }
343 if ( !std::ranges::contains(processedVertices,predecessor) ) {
344//std::cerr << predecessor.reference() << " precedes " << vertex->reference() << std::endl;
345 return true;
346 }
347 }
348 for ( auto predecessor : vertex->predecessors ) {
349 if ( !std::ranges::contains(processedVertices,predecessor) ) {
350//std::cerr << predecessor.reference() << " precedes " << vertex->reference() << std::endl;
351 return true;
352 }
353 }
354 return false;
355}
356
358 if ( !node ) return false;
359
360 auto catchEvent = node->represents<BPMN::CatchEvent>();
361
362 return (
363 catchEvent && (
364 catchEvent->represents<BPMN::TypedStartEvent>() ||
365 ( !catchEvent->incoming.empty() && catchEvent->incoming.front()->source->represents<BPMN::EventBasedGateway>() )
366 )
367 );
368}
369
370
371std::list< const SeededController::Vertex* >::iterator SeededController::finalizeUnvisitedTypedStartEvents(std::list< const Vertex* >::iterator it) {
372 auto node = (*it)->node;
373 auto parentEntry = (*it)->parent.value().first;
374
375 auto it2 = it;
376 // find first iterator to vertex at other node
377 it = std::find_if_not(it, pendingVertices.end(), [&](auto other) {
378 return (node == other->node && parentEntry == other->parent.value().first );
379 });
380
381 // finalize message start events that are not visited
382 while ( it2 != pendingVertices.end() ) {
383 if ( (*it2)->type == Vertex::Type::EXIT && node == (*it2)->node && parentEntry == (*it2)->parent.value().first ) {
384//std::cerr << "unvisit: " << (*it2)->shortReference() << std::endl;
385 assert( std::ranges::contains(pendingVertices,entry(*it2)) );
386 it2 = finalizeUnvisited(entry(*it2));
387 }
388 else {
389 it2++;
390 }
391 }
392 return it;
393}
394
396 assert( vertex->exit<BPMN::SendTask>() );
397 for ( auto recipient : entry(vertex)->recipients ) {
398 if ( std::ranges::contains(pendingVertices,recipient) ) {
399 return true;
400 }
401 }
402//std::cerr << vertex->reference() << " has no pending recipient " << entry(vertex)->recipients.size() << std::endl;
403 return false;
404}
405
406std::shared_ptr<Event> SeededController::dispatchEvent(const SystemState* systemState) {
407//std::cerr << "dispatchEvent" << std::endl;
408 if ( terminationEvent ) {
409 return terminationEvent;
410 }
411
412 // when dispatchEvent is called all tokens have been advanced as much as possible
413 // non-decision vertices may only be pending if they are visited and must wait for
414 // the respective event, e.g. timer event, completion event
415
416 auto getRequest = [](const Vertex* vertex, const auto& pendingDecisions) -> DecisionRequest* {
417 for (const auto& [token_ptr, request_ptr] : pendingDecisions) {
418 if (auto request = request_ptr.lock()) {
419//std::cerr << request->token->jsonify() << "/" << vertex->reference() << std::endl;
420 if (
421 request->token->node == vertex->node &&
422 request->token->data->at(BPMNOS::Model::ExtensionElements::Index::Instance).get().value() == vertex->instanceId
423 ) {
424 return request.get();
425 }
426 }
427 }
428 return nullptr;
429 };
430
431 auto waitingForSequentialPerformer = [&](const Vertex* vertex) -> bool {
432 assert( vertex->parent.has_value() );
433 assert( performing.contains(vertex->performer()) );
434 if ( auto other = performing.at(vertex->performer()) ) {
435 return other != entry(vertex);
436 }
437 return false;
438 };
439
440 auto hasRequest = [&](const Vertex* vertex) -> DecisionRequest* {
441 if ( vertex->type == Vertex::Type::ENTRY ) {
442 return getRequest(vertex,systemState->pendingEntryDecisions);
443 }
444 if (auto request = getRequest(vertex, systemState->pendingExitDecisions)) {
445 return request;
446 }
447 if (auto request = getRequest(vertex, systemState->pendingMessageDeliveryDecisions)) {
448 return request;
449 }
450 if (auto request = getRequest(vertex, systemState->pendingChoiceDecisions)) {
451 return request;
452 }
453 return nullptr;
454 };
455
456 auto createEvent = [&](const Vertex* vertex, DecisionRequest* request) -> std::shared_ptr<Event> {
457 std::shared_ptr<Event> event;
458 using enum RequestType;
459 if ( request->type == EntryRequest ) {
460 event = createEntryEvent( systemState, request->token, vertex);
461 }
462 else if ( request->type == ExitRequest ) {
463 event = createExitEvent( systemState, request->token, vertex);
464 }
465 else if ( request->type == MessageDeliveryRequest ) {
466 event = createMessageDeliveryEvent( systemState, request->token, vertex);
467 }
468 else if ( request->type == ChoiceRequest ) {
469 event = createChoiceEvent( systemState, request->token, vertex);
470 }
471 else {
472 assert(!"Unexpected request type");
473 }
474 return event;
475 };
476//std::cerr << pendingVertices.size() << " pending vertices" << std::endl;
477
478 auto it = pendingVertices.begin();
479 while ( it != pendingVertices.end() ) {
480 auto vertex = *it;
481//std::cerr << "Pending: " << vertex->reference() << std::endl;
482 if (
483 hasPendingPredecessor(vertex) &&
484 !(
485 vertex->type == Vertex::Type::EXIT &&
486 withdrawableEntry( vertex->node ) &&
488 )
489 ) {
490//std::cerr << "Postpone (pending predecessor): " << vertex->reference() << std::endl;
491 // postpone vertex because a predecessor has not yet been processed
492 it++;
493 continue;
494 }
495 else if ( flattenedGraph->dummies.contains(vertex) ) {
496 // vertex is dummy
497//std::cerr << "Dummy: " << vertex->reference() << std::endl;
498 it = finalizeVertexPosition(vertex);
499 continue;
500 }
501 else if (
502 vertex->type == Vertex::Type::ENTRY &&
503 withdrawableEntry( vertex->node )
504 ) {
505//std::cerr << "Ignore: " << vertex->reference() << std::endl;
506 // ignore vertex and proceed with exit
507 it++;
508 continue;
509 }
510 else if (
511 vertex->type == Vertex::Type::EXIT &&
512 withdrawableEntry( vertex->node ) &&
514 ) {
515//std::cerr << "Postpone (pending predecessor): " << vertex->reference() << std::endl;
516 // postpone vertex because a predecessor has not yet been processed
517 it++;
518 continue;
519 }
520 else if ( auto request = hasRequest(vertex) ) {
521//std::cerr << "Request: " << request->token->jsonify() << std::endl;
522 if ( auto event = createEvent(vertex,request) ) {
523//std::cerr << "Event: " << vertex->reference() << std::endl;
524 return event;
525 }
526 else {
527//std::cerr << "Postpone (infeasible): " << vertex->reference() << std::endl;
528 // postpone vertex because there is no feasible way to process
529 it++;
530 continue;
531 }
532 }
533 else if ( vertex->exit<BPMN::SendTask>() ) {
534 if ( hasPendingRecipient(vertex) ) {
535//std::cerr << "Postpone (send task): " << vertex->reference() << std::endl;
536 // postpone vertex because there is no feasible way to process
537 it++;
538 continue;
539 }
540 else {
541//std::cerr << "Failed (send task): " << vertex->reference() << std::endl;
542 // ensure send task follows last position
543 finalizeVertexPosition( vertex );
544 // terminate as no solution exists
545 return std::make_shared<TerminationEvent>();
546 }
547 }
548 else if ( vertex->exit<BPMN::MessageStartEvent>() ) {
549 // all there is no request
550//std::cerr << "Postpone (message start): " << vertex->reference() << std::endl;
551 // postpone vertex because a predecessor has not yet been processed
552 it++;
553 continue;
554 }
555 else if ( vertex->entry<BPMN::Process>() ) {
556 // wait for process to start
557//std::cerr << "Wait: " << vertex->jsonify() << std::endl;
558 return nullptr;
559 }
560 else if ( vertex->exit<BPMN::TypedStartEvent>() ) {
561 // wait for trigger
562//std::cerr << "Wait: " << vertex->jsonify() << std::endl;
563 return nullptr;
564 }
565 else if (
566 vertex->node->represents<BPMN::Activity>() &&
568 waitingForSequentialPerformer( vertex )
569 ) {
570//std::cerr << "Postpone (sequential activity): " << vertex->reference() << std::endl;
571 // ignore vertex at sequential activity because performer is busy with other activity
572 it++;
573 continue;
574 }
575 else if (
576 vertex->exit<BPMN::Activity>() &&
577 !vertex->node->represents<BPMN::ReceiveTask>() &&
579 ) {
580 assert(!std::ranges::contains(pendingVertices,entry(vertex)));
581//std::cerr << "Wait for completion: " << vertex->jsonify() << std::endl;
582 // wait for activity to be completed
583 return nullptr;
584 }
585 else if (
586 vertex->exit<BPMN::TimerCatchEvent>() &&
588 ) {
589//std::cerr << "Wait for trigger: " << vertex->jsonify() << std::endl;
590 // wait for timer to be triggered
591 return nullptr;
592 }
593 else {
594 // postpone vertex because it has no predecessors, no request, and does not incur waiting
595 it++;
596 continue;
597 }
598 }
599 if ( !pendingVertices.empty() && it == pendingVertices.end() ) {
600 // none of the pending decision requests is feasible, and the only
601 // way for one to become feasible would be by changing the timestamp.
602 // - entry request: we can assume a timer event to preceed
603 // - exit request: for a task we can assume that the duration of the activity
604 // to be set appropriately, for subprocesses we can assume a timer event
605 // to be used
606 // - choice request: we can assume that a feasible choice must always exist
607 // - message delivery request: we can assume that the feasibility of a message
608 // delivery is not time-dependent
609//std::cerr << processedVertices.size() << "/" << pendingVertices.size() << " - Terminate: " << pendingVertices.front()->reference() << std::endl;
610 return std::make_shared<TerminationEvent>();
611 }
612 return nullptr;
613}
614
615std::vector<size_t> SeededController::getSequence() const {
616 std::vector<size_t> sequence;
617 sequence.reserve(processedVertices.size() + pendingVertices.size());
618
619 for ( auto vertex : processedVertices ) {
620 assert( vertex == flattenedGraph->vertices[vertex->index].get() );
621 sequence.push_back( vertex->index + 1 );
622//std::cerr << vertex->reference() << std::endl;
623 }
624
625 for ( auto vertex : pendingVertices ) {
626 assert( vertex == flattenedGraph->vertices[vertex->index].get() );
627 sequence.push_back( vertex->index + 1 );
628//std::cerr << vertex->reference() << std::endl;
629 }
630
631 return sequence;
632}
633
635 return processedVertices.size();
636}
637
void notice(const Observable *observable) override
virtual void connect(Mediator *mediator)
Definition Controller.cpp:9
std::vector< Vertex * > successors
Container holding predecessors according to the execution logic (excl. sequence flows)
std::vector< std::pair< const BPMN::SequenceFlow *, Vertex * > > inflows
Parent vertices.
std::vector< Vertex * > predecessors
Container holding vertices connecting by an outgoing sequence flow, for loop activities the sequence ...
const Vertex * performer() const
Container holding all entry vertices of nodes owning at least one data attribute.
std::optional< std::pair< Vertex *, Vertex * > > parent
Represents a graph containing all BPMN nodes that may receive a token during execution of a scenario.
std::unordered_set< const Vertex * > dummies
Container holding entry and exit vertices of each possible instantiation of a node.
const Vertex * getVertex(const Token *token) const
Method returning true if the vertex modifies a global attribute.
std::vector< std::unique_ptr< Vertex > > vertices
Returns a topologically sorted vector of all vertices reachable from the initial vertices.
void addSubscriber(Observer *subscriber, ObservableTypes... observableTypes)
Definition Notifier.h:17
std::list< constVertex * >::iterator finalizeUnvisitedTypedStartEvents(std::list< const Vertex * >::iterator it)
bool withdrawableEntry(const BPMN::Node *node) const
Method finalizing the sequence position of a unvisited vertices belonging to typed start events.
void synchronizeSolution(const Token *token)
const FlattenedGraph * flattenedGraph
const Vertex * entry(const Vertex *vertex) const
Method creating a message delivery event.
virtual std::shared_ptr< Event > createChoiceEvent(const SystemState *systemState, const Token *token, const Vertex *vertex)=0
Method creating a choice event.
virtual std::shared_ptr< Event > createExitEvent(const SystemState *systemState, const Token *token, const Vertex *vertex)=0
Method creating a choice event.
void finalizePredecessorPositions(const Vertex *vertex)
std::list< const Vertex * > pendingVertices
void initializePendingVertices()
Method returning the number of processed vertices.
void fetchPendingPredecessors(std::unordered_set< const Vertex * > &predecessors, const Vertex *vertex) const
bool setSeed(const std::vector< size_t > initialSeed)
size_t getProgress() const
Method providing the vertex sequence in the solution.
void notice(const Observable *observable) override
std::unordered_map< const Vertex *, const Vertex * > performing
std::vector< size_t > getSequence() const
Method return true if a token entering a catch event node may be withdrawn.
std::shared_ptr< Event > dispatchEvent(const SystemState *systemState)
virtual std::shared_ptr< Event > createEntryEvent(const SystemState *systemState, const Token *token, const Vertex *vertex)=0
Method creating an initial sequence of vertices.
bool hasPendingRecipient(const Vertex *vertex) const
std::shared_ptr< TerminationEvent > terminationEvent
std::list< const Vertex * > processedVertices
The list of vertices to be processed.
const Vertex * exit(const Vertex *vertex) const
std::list< constVertex * >::iterator finalizeVertexPosition(const Vertex *vertex)
std::list< constVertex * >::iterator finalizeUnvisited(const Vertex *vertex)
Method finalizing the sequence position of a pending vertex and removing it from the list.
void finalizeUnvisitedChildren(const Vertex *vertex)
SeededController(const BPMNOS::Execution::FlattenedGraph *flattenedGraph, Config config=default_config())
virtual std::shared_ptr< Event > createMessageDeliveryEvent(const SystemState *systemState, const Token *token, const Vertex *vertex)=0
Method creating a choice event.
bool hasPendingPredecessor(const Vertex *vertex) const
The list of vertices already processed.
A class representing the state that the execution or simulation of a given scenario is in.
Definition SystemState.h:21
auto_list< std::weak_ptr< Token >, std::weak_ptr< DecisionRequest > > pendingEntryDecisions
Definition SystemState.h:66
auto_list< std::weak_ptr< Token >, std::weak_ptr< DecisionRequest > > pendingExitDecisions
Definition SystemState.h:68
auto_list< std::weak_ptr< Token >, std::weak_ptr< DecisionRequest > > pendingMessageDeliveryDecisions
Definition SystemState.h:69
auto_list< std::weak_ptr< Token >, std::weak_ptr< DecisionRequest > > pendingChoiceDecisions
Definition SystemState.h:67
Represents a token running through a (sub)process.
Definition Token.h:35
const BPMN::FlowNode * node
Definition Token.h:46
Class representing a task in which one or more choices have to be made.
Class representing adhoc subprocesses with sequential ordering.
T * get()
Casts the element to the specified type T.
Definition bpmn++.h:16322
Scope * parent
Reference to the parent node.
Definition bpmn++.h:16592
T * as()
Casts the element to the specified type T.
Definition bpmn++.h:16253
T * represents()
Attempts to cast the element to the specified type T.
Definition bpmn++.h:16236
std::vector< SequenceFlow * > incoming
Vector containing all incoming sequence flows of the node.
Definition bpmn++.h:16703
Base class for all nodes in a BPMN model.
Definition bpmn++.h:16444
Base class for BPMN elements that may contain a ChildNode elements.
Definition bpmn++.h:16510
Base class for all start events with an event definition.
Definition bpmn++.h:16880
STL namespace.
Represents a pending decision.
Represents an abstract base class for a class that is an event listener and notifier.
Definition Mediator.h:13
virtual constexpr Type getObservableType() const =0