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