19 reader = std::make_unique<CSVReader>(instanceFileOrString);
25 for (
auto& lookupTable :
model->lookupTables) {
26 auto* table = lookupTable.get();
28 return table->at(args);
39 globals[attribute->index] = value;
42 for (
auto* attribute : expression.
variables) {
44 throw std::runtime_error(
"ExpectedValueDataProvider: expression '" + expressionString +
45 "' references non-global attribute '" + attribute->name +
"'");
49 if (!value.has_value()) {
50 throw std::runtime_error(
"ExpectedValueDataProvider: failed to evaluate expression '" + expressionString +
"'");
58 throw std::runtime_error(
"ExpectedValueDataProvider: table is empty");
60 if (table.size() < 2) {
61 throw std::runtime_error(
"ExpectedValueDataProvider: table must have at least a header and one data row");
64 size_t columnCount = table[0].size();
65 if (columnCount == 3 || columnCount == 4 || columnCount == 6) {
72 throw std::runtime_error(
"ExpectedValueDataProvider: expected 3, 4, or 6 columns, got " + std::to_string(columnCount));
93 enum { INSTANCE_ID, NODE_ID, INITIALIZATION, DISCLOSURE, ARRIVAL, COMPLETION };
95 for (
auto& row : table | std::views::drop(1)) {
96 if (row.empty())
continue;
97 if (row.size() < 3 || row.size() != columnCount) {
98 throw std::runtime_error(
"ExpectedValueDataProvider: inconsistent column count");
102 if (!std::holds_alternative<std::string>(row.at(INSTANCE_ID))) {
103 throw std::runtime_error(
"ExpectedValueDataProvider: illegal instance id");
105 std::string instanceIdentifier = std::get<std::string>(row.at(INSTANCE_ID));
108 if (!std::holds_alternative<std::string>(row.at(NODE_ID))) {
109 throw std::runtime_error(
"ExpectedValueDataProvider: illegal node id");
111 std::string nodeId = std::get<std::string>(row.at(NODE_ID));
114 if (!std::holds_alternative<std::string>(row.at(INITIALIZATION))) {
115 throw std::runtime_error(
"ExpectedValueDataProvider: illegal initialization");
117 std::string initialization = std::get<std::string>(row.at(INITIALIZATION));
123 if (instanceIdentifier.empty() && nodeId.empty()) {
125 if (initialization.empty())
continue;
129 for (
auto& [
id, globalAttribute] :
attributes[
nullptr]) {
130 if (globalAttribute->name == attributeName) {
131 attribute = globalAttribute;
136 throw std::runtime_error(
"ExpectedValueDataProvider: unknown global attribute '" + attributeName +
"'");
141 globals[globalAttribute->index] = value;
145 if (!value.has_value()) {
146 throw std::runtime_error(
"ExpectedValueDataProvider: failed to evaluate global '" + attributeName +
"'");
150 else if (instanceIdentifier.empty()) {
151 throw std::runtime_error(
"ExpectedValueDataProvider: instance id required when node id is provided");
160 throw std::runtime_error(
"ExpectedValueDataProvider: first row for instance must reference a process");
169 if (!initialization.empty()) {
172 if (!extensionElements->attributeRegistry.contains(attributeName)) {
173 throw std::runtime_error(
"ExpectedValueDataProvider: node '" + nodeId +
"' has no attribute '" + attributeName +
"'");
176 if (attribute->expression) {
177 throw std::runtime_error(
"ExpectedValueDataProvider: attribute '" + attributeName +
"' is initialized by expression");
192 auto instantiationTime = instance.data[timestampAttribute];
193 scenario->addInstance(instance.process,
id, instantiationTime);
194 for (
auto& [attribute, value] : instance.data) {
195 scenario->setValue(
id, attribute, value);
void registerFunctions(LIMEX::Handle< double > &handle)
Register all expected value functions with the given LIMEX handle.
DataInput attributes
Map holding all attributes in the model with keys being the process (or nullptr for global attributes...
BPMN::Node * findNode(const std::string &nodeId) const
std::unique_ptr< Model > model
Pointer to the BPMN model.
Data provider that accepts stochastic CSV format but uses expected values.
void initializeExpectedValueHandle()
LIMEX::Handle< double > expectedValueHandle
ExpectedValueDataProvider(const std::string &modelFile, const std::string &instanceFileOrString)
BPMNOS::number evaluateExpression(const std::string &expression) const override
Override to use expectedValueHandle instead of model->limexHandle.
std::unique_ptr< Scenario > createScenario(unsigned int scenarioId=0) override
void readInstancesExtendedFormat(const CSVReader::Table &table, size_t columnCount)
ExpectedValueFactory expectedValueFactory
Class representing a mathematical expression.
std::vector< const Attribute * > variables
Vector containing all input attributes used by the expression.
std::optional< BPMNOS::number > execute(const BPMNOS::Values &status, const DataType &data, const BPMNOS::Values &globals) const
Class holding extension elements representing execution data for nodes.
AttributeRegistry attributeRegistry
Registry allowing to look up all status and data attributes by their names.
Class representing a data provider for static BPMN instance data.
std::pair< std::string, std::string > parseInitialization(const std::string &initialization) const
std::unordered_map< const Attribute *, BPMNOS::number > globalValueMap
BPMNOS::number latestInstantiation
BPMNOS::number earliestInstantiation
std::unique_ptr< CSVReader > reader
std::unordered_map< long unsigned int, StaticInstanceData > instances
void ensureDefaultValue(StaticInstanceData &instance, const std::string attributeId, std::optional< BPMNOS::number > value=std::nullopt)
std::unique_ptr< ExtensionElements > extensionElements
T * represents()
Attempts to cast the element to the specified type T.
Base class for all nodes in a BPMN model.
const std::string Instance
const std::string Timestamp
number to_number(const std::string &valueString, const ValueType &type)
Converts a string to a number.
BPMNOS_NUMBER_TYPE number