BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
DynamicDataProvider.cpp
Go to the documentation of this file.
5#include <unordered_map>
6#include <algorithm>
7#include <ranges>
8
9
10using namespace BPMNOS::Model;
11
12DynamicDataProvider::DynamicDataProvider(const std::string& modelFile, const std::string& instanceFileOrString)
13 : DynamicDataProvider(modelFile,{},instanceFileOrString)
14{
15}
16
17DynamicDataProvider::DynamicDataProvider(const std::string& modelFile, const std::vector<std::string>& folders, const std::string& instanceFileOrString)
18 : DataProvider(modelFile,folders)
19 , reader( CSVReader(instanceFileOrString) )
20{
21 earliestInstantiation = std::numeric_limits<BPMNOS::number>::max();
22 latestInstantiation = std::numeric_limits<BPMNOS::number>::min();
24}
25
27 enum {PROCESS_ID, INSTANCE_ID, ATTRIBUTE_ID, VALUE, DISCLOSURE};
28
30 if ( table.empty() ) {
31 throw std::runtime_error("DynamicDataProvider: table '" + reader.instanceFileOrString + "' is empty");
32 }
33
34 for (auto &row : table | std::views::drop(1)) { // assume a single header line
35 if ( row.empty() ) {
36 continue;
37 }
38 if ( row.size() != 5 ) {
39 throw std::runtime_error("DynamicDataProvider: illegal number of cells");
40 }
41/*
42 std::string processId = row[PROCESS_ID].get();
43 // find process with respective identifier
44 auto processIt = std::find_if(
45 model->processes.begin(),
46 model->processes.end(),
47 [&processId](const std::unique_ptr<BPMN::Process>& process) { return process->id == processId;}
48 );
49 if ( processIt == model->processes.end() ) {
50 throw std::runtime_error("DynamicDataProvider: model has no process '" + processId + "'");
51 }
52
53 // TODO: populate globalValueMap!!!
54 auto process = processIt->get();
55
56 auto instanceId = (long unsigned int)BPMNOS::to_number( row[INSTANCE_ID].get(), STRING );
57 // find instance with respective identifier
58 if ( !instances.contains(instanceId) ) {
59 // row has first entry for instance, create new entry in data
60 instances[instanceId] = DynamicInstanceData({process,instanceId,{},{}});
61 }
62
63 auto& instance = instances[instanceId];
64 auto instanceAtribute = attributes[process][Keyword::Instance];
65 if ( auto it = instance.data.find( instanceAtribute );
66 it == instance.data.end()
67 ) {
68 // instance attribute is assumed to be known, even if instantiation is disclosed later
69 instance.data[ instanceAtribute ] = { { std::numeric_limits<BPMNOS::number>::min(), instanceId } };
70 }
71
72 std::string attributeId = row[ATTRIBUTE_ID].get();
73
74 if ( attributeId == "" ) {
75 // no attribute provided in this row
76 continue;
77 }
78
79 if ( !attributes[process].contains(attributeId) ) {
80 throw std::runtime_error("DynamicDataProvider: process '" + processId + "' has no node with attribute '" + attributeId + "'");
81 }
82
83 auto attribute = attributes[process][attributeId];
84 BPMNOS::number disclosure = BPMNOS::to_number(row[DISCLOSURE].get(),INTEGER);
85 BPMNOS::number value = BPMNOS::to_number(row[VALUE].get(),attribute->type);
86 auto &attributeData = instance.data[ attribute ];
87 if ( attributeData.size() && attributeData.back().first >= disclosure ) {
88 throw std::runtime_error("DynamicDataProvider: disclosures of attribute values must be provided in strictly increasing order");
89 }
90 instance.data[ attribute ].push_back({ disclosure, value });
91
92 if ( attribute->index == BPMNOS::Model::ExtensionElements::Index::Timestamp ) {
93 if ( instance.instantiation.size() && instance.instantiation.back().first >= disclosure ) {
94 throw std::runtime_error("DynamicDataProvider: disclosures of timestamp values must be provided in strictly increasing order");
95 }
96 if ( instance.instantiation.size() && instance.instantiation.back().first >= instance.instantiation.back().second ) {
97 throw std::runtime_error("DynamicDataProvider: disclosures of anticipated timestamps must be strictly smaller than the timestamp value");
98 }
99 instance.instantiation.push_back({ disclosure, value });
100 }
101*/
102 }
103 for (auto& [id, instance] : instances) {
104 auto& instantiation = instance.instantiation.back().second;
105
106 if ( earliestInstantiation > instantiation ) {
107 earliestInstantiation = instantiation;
108 }
109 if ( latestInstantiation < instantiation ) {
110 latestInstantiation = instantiation;
111 }
112 }
113}
114
115std::unique_ptr<Scenario> DynamicDataProvider::createScenario(unsigned int scenarioId) {
116 std::unique_ptr<Scenario> scenario = std::make_unique<Scenario>(model.get(), earliestInstantiation, latestInstantiation, attributes, globalValueMap, scenarioId);
117 for ( auto& [id, instance] : instances ) {
118 if ( instance.instantiation.size() ) {
119 // instances become known at last disclosure of the instantiation
120 auto& [instantiationDisclosure, instantiationTime] = instance.instantiation.back();
121 scenario->addInstance(instance.process, id, { {}, {{instantiationDisclosure, instantiationTime}} });
122 for ( auto& [disclosure, value] : instance.instantiation ) {
123 scenario->addAnticipation( scenario->getInstantiationData(id), {disclosure, value} );
124 }
125 }
126
127 for ( auto& [attribute, data] : instance.data ) {
128 for ( auto& [disclosure, value] : data ) {
129 // add anticipation of attribute value
130 scenario->addAnticipation( scenario->getAttributeData(id, attribute), {disclosure, value} );
131 }
132
133 if ( data.size() ) {
134 // use last given attribute data as realization
135 auto& [disclosure, value] = data.back();
136 scenario->setRealization( scenario->getAttributeData(id, attribute), {disclosure, value} );
137 }
138 else {
139 // no attribute data given, use default value as realization at time
140// TODO
141// scenario->setRealization( scenario->getAttributeData(id, attribute), {earliestInstantiation, attribute->value} );
142 }
143
144 }
145 }
146 return scenario;
147}
std::vector< Row > Table
Definition CSVReader.h:17
const std::string instanceFileOrString
Definition CSVReader.h:21
Abstract base class representing a data provider for BPMN instance data.
DataInput attributes
Map holding all attributes in the model with keys being the process (or nullptr for global attributes...
std::unique_ptr< Model > model
Pointer to the BPMN model.
Class representing a data provider for dynamic BPMN instance data.
std::unordered_map< const Attribute *, BPMNOS::number > globalValueMap
DynamicDataProvider(const std::string &modelFile, const std::string &instanceFileOrString)
Constructor for DynamicDataProvider.
std::unique_ptr< Scenario > createScenario(unsigned int scenarioId=0) override
std::unordered_map< long unsigned int, DynamicInstanceData > instances