Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DeterministicSparseTransitionParser.cpp
Go to the documentation of this file.
2
3#include <clocale>
4#include <string>
5
15
16namespace storm {
17namespace parser {
18
19using namespace storm::utility::cstring;
20
21template<typename ValueType>
26
27template<typename ValueType>
28template<typename MatrixValueType>
33
34template<typename ValueType>
35template<typename MatrixValueType>
37 std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix) {
38 // Enforce locale where decimal point is '.'.
39 setlocale(LC_NUMERIC, "C");
40
41 // Open file.
42 MappedFile file(filename.c_str());
43 char const* buf = file.getData();
44
45 // Perform first pass, i.e. count entries that are not zero.
48
49 STORM_LOG_TRACE("First pass on " << filename << " shows " << firstPass.numberOfNonzeroEntries << " non-zeros.");
50
51 // If first pass returned zero, the file format was wrong.
52 if (firstPass.numberOfNonzeroEntries == 0) {
53 STORM_LOG_ERROR("Error while parsing " << filename << ": empty or erroneous file format.");
54 throw storm::exceptions::WrongFormatException();
55 }
56
57 // Perform second pass.
58
59 // Skip the format hint if it is there.
60 buf = trimWhitespaces(buf);
61 if (buf[0] < '0' || buf[0] > '9') {
62 buf = forwardToLineEnd(buf);
63 buf = trimWhitespaces(buf);
64 }
65
66 if (isRewardFile) {
67 // The reward matrix should match the size of the transition matrix.
68 if (firstPass.highestStateIndex + 1 > transitionMatrix.getRowCount() || firstPass.highestStateIndex + 1 > transitionMatrix.getColumnCount()) {
69 STORM_LOG_ERROR("Reward matrix has more rows or columns than transition matrix.");
70 throw storm::exceptions::WrongFormatException() << "Reward matrix has more rows or columns than transition matrix.";
71 } else {
72 // If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
73 firstPass.highestStateIndex = transitionMatrix.getRowCount() - 1;
74 }
75 }
76
77 // Creating matrix builder here.
78 // The actual matrix will be build once all contents are inserted.
80 firstPass.numberOfNonzeroEntries);
81
82 uint_fast64_t row, col, lastRow = 0;
83 double val;
84 bool dontFixDeadlocks = storm::settings::getModule<storm::settings::modules::BuildSettings>().isDontFixDeadlocksSet();
85 bool hadDeadlocks = false;
86
87 // Read all transitions from file. Note that we assume that the
88 // transitions are listed in canonical order, otherwise this will not
89 // work, i.e. the values in the matrix will be at wrong places.
90
91 // Different parsing routines for transition systems and transition rewards.
92 if (isRewardFile) {
93 while (buf[0] != '\0') {
94 // Read next transition.
95 row = checked_strtol(buf, &buf);
96 col = checked_strtol(buf, &buf);
97 val = checked_strtod(buf, &buf);
98
99 resultMatrix.addNextValue(row, col, val);
100 buf = trimWhitespaces(buf);
101 }
102 } else {
103 // Read first row and add self-loops if necessary.
104 char const* tmp;
105 row = checked_strtol(buf, &tmp);
106
107 if (row > 0) {
108 for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
109 hadDeadlocks = true;
110 if (!dontFixDeadlocks) {
111 resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
112 STORM_LOG_WARN("Warning while parsing " << filename << ": state " << skippedRow
113 << " has no outgoing transitions. A self-loop was inserted.");
114 } else {
115 STORM_LOG_ERROR("Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
116 // Before throwing the appropriate exception we will give notice of all deadlock states.
117 }
118 }
119 }
120
121 while (buf[0] != '\0') {
122 // Read next transition.
123 row = checked_strtol(buf, &buf);
124 col = checked_strtol(buf, &buf);
125 val = checked_strtod(buf, &buf);
126
127 // Test if we moved to a new row.
128 // Handle all incomplete or skipped rows.
129 if (lastRow != row) {
130 for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
131 hadDeadlocks = true;
132 if (!dontFixDeadlocks) {
133 resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
134 STORM_LOG_INFO("Warning while parsing " << filename << ": state " << skippedRow
135 << " has no outgoing transitions. A self-loop was inserted.");
136 } else {
137 STORM_LOG_ERROR("Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
138 // Before throwing the appropriate exception we will give notice of all deadlock states.
139 }
140 }
141 lastRow = row;
142 }
143
144 resultMatrix.addNextValue(row, col, val);
145 buf = trimWhitespaces(buf);
146 }
147
148 // If we encountered deadlock and did not fix them, now is the time to throw the exception.
149 if (dontFixDeadlocks && hadDeadlocks)
150 throw storm::exceptions::WrongFormatException() << "Some of the states do not have outgoing transitions.";
151 }
152
153 // Finally, build the actual matrix, test and return it.
154 storm::storage::SparseMatrix<ValueType> result = resultMatrix.build();
155
156 // Since we cannot check if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to
157 // do it afterwards.
158 if (isRewardFile && !result.isSubmatrixOf(transitionMatrix)) {
159 STORM_LOG_ERROR("There are rewards for non existent transitions given in the reward file.");
160 throw storm::exceptions::WrongFormatException() << "There are rewards for non existent transitions given in the reward file.";
161 }
162
163 return result;
164}
165
166template<typename ValueType>
167typename DeterministicSparseTransitionParser<ValueType>::FirstPassResult DeterministicSparseTransitionParser<ValueType>::firstPass(
168 char const* buf, bool reserveDiagonalElements) {
169 DeterministicSparseTransitionParser<ValueType>::FirstPassResult result;
170
171 // Skip the format hint if it is there.
172 buf = trimWhitespaces(buf);
173 if (buf[0] < '0' || buf[0] > '9') {
174 buf = forwardToLineEnd(buf);
175 buf = trimWhitespaces(buf);
176 }
177
178 // Check all transitions for non-zero diagonal entries and deadlock states.
179 uint_fast64_t row, col, lastRow = 0, lastCol = -1;
180
181 // Read first row and reserve space for self-loops if necessary.
182 char const* tmp;
183 row = checked_strtol(buf, &tmp);
184 if (row > 0 && reserveDiagonalElements) {
185 for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
186 ++result.numberOfNonzeroEntries;
187 }
188 }
189
190 while (buf[0] != '\0') {
191 // Read the transition.
192 row = checked_strtol(buf, &buf);
193 col = checked_strtol(buf, &buf);
194 // The actual read value is not needed here.
195 checked_strtod(buf, &buf);
196
197 if (lastRow != row && reserveDiagonalElements) {
198 // Compensate for missing rows.
199 for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
200 ++result.numberOfNonzeroEntries;
201 }
202 }
203
204 // Check if a higher state id was found.
205 if (row > result.highestStateIndex)
206 result.highestStateIndex = row;
207 if (col > result.highestStateIndex)
208 result.highestStateIndex = col;
209
210 ++result.numberOfNonzeroEntries;
211
212 // Have we already seen this transition?
213 if (row == lastRow && col == lastCol) {
214 STORM_LOG_ERROR("The same transition (" << row << ", " << col << ") is given twice.");
215 throw storm::exceptions::InvalidArgumentException() << "The same transition (" << row << ", " << col << ") is given twice.";
216 }
217
218 lastRow = row;
219 lastCol = col;
220
221 buf = trimWhitespaces(buf);
222 }
223
224 if (reserveDiagonalElements) {
225 for (uint_fast64_t skippedRow = (uint_fast64_t)(lastRow + 1); skippedRow <= result.highestStateIndex; ++skippedRow) {
226 ++result.numberOfNonzeroEntries;
227 }
228 }
229
230 return result;
231}
232
233template class DeterministicSparseTransitionParser<double>;
235 std::string const& filename, storm::storage::SparseMatrix<double> const& transitionMatrix);
236template storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser<double>::parse(std::string const& filename, bool isRewardFile,
237 storm::storage::SparseMatrix<double> const& transitionMatrix);
238
239template class DeterministicSparseTransitionParser<storm::Interval>;
240
242 std::string const& filename, storm::storage::SparseMatrix<double> const& transitionMatrix);
243template storm::storage::SparseMatrix<storm::Interval> DeterministicSparseTransitionParser<storm::Interval>::parse(
244 std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const& transitionMatrix);
245} // namespace parser
246} // namespace storm
This class can be used to parse a file containing either transitions or transition rewards of a deter...
static storm::storage::SparseMatrix< ValueType > parseDeterministicTransitionRewards(std::string const &filename, storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix)
Load the transition rewards for a deterministic transition system from file and create a sparse adjac...
static storm::storage::SparseMatrix< ValueType > parseDeterministicTransitions(std::string const &filename)
Load a deterministic transition system from file and create a sparse adjacency matrix whose entries r...
Opens a file and maps it to memory providing a char* containing the file content.
Definition MappedFile.h:21
A class that can be used to build a sparse matrix by adding value by value.
A class that holds a possibly non-square matrix in the compressed row storage format.
bool isSubmatrixOf(SparseMatrix< OtherValueType > const &matrix) const
Checks if the current matrix is a submatrix of the given matrix, where a matrix A is called a submatr...
index_type getColumnCount() const
Returns the number of columns of the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
#define STORM_LOG_INFO(message)
Definition logging.h:24
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ERROR(message)
Definition logging.h:26
char const * forwardToLineEnd(char const *buffer)
Encapsulates the usage of function @strcspn to forward to the end of the line (next char is the newli...
Definition cstring.cpp:74
double checked_strtod(char const *str, char const **end)
Calls strtod() internally and checks if the new pointer is different from the original one,...
Definition cstring.cpp:39
uint_fast64_t checked_strtol(char const *str, char const **end)
Calls strtol() internally and checks if the new pointer is different from the original one,...
Definition cstring.cpp:21
char const * trimWhitespaces(char const *buf)
Skips spaces, tabs, newlines and carriage returns.
Definition cstring.cpp:66
A structure representing the result of the first pass of this parser.
uint_fast64_t highestStateIndex
The highest state index that appears in the model.
uint_fast64_t numberOfNonzeroEntries
The total number of non-zero entries of the model.