3#include <boost/algorithm/string.hpp>
4#include <boost/algorithm/string/predicate.hpp>
25template<
typename ValueType,
typename RewardModelType>
37 bool sawParameters =
false;
38 std::unordered_map<std::string, ValueType> placeholders;
42 std::vector<std::string> rewardModelNames;
43 std::shared_ptr<storm::storage::sparse::ModelComponents<ValueType, RewardModelType>> modelComponents;
47 if (line.empty() || boost::starts_with(line,
"//")) {
51 if (boost::starts_with(line,
"@type: ")) {
53 STORM_LOG_THROW(!sawType, storm::exceptions::WrongFormatException,
"Type declared twice");
57 "Stochastic Two Player Games in DRN format are not supported.");
60 }
else if (line ==
"@parameters") {
62 STORM_LOG_THROW(!sawParameters, storm::exceptions::WrongFormatException,
"Parameters declared twice");
65 std::vector<std::string> parameters;
66 boost::split(parameters, line, boost::is_any_of(
" "));
67 for (std::string
const& parameter : parameters) {
74 }
else if (line ==
"@placeholders") {
77 size_t posColon = line.find(
':');
78 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
"':' not found.");
79 std::string placeName = line.substr(0, posColon - 1);
80 STORM_LOG_THROW(placeName.front() ==
'$', storm::exceptions::WrongFormatException,
"Placeholder must start with dollar symbol $.");
81 std::string valueStr = line.substr(posColon + 2);
82 ValueType value = parseValue(valueStr, placeholders, valueParser);
84 auto ret = placeholders.insert(std::make_pair(placeName.substr(1), value));
85 STORM_LOG_THROW(ret.second, storm::exceptions::WrongFormatException,
"Placeholder '$" << placeName <<
"' was already defined before.");
86 if (file.peek() ==
'@') {
91 }
else if (line ==
"@reward_models") {
93 STORM_LOG_THROW(rewardModelNames.empty(), storm::exceptions::WrongFormatException,
"Reward model names declared twice");
95 boost::split(rewardModelNames, line, boost::is_any_of(
"\t "));
96 }
else if (line ==
"@nr_states") {
98 STORM_LOG_THROW(nrStates == 0, storm::exceptions::WrongFormatException,
"Number states declared twice");
100 nrStates = parseNumber<size_t>(line);
101 }
else if (line ==
"@nr_choices") {
102 STORM_LOG_THROW(nrChoices == 0, storm::exceptions::WrongFormatException,
"Number of actions declared twice");
104 nrChoices = parseNumber<size_t>(line);
105 }
else if (line ==
"@model") {
107 STORM_LOG_THROW(sawType, storm::exceptions::WrongFormatException,
"Type has to be declared before model.");
108 STORM_LOG_THROW(nrStates != 0, storm::exceptions::WrongFormatException,
"No. of states has to be declared before model.");
110 "No. of actions (@nr_choices) has to be declared before model.");
111 STORM_LOG_WARN_COND(nrChoices != 0,
"No. of actions has to be declared. We may continue now, but future versions might not support this.");
113 modelComponents = parseStates(file, type, nrStates, nrChoices, placeholders, valueParser, rewardModelNames, options);
116 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Could not parse line '" << line <<
"'.");
126template<
typename ValueType,
typename RewardModelType>
128 std::istream& file,
storm::models::ModelType type,
size_t stateSize,
size_t nrChoices, std::unordered_map<std::string, ValueType>
const& placeholders,
131 auto modelComponents = std::make_shared<storm::storage::sparse::ModelComponents<ValueType, RewardModelType>>();
132 bool nonDeterministic =
137 modelComponents->observabilityClasses = std::vector<uint32_t>();
138 modelComponents->observabilityClasses->resize(stateSize);
142 std::vector<std::vector<ValueType>> stateRewards;
143 std::vector<std::vector<ValueType>> actionRewards;
144 if (continuousTime) {
145 modelComponents->exitRates = std::vector<ValueType>(stateSize);
152 modelComponents->rateTransitions =
true;
159 uint64_t lineNumber = 0;
160 bool firstState =
true;
161 bool firstActionForState =
true;
164 if (boost::starts_with(line,
"//")) {
171 boost::trim_left(line);
172 if (boost::starts_with(line,
"state ")) {
180 firstActionForState =
true;
182 STORM_LOG_THROW(state <= stateSize, storm::exceptions::WrongFormatException,
"More states detected than declared (in @nr_states).");
185 line = line.substr(6);
186 std::string curString = line;
187 size_t posEnd = line.find(
" ");
188 if (posEnd != std::string::npos) {
189 curString = line.substr(0, posEnd);
190 line = line.substr(posEnd + 1);
194 size_t parsedId = parseNumber<size_t>(curString);
195 STORM_LOG_THROW(state == parsedId, storm::exceptions::WrongFormatException,
196 "In line " << lineNumber <<
" state ids are not ordered and without gaps. Expected " << state <<
" but got " << parsedId <<
".");
197 if (nonDeterministic) {
201 "More actions detected than declared (in @nr_choices).");
204 if (continuousTime) {
206 STORM_LOG_THROW(boost::starts_with(line,
"!"), storm::exceptions::WrongFormatException,
"Exit rate missing in " << lineNumber);
207 line = line.substr(1);
209 posEnd = line.find(
" ");
210 if (posEnd != std::string::npos) {
211 curString = line.substr(0, posEnd);
212 line = line.substr(posEnd + 1);
216 ValueType exitRate = parseValue(curString, placeholders, valueParser);
218 modelComponents->markovianStates.get().set(state);
221 modelComponents->exitRates.get()[state] = exitRate;
225 if (boost::starts_with(line,
"{")) {
226 size_t posEndObservation = line.find(
"}");
227 std::string observation = line.substr(1, posEndObservation - 1);
229 modelComponents->observabilityClasses.value()[state] = std::stoi(observation);
230 line = line.substr(posEndObservation + 1);
232 STORM_LOG_THROW(line.starts_with(
" "), storm::exceptions::WrongFormatException,
233 "Expected whitespace after observation in line " << lineNumber);
235 line = line.substr(1);
238 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Expected an observation for state " << state <<
" in line " << lineNumber);
242 if (boost::starts_with(line,
"[")) {
244 size_t posEndReward = line.find(
']');
245 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing in line " << lineNumber <<
" .");
246 std::string rewardsStr = line.substr(1, posEndReward - 1);
248 std::vector<std::string> rewards;
249 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
250 if (stateRewards.size() < rewards.size()) {
251 stateRewards.resize(rewards.size());
253 auto stateRewardsIt = stateRewards.begin();
254 for (
auto const& rew : rewards) {
255 auto rewardValue = parseValue(rew, placeholders, valueParser);
257 if (stateRewardsIt->empty()) {
258 stateRewardsIt->resize(stateSize, storm::utility::zero<ValueType>());
260 (*stateRewardsIt)[state] = std::move(rewardValue);
264 line = line.substr(posEndReward + 1);
269 std::vector<std::string> labels;
279 std::regex labelRegex(R
"(\"([^\"]+?)\"(?=(\s|$|\"))|([^\s\"]+?(?=(\s|$))))");
282 auto match_begin = std::sregex_iterator(line.begin(), line.end(), labelRegex);
283 auto match_end = std::sregex_iterator();
284 for (std::sregex_iterator i = match_begin;
i != match_end; ++
i) {
285 std::smatch match = *
i;
287 if (match.length(1) > 0) {
288 labels.push_back(match.str(1));
290 labels.push_back(match.str(3));
294 for (std::string
const& label : labels) {
295 if (!modelComponents->stateLabeling.containsLabel(label)) {
296 modelComponents->stateLabeling.addLabel(label);
298 modelComponents->stateLabeling.addLabelToState(label, state);
302 }
else if (boost::starts_with(line,
"action ")) {
304 if (firstActionForState) {
305 firstActionForState =
false;
310 line = line.substr(7);
311 std::string curString = line;
312 size_t posEnd = line.find(
" ");
313 if (posEnd != std::string::npos) {
314 curString = line.substr(0, posEnd);
315 line = line.substr(posEnd + 1);
322 if (curString !=
"__NOLABEL__") {
323 if (!modelComponents->choiceLabeling.value().containsLabel(curString)) {
324 modelComponents->choiceLabeling.value().addLabel(curString);
326 modelComponents->choiceLabeling.value().addLabelToChoice(curString, row);
330 if (boost::starts_with(line,
"[")) {
332 size_t posEndReward = line.find(
']');
333 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing.");
334 std::string rewardsStr = line.substr(1, posEndReward - 1);
336 std::vector<std::string> rewards;
337 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
338 if (actionRewards.size() < rewards.size()) {
339 actionRewards.resize(rewards.size());
341 auto actionRewardsIt = actionRewards.begin();
342 for (
auto const& rew : rewards) {
343 auto rewardValue = parseValue(rew, placeholders, valueParser);
345 if (actionRewardsIt->size() <= row) {
346 actionRewardsIt->resize(std::max(row + 1, stateSize), storm::utility::zero<ValueType>());
348 (*actionRewardsIt)[row] = std::move(rewardValue);
352 line = line.substr(posEndReward + 1);
357 size_t posColon = line.find(
':');
358 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
359 "':' not found in '" << line <<
"' on line " << lineNumber <<
".");
360 size_t target = parseNumber<size_t>(line.substr(0, posColon - 1));
361 std::string valueStr = line.substr(posColon + 2);
362 ValueType value = parseValue(valueStr, placeholders, valueParser);
363 STORM_LOG_TRACE(
"Transition " << row <<
" -> " << target <<
": " << value);
364 STORM_LOG_THROW(target < stateSize, storm::exceptions::WrongFormatException,
365 "In line " << lineNumber <<
" target state " << target <<
" is greater than state size " << stateSize);
370 std::cout <<
"Parsed " << state <<
"/" << stateSize <<
" states before abort.\n";
371 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
378 if (nonDeterministic) {
380 "Number of actions detected (at least " << builder.
getLastRow() + 1 <<
") does not match number of actions declared (" << nrChoices
381 <<
", in @nr_choices).");
385 modelComponents->transitionMatrix = builder.
build(row + 1, stateSize, nonDeterministic ? stateSize : 0);
389 uint64_t numRewardModels = std::max(stateRewards.size(), actionRewards.size());
390 for (uint64_t i = 0;
i < numRewardModels; ++
i) {
391 std::string rewardModelName;
392 if (rewardModelNames.size() <= i) {
393 rewardModelName =
"rew" + std::to_string(i);
395 rewardModelName = rewardModelNames[
i];
397 std::optional<std::vector<ValueType>> stateRewardVector, actionRewardVector;
398 if (i < stateRewards.size() && !stateRewards[i].empty()) {
399 stateRewardVector = std::move(stateRewards[i]);
401 if (i < actionRewards.size() && !actionRewards[i].empty()) {
402 actionRewards[
i].resize(row + 1, storm::utility::zero<ValueType>());
403 actionRewardVector = std::move(actionRewards[i]);
405 modelComponents->rewardModels.emplace(
409 return modelComponents;
412template<
typename ValueType,
typename RewardModelType>
413ValueType DirectEncodingParser<ValueType, RewardModelType>::parseValue(std::string
const& valueStr,
414 std::unordered_map<std::string, ValueType>
const& placeholders,
415 ValueParser<ValueType>
const& valueParser) {
416 if (boost::starts_with(valueStr,
"$")) {
417 auto it = placeholders.find(valueStr.substr(1));
418 STORM_LOG_THROW(it != placeholders.end(), storm::exceptions::WrongFormatException,
"Placeholder " << valueStr <<
" unknown.");
422 return valueParser.parseValue(valueStr);
427template class DirectEncodingParser<double>;
428template class DirectEncodingParser<storm::RationalNumber>;
429template class DirectEncodingParser<storm::RationalFunction>;
430template class DirectEncodingParser<storm::Interval>;
This class manages the labeling of the choice space with a number of (atomic) labels.
This class manages the labeling of the state space with a number of (atomic) labels.
Parser for models in the DRN format with explicit encoding.
static std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > parseModel(std::string const &fil, DirectEncodingParserOptions const &options=DirectEncodingParserOptions())
Load a model in DRN format from a file and create the model.
Parser for values according to their ValueType.
void addParameter(std::string const ¶meter)
Add declaration of parameter.
A bit vector that is internally represented as a vector of 64-bit values.
A class that can be used to build a sparse matrix by adding value by value.
index_type getCurrentRowGroupCount() const
Retrieves the current row group count.
index_type getLastRow() const
Retrieves the most recently used row.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
#define STORM_LOG_INFO(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
std::basic_istream< CharT, Traits > & getline(std::basic_istream< CharT, Traits > &input, std::basic_string< CharT, Traits, Allocator > &str)
Overloaded getline function which handles different types of newline ( and \r).
void closeFile(std::ofstream &stream)
Close the given file after writing.
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.
ModelType getModelType(std::string const &type)
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > buildModelFromComponents(storm::models::ModelType modelType, storm::storage::sparse::ModelComponents< ValueType, RewardModelType > &&components)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
bool isZero(ValueType const &a)