Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ParallelComposition.cpp
Go to the documentation of this file.
2
3#include <sstream>
4
5#include <boost/algorithm/string/join.hpp>
6
10
11namespace storm {
12namespace jani {
13
14const std::string SynchronizationVector::NO_ACTION_INPUT = "-";
15
16SynchronizationVector::SynchronizationVector(std::vector<std::string> const& input, std::string const& output) : input(input), output(output) {
17 // Intentionally left empty.
18}
19
20SynchronizationVector::SynchronizationVector(std::vector<std::string> const& input) : input(input), output(storm::jani::Model::SILENT_ACTION_NAME) {}
21
22std::size_t SynchronizationVector::size() const {
23 return input.size();
24}
25
26std::vector<std::string> const& SynchronizationVector::getInput() const {
27 return input;
28}
29
30std::string const& SynchronizationVector::getInput(uint64_t index) const {
31 return input[index];
32}
33std::string const& SynchronizationVector::getOutput() const {
34 return output;
35}
36
37boost::optional<std::string> SynchronizationVector::getPrecedingParticipatingAction(uint64_t index) const {
38 boost::optional<uint64_t> position = getPositionOfPrecedingParticipatingAction(index);
39 if (position) {
40 return getInput(position.get());
41 } else {
42 return boost::none;
43 }
44}
45
46boost::optional<uint64_t> SynchronizationVector::getPositionOfPrecedingParticipatingAction(uint64_t index) const {
47 if (index == 0) {
48 return boost::none;
49 }
50
51 uint64_t i = index - 1;
52 for (; i > 0; --i) {
53 if (this->getInput(i) != NO_ACTION_INPUT) {
54 return boost::make_optional(i);
55 }
56 }
57
58 // Check the 0-index.
59 if (this->getInput(i) != NO_ACTION_INPUT) {
60 return boost::make_optional(i);
61 }
62
63 return boost::none;
64}
65
67 for (uint64_t result = 0; result < this->size(); ++result) {
68 if (this->getInput(result) != NO_ACTION_INPUT) {
69 return result;
70 }
71 }
72 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Synchronization vector must have at least one participating action.");
73}
74
76 uint64_t result = 0;
77 for (auto const& inputEntry : input) {
78 if (!isNoActionInput(inputEntry)) {
79 ++result;
80 }
81 }
82 return result;
83}
84
85bool SynchronizationVector::isNoActionInput(std::string const& action) {
86 return action == NO_ACTION_INPUT;
87}
88
89std::ostream& operator<<(std::ostream& stream, SynchronizationVector const& synchronizationVector) {
90 bool first = true;
91 stream << "(";
92 for (auto const& element : synchronizationVector.getInput()) {
93 if (!first) {
94 stream << ", ";
95 }
96 stream << element;
97 first = false;
98 }
99 stream << ") -> " << synchronizationVector.getOutput();
100 return stream;
101}
102
103bool operator==(SynchronizationVector const& vector1, SynchronizationVector const& vector2) {
104 if (vector1.getOutput() != vector2.getOutput()) {
105 return false;
106 }
107 if (vector1.getInput() != vector1.getInput()) {
108 return false;
109 }
110 return true;
111}
112
113bool operator!=(SynchronizationVector const& vector1, SynchronizationVector const& vector2) {
114 return !(vector1 == vector2);
115}
116
118 STORM_LOG_THROW(vector1.size() == vector2.size(), storm::exceptions::WrongFormatException, "Cannot compare synchronization vectors of different size.");
119 for (uint64_t i = 0; i < vector1.size(); ++i) {
120 if (vector1.getInput(i) < vector2.getInput(i)) {
121 return true;
122 } else if (vector1.getInput(i) > vector2.getInput(i)) {
123 return false;
124 }
125 }
126 if (vector1.getOutput() < vector2.getOutput()) {
127 return true;
128 } else if (vector1.getOutput() > vector2.getOutput()) {
129 return false;
130 }
131 return false;
132}
133
134ParallelComposition::ParallelComposition(std::shared_ptr<Composition> const& subcomposition, std::vector<SynchronizationVector> const& synchronizationVectors)
135 : ParallelComposition(std::vector<std::shared_ptr<Composition>>{subcomposition}, synchronizationVectors) {
136 // Intentionally left empty.
137}
138
139ParallelComposition::ParallelComposition(std::vector<std::shared_ptr<Composition>> const& subcompositions,
140 std::vector<SynchronizationVector> const& synchronizationVectors)
141 : subcompositions(subcompositions), synchronizationVectors(synchronizationVectors) {
142 STORM_LOG_THROW(!subcompositions.empty(), storm::exceptions::WrongFormatException, "At least one automaton required for parallel composition.");
143 this->checkSynchronizationVectors();
144}
145
146ParallelComposition::ParallelComposition(std::vector<std::shared_ptr<Composition>> const& subcompositions, std::set<std::string> const& synchronizationAlphabet)
147 : subcompositions(subcompositions), synchronizationVectors() {
148 STORM_LOG_THROW(!subcompositions.empty(), storm::exceptions::WrongFormatException, "At least one automaton required for parallel composition.");
149
150 // Manually construct the synchronization vectors for all elements of the synchronization alphabet.
151 for (auto const& action : synchronizationAlphabet) {
152 synchronizationVectors.emplace_back(std::vector<std::string>(this->subcompositions.size(), action), action);
153 }
154}
155
156ParallelComposition::ParallelComposition(std::shared_ptr<Composition> const& leftSubcomposition, std::shared_ptr<Composition> const& rightSubcomposition,
157 std::set<std::string> const& synchronizationAlphabet) {
158 subcompositions.push_back(leftSubcomposition);
159 subcompositions.push_back(rightSubcomposition);
160
161 // Manually construct the synchronization vectors for all elements of the synchronization alphabet.
162 for (auto const& action : synchronizationAlphabet) {
163 synchronizationVectors.emplace_back(std::vector<std::string>(this->subcompositions.size(), action), action);
164 }
165}
166
168 return true;
169}
170
172 return *subcompositions[index];
173}
174
175std::vector<std::shared_ptr<Composition>> const& ParallelComposition::getSubcompositions() const {
176 return subcompositions;
177}
178
180 return subcompositions.size();
181}
182
184 return synchronizationVectors[index];
185}
186
187std::vector<SynchronizationVector> const& ParallelComposition::getSynchronizationVectors() const {
188 return synchronizationVectors;
189}
190
192 return synchronizationVectors.size();
193}
194
196 for (uint_fast64_t inputIndex = 0; inputIndex < subcompositions.size(); ++inputIndex) {
197 std::set<std::string> actions;
198 for (auto const& vector : synchronizationVectors) {
199 std::string const& action = vector.getInput(inputIndex);
201 if (actions.find(action) != actions.end()) {
202 return true;
203 }
204 actions.insert(action);
205 }
206 }
207 // And check recursively, in case we have nested parallel composition
208 if (subcompositions.at(inputIndex)->isParallelComposition()) {
209 if (subcompositions.at(inputIndex)->asParallelComposition().areActionsReused()) {
210 return true;
211 }
212 }
213 }
214 return false;
215}
216
217void ParallelComposition::checkSynchronizationVectors() const {
218 for (uint_fast64_t inputIndex = 0; inputIndex < subcompositions.size(); ++inputIndex) {
219 for (auto const& vector : synchronizationVectors) {
220 STORM_LOG_THROW(vector.size() == this->subcompositions.size(), storm::exceptions::WrongFormatException,
221 "Synchronization vectors must match parallel composition size.");
222 }
223 }
224
225 for (auto const& vector : synchronizationVectors) {
226 bool hasInput = false;
227 for (auto const& input : vector.getInput()) {
229 hasInput = true;
230 break;
231 }
232 }
233 STORM_LOG_THROW(hasInput, storm::exceptions::WrongFormatException, "Synchronization vector must have at least one proper input.");
234 }
235}
236
237boost::any ParallelComposition::accept(CompositionVisitor& visitor, boost::any const& data) const {
238 return visitor.visit(*this, data);
239}
240
241void ParallelComposition::write(std::ostream& stream) const {
242 std::vector<std::string> synchronizationVectorsAsStrings;
243 for (auto const& synchronizationVector : synchronizationVectors) {
244 std::stringstream tmpStream;
245 tmpStream << synchronizationVector;
246 synchronizationVectorsAsStrings.push_back(tmpStream.str());
247 }
248
249 bool first = true;
250 bool hasSynchVectors = !synchronizationVectors.empty();
251 stream << "(";
252 for (auto const& subcomposition : subcompositions) {
253 if (!first) {
254 stream << (hasSynchVectors ? " || " : " ||| ");
255 }
256 stream << *subcomposition;
257 first = false;
258 }
259 stream << ")";
260 if (hasSynchVectors) {
261 stream << "[" << boost::algorithm::join(synchronizationVectorsAsStrings, ", ") << "]";
262 }
263}
264
265} // namespace jani
266} // namespace storm
virtual boost::any visit(AutomatonComposition const &composition, boost::any const &data)=0
uint64_t getNumberOfSubcompositions() const
Retrieves the number of subcompositions of this parallel composition.
virtual void write(std::ostream &stream) const override
std::vector< SynchronizationVector > const & getSynchronizationVectors() const
Retrieves the synchronization vectors of the parallel composition.
std::size_t getNumberOfSynchronizationVectors() const
Retrieves the number of synchronization vectors.
SynchronizationVector const & getSynchronizationVector(uint64_t index) const
Retrieves the synchronization vector with the given index.
virtual bool isParallelComposition() const override
std::vector< std::shared_ptr< Composition > > const & getSubcompositions() const
Retrieves the subcompositions of the parallel composition.
virtual boost::any accept(CompositionVisitor &visitor, boost::any const &data) const override
Composition const & getSubcomposition(uint64_t index) const
Retrieves the subcomposition with the given index.
ParallelComposition(std::shared_ptr< Composition > const &subcomposition, std::vector< SynchronizationVector > const &synchronizationVectors)
Creates a parallel composition of the subcomposition and the provided synchronization vectors.
static const std::string NO_ACTION_INPUT
std::vector< std::string > const & getInput() const
uint64_t getPositionOfFirstParticipatingAction() const
Retrieves the position of the first participating action.
boost::optional< std::string > getPrecedingParticipatingAction(uint64_t index) const
Retrieves the action name that is the last participating action before the given input index.
SynchronizationVector(std::vector< std::string > const &input, std::string const &output)
boost::optional< uint64_t > getPositionOfPrecedingParticipatingAction(uint64_t index) const
Retrieves the position of the last participating action before the given input index.
static bool isNoActionInput(std::string const &action)
uint64_t getNumberOfActionInputs() const
Retrieves the number of action inputs, i.e.
std::string const & getOutput() const
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool operator!=(SynchronizationVector const &vector1, SynchronizationVector const &vector2)
bool operator==(SynchronizationVector const &vector1, SynchronizationVector const &vector2)
std::ostream & operator<<(std::ostream &stream, Assignment const &assignment)
LabParser.cpp.
Definition cli.cpp:18
bool operator()(SynchronizationVector const &vector1, SynchronizationVector const &vector2) const