BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
DynamicScenario.cpp
Go to the documentation of this file.
1#include "DynamicScenario.h"
4
5using namespace BPMNOS::Model;
6
7DynamicScenario::DynamicScenario(const Model* model, BPMNOS::number earliestInstantiationTime, BPMNOS::number latestInstantiationTime, const std::unordered_map< const Attribute*, BPMNOS::number >& globalValueMap)
8 : earliestInstantiationTime(earliestInstantiationTime)
9 , latestInstantiationTime(latestInstantiationTime)
10{
11 this->model = model;
12 globals.resize(model->attributes.size());
13 for ( auto& [attribute, value] : globalValueMap ) {
14 globals[attribute->index] = value;
15 }
16}
17
18void DynamicScenario::addInstance(const BPMN::Process* process, const BPMNOS::number instanceId, BPMNOS::number instantiationTime) {
19 instances[(size_t)instanceId] = {process, (size_t)instanceId, instantiationTime, {}};
20}
21
22void DynamicScenario::setValue(const BPMNOS::number instanceId, const Attribute* attribute, std::optional<BPMNOS::number> value) {
23 instances[(size_t)instanceId].values[attribute] = value;
24}
25
26void DynamicScenario::setDisclosure(const BPMNOS::number instanceId, const BPMN::Node* node, BPMNOS::number disclosureTime) {
27 disclosure[(size_t)instanceId][node] = disclosureTime;
28}
29
33
34bool DynamicScenario::isCompleted(const BPMNOS::number currentTime) const {
35 return currentTime > latestInstantiationTime;
36}
37
38std::vector< const Scenario::InstanceData* > DynamicScenario::getCreatedInstances(const BPMNOS::number currentTime) const {
39 std::vector< const Scenario::InstanceData* > result;
40 for ( auto& [id, instance] : instances ) {
41 if ( instance.instantiationTime <= currentTime ) {
42 result.push_back(&instance);
43 }
44 }
45 return result;
46}
47
48std::vector< const Scenario::InstanceData* > DynamicScenario::getKnownInstances([[maybe_unused]] const BPMNOS::number currentTime) const {
49 // All instances are known from the start
50 std::vector< const Scenario::InstanceData* > result;
51 for ( auto& [id, instance] : instances ) {
52 result.push_back(&instance);
53 }
54 return result;
55}
56
57std::vector< std::tuple<const BPMN::Process*, BPMNOS::Values, BPMNOS::Values> > DynamicScenario::getCurrentInstantiations(const BPMNOS::number currentTime) const {
58 std::vector< std::tuple<const BPMN::Process*, BPMNOS::Values, BPMNOS::Values> > result;
59 for ( auto& [id, instance] : instances ) {
60 // Effective instantiation time is max(instantiationTime, processDisclosure).
61 // If process data disclosure is later than instantiation time, instantiation is delayed
62 // until all process data is disclosed.
63 BPMNOS::number effectiveInstantiationTime = instance.instantiationTime;
64 if ( disclosure.contains(instance.id) && disclosure.at(instance.id).contains(instance.process) ) {
65 effectiveInstantiationTime = std::max(effectiveInstantiationTime, disclosure.at(instance.id).at(instance.process));
66 }
67 if ( effectiveInstantiationTime == currentTime ) {
68 auto status = getKnownInitialStatus(&instance, currentTime);
69 // If instantiation was delayed due to disclosure, update timestamp to reflect actual instantiation time
70 if ( effectiveInstantiationTime > instance.instantiationTime ) {
71 status[ExtensionElements::Index::Timestamp] = currentTime;
72 }
73 result.push_back({instance.process, std::move(status), getKnownInitialData(&instance, currentTime)});
74 }
75 }
76 return result;
77}
78
80 BPMNOS::Values result;
81 for ( auto& attribute : instance->process->extensionElements->as<const BPMNOS::Model::ExtensionElements>()->attributes ) {
82 result.push_back( getKnownValue(instance, attribute.get(), currentTime) );
83 }
84 return result;
85}
86
88 BPMNOS::Values result;
89 for ( auto& attribute : instance->process->extensionElements->as<const BPMNOS::Model::ExtensionElements>()->data ) {
90 result.push_back( getKnownValue(instance, attribute.get(), currentTime) );
91 }
92 return result;
93}
94
95std::optional<BPMNOS::number> DynamicScenario::getKnownValue(const Scenario::InstanceData* instance, const BPMNOS::Model::Attribute* attribute, [[maybe_unused]] const BPMNOS::number currentTime) const {
96 // Node-level disclosure is checked by caller (getCurrentInstantiations, getKnownValues, getKnownData)
97 if ( attribute->expression && attribute->expression->type == Expression::Type::ASSIGN ) {
98 // Value is computed from an expression
99 std::vector<double> variableValues;
100 for ( auto input : attribute->expression->variables ) {
101 if ( !input->isImmutable ) {
102 return std::nullopt;
103 }
104 auto value = getKnownValue(instance, input, currentTime);
105 if ( !value.has_value() ) {
106 return std::nullopt;
107 }
108 variableValues.push_back( (double)value.value() );
109 }
110
111 std::vector<std::vector<double>> collectionValues;
112 for ( auto input : attribute->expression->collections ) {
113 if ( !input->isImmutable ) {
114 return std::nullopt;
115 }
116 collectionValues.push_back( {} );
117 auto collection = getKnownValue(instance, input, currentTime);
118 if ( !collection.has_value() ) {
119 return std::nullopt;
120 }
121 for ( auto value : collectionRegistry[(size_t)collection.value()] ) {
122 collectionValues.back().push_back( value );
123 }
124 }
125
126 return number(attribute->expression->compiled.evaluate(variableValues, collectionValues));
127 }
128 else {
129 // Return stored value directly
130 if ( instance->values.contains(attribute) ) {
131 return instance->values.at(attribute);
132 }
133 }
134 return std::nullopt;
135}
136
137std::optional<BPMNOS::number> DynamicScenario::getKnownValue(const BPMNOS::number instanceId, const BPMNOS::Model::Attribute* attribute, const BPMNOS::number currentTime) const {
138 return getKnownValue(&instances.at((size_t)instanceId), attribute, currentTime);
139}
140
141std::optional<BPMNOS::Values> DynamicScenario::getKnownValues(const BPMNOS::number instanceId, const BPMN::Node* node, const BPMNOS::number currentTime) const {
142 auto& instance = instances.at((size_t)instanceId);
143 // Check if node data is disclosed
144 if ( disclosure.contains(instance.id) && disclosure.at(instance.id).contains(node) ) {
145 if ( currentTime < disclosure.at(instance.id).at(node) ) {
146 return std::nullopt;
147 }
148 }
149 Values result;
150 for ( auto& attribute : node->extensionElements->as<const BPMNOS::Model::ExtensionElements>()->attributes ) {
151 result.push_back( getKnownValue(&instance, attribute.get(), currentTime) );
152 }
153 return result;
154}
155
156std::optional<BPMNOS::Values> DynamicScenario::getKnownData(const BPMNOS::number instanceId, const BPMN::Node* node, const BPMNOS::number currentTime) const {
157 auto& instance = instances.at((size_t)instanceId);
158 // Check if node data is disclosed
159 if ( disclosure.contains(instance.id) && disclosure.at(instance.id).contains(node) ) {
160 if ( currentTime < disclosure.at(instance.id).at(node) ) {
161 return std::nullopt;
162 }
163 }
164 Values result;
165 for ( auto& attribute : node->extensionElements->as<const BPMNOS::Model::ExtensionElements>()->data ) {
166 result.push_back( getKnownValue(&instance, attribute.get(), currentTime) );
167 }
168 return result;
169}
170
172 pendingDisclosures[(size_t)instanceId].push_back(std::move(pending));
173}
174
176 for (auto& [instanceId, pendings] : pendingDisclosures) {
177 auto& instance = instances.at(instanceId);
178
179 // Process pending disclosures that are due
180 auto it = pendings.begin();
181 while (it != pendings.end()) {
182 if (currentTime >= it->disclosureTime) {
183 // Reveal pre-computed value
184 instance.values[it->attribute] = it->value;
185 disclosedAttributes.insert({instanceId, it->attribute});
186 it = pendings.erase(it);
187 }
188 else {
189 ++it;
190 }
191 }
192 }
193}
CollectionRegistry collectionRegistry
std::unique_ptr< const Expression > expression
Definition Attribute.h:31
std::optional< BPMNOS::number > getKnownValue(const Scenario::InstanceData *instance, const BPMNOS::Model::Attribute *attribute, const BPMNOS::number currentTime) const override
Method returning a known value of an attribute.
std::unordered_map< size_t, std::vector< PendingDisclosure > > pendingDisclosures
Instance ID -> pending disclosures.
BPMNOS::number getEarliestInstantiationTime() const override
Method returning the time of the earliest instantiation.
std::optional< BPMNOS::Values > getKnownValues(const BPMNOS::number instanceId, const BPMN::Node *node, const BPMNOS::number currentTime) const override
Method returning all known values of new attributes.
void addInstance(const BPMN::Process *process, const BPMNOS::number instanceId, BPMNOS::number instantiationTime)
void revealData(BPMNOS::number currentTime) const
void setValue(const BPMNOS::number instanceId, const Attribute *attribute, std::optional< BPMNOS::number > value)
void setDisclosure(const BPMNOS::number instanceId, const BPMN::Node *node, BPMNOS::number disclosureTime)
std::unordered_map< size_t, std::unordered_map< const BPMN::Node *, BPMNOS::number > > disclosure
Instance ID -> Node -> time when node's data is disclosed.
Values getKnownInitialStatus(const InstanceData *, const BPMNOS::number time) const override
Method returning the initial status attributes for process instantiation.
std::set< std::pair< size_t, const Attribute * > > disclosedAttributes
Track which attributes have been disclosed.
std::vector< const InstanceData * > getKnownInstances(const BPMNOS::number currentTime) const override
Method returning a vector of all instances that have been created or are known for sure until the giv...
std::vector< std::tuple< const BPMN::Process *, BPMNOS::Values, BPMNOS::Values > > getCurrentInstantiations(const BPMNOS::number currentTime) const override
Method returning a vector of all instances that are known to be instantiated at the given time.
bool isCompleted(const BPMNOS::number currentTime) const override
Method returning true if the currentTime exceeds the completion time.
std::optional< BPMNOS::Values > getKnownData(const BPMNOS::number instanceId, const BPMN::Node *node, const BPMNOS::number currentTime) const override
Method returning all known values of new attributes.
void addPendingDisclosure(const BPMNOS::number instanceId, PendingDisclosure &&pending)
std::vector< const InstanceData * > getCreatedInstances(const BPMNOS::number currentTime) const override
Method returning a vector of all instances that have been created until the given time.
DynamicScenario(const Model *model, BPMNOS::number earliestInstantiationTime, BPMNOS::number latestInstantiationTime, const std::unordered_map< const Attribute *, BPMNOS::number > &globalValueMap)
Values getKnownInitialData(const InstanceData *, const BPMNOS::number time) const override
Method returning the initial data attributes for process instantiation.
std::unordered_map< size_t, InstanceData > instances
Class holding extension elements representing execution data for nodes.
std::vector< std::unique_ptr< Attribute > > attributes
Vector containing new status attributes declared for the node.
std::vector< std::unique_ptr< Attribute > > data
Vector containing data attributes declared for data objects within the node's scope.
Represents a BPMN model with all its processes.
Definition Model.h:22
std::vector< std::unique_ptr< Attribute > > attributes
Vector containing new global attributes declared for the model.
Definition Model.h:70
const Model * model
Pointer to the BPMN model.
Definition Scenario.h:148
BPMNOS::Values globals
Definition Scenario.h:144
std::unique_ptr< ExtensionElements > extensionElements
Definition bpmn++.h:16299
Base class for all nodes in a BPMN model.
Definition bpmn++.h:16444
BPMNOS_NUMBER_TYPE number
Definition Number.h:50
Structure representing a pending disclosure.
std::unordered_map< const Attribute *, std::optional< BPMNOS::number > > values
Attribute values.
Definition Scenario.h:27
const BPMN::Process * process
Definition Scenario.h:24