BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
CPController.cpp
Go to the documentation of this file.
1#ifdef USE_CP
2
3#include "CPController.h"
10
11using namespace BPMNOS::Execution;
12
13CPController::CPController(const BPMNOS::Execution::FlattenedGraph* flattenedGraph)
14 : SeededController(flattenedGraph)
15 , constraintProgramm(flattenedGraph)
16{
17}
18
19void CPController::setSolution(CP::Solution sol) {
20 solution = std::make_unique<CP::Solution>(std::move(sol));
21 if (&solution->model != &constraintProgramm.getModel()) {
22 throw std::invalid_argument("CPController: Solution model mismatch");
23 }
24 initializeFromSolution();
25}
26
27void CPController::initializeFromSolution() {
28 // Extract sequence from solution position variables
29 std::vector<size_t> sequence(flattenedGraph->vertices.size());
30 for (size_t i = 0; i < flattenedGraph->vertices.size(); i++) {
31 auto& vertex = flattenedGraph->vertices[i];
32 auto pos = solution->getVariableValue(
33 constraintProgramm.position.at(vertex.get())
34 ).value();
35 sequence[(size_t)pos - 1] = i + 1;
36 }
37 setSeed(sequence);
38}
39
40bool CPController::isVisited(const Vertex* vertex) const {
41 return solution->evaluate(
42 constraintProgramm.visit.at(vertex)
43 ).value_or(false);
44}
45
46BPMNOS::number CPController::getTimestamp(const Vertex* vertex) const {
47 auto result = solution->evaluate(
48 constraintProgramm.status.at(vertex)[BPMNOS::Model::ExtensionElements::Index::Timestamp].value
49 );
50 assert(result.has_value());
51 return result.value();
52}
53
54void CPController::notice(const Observable* observable) {
55 SeededController::notice(observable);
56 if (observable->getObservableType() == Observable::Type::Message) {
57 auto message = static_cast<const Message*>(observable);
58 if (message->state == Message::State::CREATED) {
59 // Get sender vertex from message header (same approach as CPSolutionObserver)
60 auto senderId = message->header[BPMNOS::Model::MessageDefinition::Index::Sender].value();
61 auto& [senderEntry, senderExit] = flattenedGraph->vertexMap.at({senderId, {}, message->origin});
62 messages.emplace_back(message->weak_from_this(), senderEntry);
63 }
64 }
65}
66
67std::shared_ptr<Event> CPController::createEntryEvent(const SystemState* systemState, [[maybe_unused]] const Token* token, const Vertex* vertex) {
68 if (!isVisited(vertex)) {
69 throw std::runtime_error("CPController: Cannot enter unvisited vertex");
70 }
71 if (systemState->getTime() < getTimestamp(vertex)) {
72 return nullptr;
73 }
74 return std::make_shared<EntryEvent>(token);
75}
76
77std::shared_ptr<Event> CPController::createExitEvent(const SystemState* systemState, const Token* token, const Vertex* vertex) {
78 if (!isVisited(vertex)) {
79 throw std::runtime_error("CPController: Cannot exit unvisited vertex");
80 }
81 if (systemState->getTime() < getTimestamp(vertex)) {
82 return nullptr;
83 }
84 return std::make_shared<ExitEvent>(token);
85}
86
87std::shared_ptr<Event> CPController::createChoiceEvent([[maybe_unused]] const SystemState* systemState, const Token* token, const Vertex* vertex) {
88 if (!isVisited(vertex)) {
89 throw std::runtime_error("CPController: Cannot make choice for unvisited vertex");
90 }
91
92 auto extensionElements = token->node->extensionElements->as<BPMNOS::Model::ExtensionElements>();
93
94 // Extract choice values from CP solution status variables
95 std::vector<number> choices;
96 choices.reserve(extensionElements->choices.size());
97
98 auto& statusVars = constraintProgramm.status.at(vertex);
99 for (auto& choice : extensionElements->choices) {
100 auto& attrVars = statusVars[choice->attribute->index];
101 auto value = solution->evaluate(attrVars.value);
102 assert(value.has_value());
103 choices.push_back(value.value());
104 }
105
106 return std::make_shared<ChoiceEvent>(token, std::move(choices));
107}
108
109std::shared_ptr<Event> CPController::createMessageDeliveryEvent([[maybe_unused]] const SystemState* systemState, const Token* token, const Vertex* vertex) {
110 if (!isVisited(vertex)) {
111 throw std::runtime_error("CPController: Cannot deliver message to unvisited vertex");
112 }
113
114 // Find sender from CP solution's messageFlow
115 const Vertex* sender = nullptr;
116 for (auto candidate : vertex->senders) {
117 auto& messageFlowVar = constraintProgramm.messageFlow.at({candidate, vertex});
118 if (solution->evaluate(messageFlowVar).value_or(false)) {
119 sender = candidate;
120 break;
121 }
122 }
123
124 if (!sender) {
125 throw std::runtime_error("CPController: No sender found in solution for message delivery");
126 }
127
128 // Find message from the designated sender vertex
129 for (auto& [message_ptr, senderVertex] : messages) {
130 if (auto message = message_ptr.lock();
131 message && senderVertex == sender)
132 {
133 return std::make_shared<MessageDeliveryEvent>(token, message.get());
134 }
135 }
136
137 // Message not yet available
138 return nullptr;
139}
140
141#endif // USE_CP
Represents a graph containing all BPMN nodes that may receive a token during execution of a scenario.
A controller dispatching decisions in the order derived from a given seed.
A class representing the state that the execution or simulation of a given scenario is in.
Definition SystemState.h:21
BPMNOS::number getTime() const
Function returning the current time.
Represents a token running through a (sub)process.
Definition Token.h:35
const BPMN::FlowNode * node
Definition Token.h:46
Class holding extension elements representing execution data for nodes.
std::unique_ptr< ExtensionElements > extensionElements
Definition bpmn++.h:16299
BPMNOS_NUMBER_TYPE number
Definition Number.h:50
virtual constexpr Type getObservableType() const =0