BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
GreedyEntry.cpp
Go to the documentation of this file.
1#include "GreedyEntry.h"
4#include <cassert>
5
6using namespace BPMNOS::Execution;
7
9 : GreedyDispatcher(evaluator)
10{
11}
12
14 mediator->addSubscriber(this,
16 );
18}
19
20void GreedyEntry::notice(const Observable* observable) {
22 assert( dynamic_cast<const DecisionRequest*>(observable) );
23 auto request = static_cast<const DecisionRequest*>(observable);
24 auto decision = std::make_shared<EntryDecision>(request->token, evaluator);
25 decisionsWithoutEvaluation.emplace_back( request->token->weak_from_this(), request->weak_from_this(), decision );
26 }
27 else {
28 GreedyDispatcher::notice(observable);
29 }
30}
31
32
33std::shared_ptr<Event> GreedyEntry::dispatchEvent( const SystemState* systemState ) {
34//std::cout << "dispatchEvent" << std::endl;
35 if ( systemState->currentTime > timestamp ) {
36 timestamp = systemState->currentTime;
37 clockTick();
38 }
39
40 for (auto it = decisionsWithoutEvaluation.begin(); it != decisionsWithoutEvaluation.end(); ) {
41 auto [ token_ptr, request_ptr, decision ] = std::move(*it);
42 it = decisionsWithoutEvaluation.erase(it);
43 assert(decision);
44 auto token = token_ptr.lock();
45 assert( token );
46 assert( token->node->parent );
47 if ( token->node->parent->represents<BPMNOS::Model::SequentialAdHocSubProcess>() ) {
48 // defer evaluation of decision
50 std::move(token_ptr), std::move(request_ptr), std::move(decision)
51 );
52 }
53 else {
54 // evaluation of decision is independent of others
55 auto reward = decision->evaluate();
56//std::cerr << "Regular: " << decision->jsonify() << std::endl;
57 addEvaluation(token_ptr, request_ptr, decision, reward);
58
59 if ( reward.has_value() ) {
60 // dispatch feasible decision
61 return std::make_shared<EntryEvent>(decision->token);
62 }
63 }
64 }
65
66 // all evaluated decisions are infeasible unless a previously dispatched decision was not deployed
67 for ( auto decisionTuple : evaluatedDecisions ) {
68 constexpr std::size_t last = std::tuple_size<decltype(decisionTuple)>::value - 1;
69 std::weak_ptr<Event>& event_ptr = std::get<last>(decisionTuple);
70 if ( auto event = event_ptr.lock();
71 event && std::get<0>(decisionTuple) < std::numeric_limits<double>::max()
72 ) {
73//std::cerr << "\nBest (old) decision " << event->jsonify() << " evaluated with " << std::get<0>(decisionTuple) << std::endl;
74 // Warning: event is dispatched even if it is no longer the best due to data updates since undeployed dispatch
75 return event;
76 }
77 else {
78 // best evalutated decision is infeasible, no need to inspect others
79 break;
80 }
81 }
82
83 std::unordered_map<const Token*, auto_list<std::weak_ptr<const Token>, std::weak_ptr<const DecisionRequest>, std::shared_ptr<Decision> > > sequentialActivityEntries;
84
85 for (auto& [ token_ptr, request_ptr, decision ] : unevaluatedSequentialEntries ) {
86 assert(decision);
87 auto token = token_ptr.lock();
88 assert( token );
89 assert( token->node->parent );
90 assert( token->node->parent->represents<BPMNOS::Model::SequentialAdHocSubProcess>() );
91 // defer entry decision for sequential activities
92 auto tokenAtSequentialPerformer = token->getSequentialPerformerToken();
93//std::cerr << "Defer: " << token->jsonify() << "/" << sequentialActivityEntries[ tokenAtSequentialPerformer ].empty() << std::endl;
94 sequentialActivityEntries[tokenAtSequentialPerformer].emplace_back(
95 std::move(token_ptr), std::move(request_ptr), std::move(decision)
96 );
97 }
99
100 // now find best activity to be entered for any sequential performer
101 for ( auto& [ performerToken, decisionTuples ] : sequentialActivityEntries ) {
102 assert( !performerToken->performing );
103//std::cerr << "Performer: " << performerToken->jsonify() << std::endl;
104 for ( auto& [ token_ptr, request_ptr, decision ] : decisionTuples ) {
105 // Call decision->evaluate() and add the evaluation
106 auto reward = decision->evaluate();
107//std::cerr << "Exclusive: " << decision->jsonify() << std::endl;
108 addEvaluation(token_ptr, request_ptr, decision, reward);
109 }
110 for ( auto decisionTuple : evaluatedDecisions ) {
111 constexpr std::size_t last = std::tuple_size<decltype(decisionTuple)>::value - 1;
112 std::weak_ptr<Event>& event_ptr = std::get<last>(decisionTuple);
113 if ( auto event = event_ptr.lock();
114 event && std::get<0>(decisionTuple) < std::numeric_limits<double>::max()
115 ) {
116//std::cerr << "\nBest decision " << event->jsonify() << " evaluated with " << std::get<0>(decisionTuple) << std::endl;
117 return event;
118 }
119 else {
120 // best decision is infeasible, proceed with next performer
121 break;
122 }
123 }
124 }
125
126 return nullptr;
127}
128
Represents an abstract base class for an evaluator determining feasibility and reward of a decision.
Definition Evaluator.h:15
Class for dispatching the event with the best evaluation.
void addEvaluation(WeakPtrs..., std::shared_ptr< Decision > decision, std::optional< double > reward)
void notice(const Observable *observable) override
void connect(Mediator *mediator) override
GreedyEntry(Evaluator *evaluator)
void connect(Mediator *mediator) override
auto_list< std::weak_ptr< const Token >, std::weak_ptr< const DecisionRequest >, std::shared_ptr< Decision > > unevaluatedSequentialEntries
Definition GreedyEntry.h:22
void notice(const Observable *observable) override
std::shared_ptr< Event > dispatchEvent(const SystemState *systemState) override
void addSubscriber(Observer *subscriber, ObservableTypes... observableTypes)
Definition Notifier.h:17
A class representing the state that the execution or simulation of a given scenario is in.
Definition SystemState.h:21
BPMNOS::number currentTime
Timestamp holding the point in time that the engine is in (this is usually representing now).
Definition SystemState.h:37
Class representing adhoc subprocesses with sequential ordering.
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