BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
GreedyDispatcher.cpp
Go to the documentation of this file.
1#include "GreedyDispatcher.h"
3#include <limits>
4#include <cassert>
5//#include <iostream>
6
7using namespace BPMNOS::Execution;
8
9template <typename... WeakPtrs>
11 : evaluator(evaluator)
12{
13 if ( !evaluator ) {
14 throw std::runtime_error("GreedyDispatcher: missing evaluator");
15 }
16 timestamp = std::numeric_limits<BPMNOS::number>::lowest();
17}
18
19template <typename... WeakPtrs>
21 mediator->addSubscriber(this,
23 );
25}
26
27template <typename... WeakPtrs>
28void GreedyDispatcher<WeakPtrs...>::addEvaluation(WeakPtrs... weak_ptrs, std::shared_ptr<Decision> decision, std::optional<double> reward) {
29//std::cerr << reward.value_or(-999) << std::endl;
30 // decisions without reward are assumed to be infeasible
31 evaluatedDecisions.emplace( (reward.has_value() ? (double)reward.value() : std::numeric_limits<double>::max() ), weak_ptrs..., decision->weak_from_this());
32
33//std::cerr << "GreedyDispatcher: evaluated decision: " << decision->jsonify() << " with " << reward.value_or(-999) << std::endl;
34 assert ( decision );
36 // add evaluation to respective container
37 if ( !decision->timeDependent && decision->dataDependencies.empty() ) {
38//std::cerr << "GreedyDispatcher: Decision is invariant"<< std::endl;
39 invariantEvaluations.emplace_back(weak_ptrs..., std::move(decision) );
40 }
41 else if ( decision->timeDependent && decision->dataDependencies.empty() ) {
42//std::cerr << "GreedyDispatcher: Decision is time dependent" << std::endl;
43 timeDependentEvaluations.emplace_back(weak_ptrs..., std::move(decision) );
44 }
45 else if ( !decision->timeDependent && decision->dataDependencies.size() ) {
46 assert(decision->token);
47 BPMNOS::number instanceId = decision->token->owner->root->instance.value();
48//std::cerr << "GreedyDispatcher: Decision is data dependent for instance " << BPMNOS::to_string(instanceId,STRING) << std::endl;
49 dataDependentEvaluations[(long unsigned int)instanceId].emplace_back(weak_ptrs..., std::move(decision) );
50 }
51 else if ( decision->timeDependent && decision->dataDependencies.size() ) {
52 assert(decision->token);
53 BPMNOS::number instanceId = decision->token->owner->root->instance.value();
54//std::cerr << "GreedyDispatcher: Decision is time and data dependent for instance " << BPMNOS::to_string(instanceId,STRING) << std::endl;
55 timeAndDataDependentEvaluations[(long unsigned int)instanceId].emplace_back(weak_ptrs..., std::move(decision) );
56 }
57}
58
59template <typename... WeakPtrs>
60std::shared_ptr<Event> GreedyDispatcher<WeakPtrs...>::dispatchEvent( [[maybe_unused]] const SystemState* systemState ) {
61//std::cout << "dispatchEvent" << std::endl;
62 if ( systemState->currentTime > timestamp ) {
63 timestamp = systemState->currentTime;
64 clockTick();
65 }
66
67 for ( auto& decisionTuple : decisionsWithoutEvaluation ) {
68// std::apply([this](auto&&... args) { this->evaluate(std::forward<decltype(args)>(args)...); }, decisionTuple);
69 std::apply([this,&decisionTuple](auto&&... args) {
70 auto decision = std::get<std::shared_ptr<Decision>>(decisionTuple);
71 assert(decision);
72 // Call decision->evaluate() and add the evaluation
73 auto evaluation = decision->evaluate();
74 this->addEvaluation(std::forward<decltype(args)>(args)..., evaluation);
75 }, decisionTuple);
76 }
77 decisionsWithoutEvaluation.clear();
78
79 for ( auto decisionTuple : evaluatedDecisions ) {
80 std::weak_ptr<Event>& event_ptr = std::get<sizeof...(WeakPtrs)+1>(decisionTuple);
81//std::cerr << "\nBest decision " << event_ptr.lock()->jsonify() << " evaluated with " << std::get<0>(decisionTuple) << std::endl;
82 return event_ptr.lock();
83 }
84
85 return nullptr;
86}
87
88template <typename... WeakPtrs>
90//std::cerr << "GreedyDispatcher:noticed event" << std::endl;
91 if ( observable->getObservableType() == Observable::Type::DataUpdate ) {
92 dataUpdate(static_cast<const DataUpdate*>(observable));
93 }
94}
95
96template <typename... WeakPtrs>
97bool GreedyDispatcher<WeakPtrs...>::intersect(const std::vector<const BPMNOS::Model::Attribute*>& first, const std::set<const BPMNOS::Model::Attribute*>& second) const {
98 for ( auto lhs : first ) {
99 if ( second.contains(lhs) ) {
100 return true;
101 }
102 }
103 return false;
104};
105
106template <typename... WeakPtrs>
107void GreedyDispatcher<WeakPtrs...>::removeObsolete(const DataUpdate* update, auto_list< WeakPtrs..., std::shared_ptr<Decision> >& evaluation, auto_list< WeakPtrs..., std::shared_ptr<Decision> >& unevaluatedDecisions) {
108 // check whether evaluation has become obsolete
109 for ( auto it = evaluation.begin(); it != evaluation.end(); ) {
110 auto& decisionTuple = *it;
111 std::shared_ptr<Decision>& decision = std::get<sizeof...(WeakPtrs)>(decisionTuple);
112 if ( intersect(update->attributes, decision->dataDependencies) ) {
113 decision->evaluation = std::nullopt;
114 std::apply([&unevaluatedDecisions](auto&&... args) { unevaluatedDecisions.emplace_back(std::forward<decltype(args)>(args)...); }, decisionTuple);
115 // remove evaluation
116//std::cerr << "GreedyDispatcher: Remove evaluation of decision: " << decision->jsonify() << std::endl;
117 it = evaluation.erase(it);
118 }
119 else {
120 ++it;
121 }
122 }
123};
124
125template <typename... WeakPtrs>
126void GreedyDispatcher<WeakPtrs...>::removeDependentEvaluations(const DataUpdate* update, std::unordered_map< long unsigned int, auto_list< WeakPtrs..., std::shared_ptr<Decision> > >& evaluatedDecisions, auto_list< WeakPtrs..., std::shared_ptr<Decision> >& unevaluatedDecisions) {
127 if ( update->instanceId >= 0 ) {
128 // find instance that data update refers to
129 if ( auto it = evaluatedDecisions.find((long unsigned int)update->instanceId);
130 it != evaluatedDecisions.end()
131 ) {
132 removeObsolete(update,it->second,unevaluatedDecisions);
133 }
134 }
135 else {
136 // update of global value may influence evaluatedDecisions of all instances
137 for ( auto it = evaluatedDecisions.begin(); it != evaluatedDecisions.end(); ++it) {
138 removeObsolete(update,it->second,unevaluatedDecisions);
139 }
140 }
141 };
142
143
144template <typename... WeakPtrs>
146 removeDependentEvaluations(update,dataDependentEvaluations,decisionsWithoutEvaluation);
147 removeDependentEvaluations(update,timeAndDataDependentEvaluations,decisionsWithoutEvaluation);
148}
149
150template <typename... WeakPtrs>
152 for ( auto& decisionTuple : timeDependentEvaluations ) {
153 std::shared_ptr<Decision>& decision = std::get<sizeof...(WeakPtrs)>(decisionTuple);
154 decision->evaluation = std::nullopt;
155 std::apply([this](auto&&... args) { this->decisionsWithoutEvaluation.emplace_back(std::forward<decltype(args)>(args)...); }, decisionTuple);
156 }
157
158 timeDependentEvaluations.clear();
159
160 for ( auto& [ instance, evaluations ] : timeAndDataDependentEvaluations ) {
161 for ( auto& decisionTuple : evaluations ) {
162 std::shared_ptr<Decision>& decision = std::get<sizeof...(WeakPtrs)>(decisionTuple);
163 decision->evaluation = std::nullopt;
164 std::apply([this](auto&&... args) { this->decisionsWithoutEvaluation.emplace_back(std::forward<decltype(args)>(args)...); }, decisionTuple);
165 }
166 }
167 timeAndDataDependentEvaluations.clear();
168}
169
170template class BPMNOS::Execution::GreedyDispatcher< std::weak_ptr<const Token>, std::weak_ptr<const DecisionRequest> >;
171template class BPMNOS::Execution::GreedyDispatcher< std::weak_ptr<const Token>, std::weak_ptr<const DecisionRequest>, std::weak_ptr<const Message> >;
172
173
174
Represents an abstract base class for a pending Evaluator.
Definition Evaluator.h:15
virtual void connect(Mediator *mediator)
Class for dispatching the event with the best evaluation.
std::shared_ptr< Event > dispatchEvent(const SystemState *systemState) override
virtual void dataUpdate(const DataUpdate *update)
void removeDependentEvaluations(const DataUpdate *update, std::unordered_map< long unsigned int, auto_list< WeakPtrs..., std::shared_ptr< Decision > > > &evaluatedDecisions, auto_list< WeakPtrs..., std::shared_ptr< Decision > > &unevaluatedDecisions)
void addEvaluation(WeakPtrs..., std::shared_ptr< Decision > decision, std::optional< double > reward)
void notice(const Observable *observable) override
void connect(Mediator *mediator) override
void removeObsolete(const DataUpdate *update, auto_list< WeakPtrs..., std::shared_ptr< Decision > > &evaluation, auto_list< WeakPtrs..., std::shared_ptr< Decision > > &unevaluatedDecisions)
bool intersect(const std::vector< const BPMNOS::Model::Attribute * > &first, const std::set< const BPMNOS::Model::Attribute * > &second) const
void addSubscriber(Observer *subscriber, ObservableTypes... observableTypes)
Definition Notifier.h:16
A class representing the state that the execution or simulation of a given scenario is in.
Definition SystemState.h:21
List of tuples with automatic removal of tuples containing an expired weak_ptr.
Definition auto_list.h:15
BPMNOS_NUMBER_TYPE number
Definition Number.h:42
const std::vector< const BPMNOS::Model::Attribute * > & attributes
Definition DataUpdate.h:17
const BPMNOS::number instanceId
Definition DataUpdate.h:16
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