110 bool sawModelType{
false}, sawParameters{
false};
112 if (line.empty() || line.starts_with(
"//")) {
116 if (line.starts_with(
"@type: ")) {
118 STORM_LOG_THROW(!sawModelType, storm::exceptions::WrongFormatException,
"Type declared twice");
122 "Stochastic Two Player Games in DRN format are not supported.");
124 }
else if (line.starts_with(
"@value_type: ")) {
128 }
else if (line ==
"@parameters") {
130 STORM_LOG_THROW(!sawParameters, storm::exceptions::WrongFormatException,
"Parameters declared twice");
133 boost::split(header.
parameters, line, boost::is_any_of(
" "));
135 sawParameters =
true;
136 }
else if (line ==
"@placeholders") {
139 size_t posColon = line.find(
':');
140 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
"':' not found.");
141 std::string placeName = line.substr(0, posColon - 1);
142 STORM_LOG_THROW(placeName.front() ==
'$', storm::exceptions::WrongFormatException,
"Placeholder must start with dollar symbol $.");
143 std::string valueStr = line.substr(posColon + 2);
144 auto ret = header.
placeholders.emplace(placeName.substr(1), valueStr);
145 STORM_LOG_THROW(ret.second, storm::exceptions::WrongFormatException,
"Placeholder '$" << placeName <<
"' was already defined before.");
146 if (file.peek() ==
'@') {
151 }
else if (line ==
"@reward_models") {
156 }
else if (line ==
"@nr_states") {
158 STORM_LOG_THROW(header.
nrStates == 0, storm::exceptions::WrongFormatException,
"Number states declared twice");
160 header.
nrStates = parseNumber<size_t>(line);
161 }
else if (line ==
"@nr_choices") {
162 STORM_LOG_THROW(header.
nrChoices == 0, storm::exceptions::WrongFormatException,
"Number of actions declared twice");
164 header.
nrChoices = parseNumber<size_t>(line);
165 }
else if (line ==
"@model") {
167 STORM_LOG_THROW(sawModelType, storm::exceptions::WrongFormatException,
"Model type has to be declared before model.");
168 STORM_LOG_THROW(header.
nrStates != 0, storm::exceptions::WrongFormatException,
"No. of states has to be declared before model.");
169 STORM_LOG_WARN_COND(header.
nrChoices != 0,
"No. of actions has to be declared. We may continue now, but future versions might not support this.");
177 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Could not parse line '" << line <<
"'.");
181 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Reached end of file before @model was found.");
197std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>>
parseModel(std::istream& file,
DrnHeader const& header,
201 isCompatibleValueType<ValueType>(header.
valueType), storm::exceptions::WrongFormatException,
202 "Value type '" <<
toString(header.
valueType) <<
"' in DRN file is not compatible with output value type '" << valueTypeToString<ValueType>() <<
"'.");
204 << valueTypeToString<ValueType>() <<
"'.");
206 for (std::string
const& parameter : header.
parameters) {
210 std::unordered_map<std::string, ValueType> placeholders;
211 for (
auto const& [placeName, valueStr] : header.
placeholders) {
212 ValueType v =
parseValue(valueStr, placeholders, valueParser);
214 placeholders.emplace(placeName, std::move(v));
216 size_t const nrStates = header.
nrStates;
217 size_t const nrChoices = header.
nrChoices;
227 STORM_LOG_THROW(nrChoices != 0, storm::exceptions::WrongFormatException,
228 "No. of actions (@nr_choices) has to be declared when building a model with choice labeling.");
231 std::vector<std::vector<ValueType>> stateRewards;
232 std::vector<std::vector<ValueType>> actionRewards;
233 if (continuousTime) {
234 modelComponents.
exitRates = std::vector<ValueType>(nrStates);
248 uint64_t lineNumber = 0;
249 bool firstState =
true;
250 bool firstActionForState =
true;
253 if (line.starts_with(
"//")) {
260 boost::trim_left(line);
261 if (line.starts_with(
"state ")) {
269 firstActionForState =
true;
271 STORM_LOG_THROW(state <= nrStates, storm::exceptions::WrongFormatException,
"More states detected than declared (in @nr_states).");
274 line = line.substr(6);
275 std::string curString = line;
276 size_t posEnd = line.find(
" ");
277 if (posEnd != std::string::npos) {
278 curString = line.substr(0, posEnd);
279 line = line.substr(posEnd + 1);
283 size_t parsedId = parseNumber<size_t>(curString);
284 STORM_LOG_THROW(state == parsedId, storm::exceptions::WrongFormatException,
285 "In line " << lineNumber <<
" state ids are not ordered and without gaps. Expected " << state <<
" but got " << parsedId <<
".");
286 if (nonDeterministic) {
290 "More actions detected than declared (in @nr_choices).");
293 if (continuousTime) {
295 STORM_LOG_THROW(line.starts_with(
"!"), storm::exceptions::WrongFormatException,
"Exit rate missing in " << lineNumber);
296 line = line.substr(1);
298 posEnd = line.find(
" ");
299 if (posEnd != std::string::npos) {
300 curString = line.substr(0, posEnd);
301 line = line.substr(posEnd + 1);
305 ValueType exitRate =
parseValue(curString, placeholders, valueParser);
310 modelComponents.
exitRates.get()[state] = exitRate;
314 if (line.starts_with(
"{")) {
315 size_t posEndObservation = line.find(
"}");
316 std::string observation = line.substr(1, posEndObservation - 1);
319 line = line.substr(posEndObservation + 1);
321 STORM_LOG_THROW(line.starts_with(
" "), storm::exceptions::WrongFormatException,
322 "Expected whitespace after observation in line " << lineNumber);
324 line = line.substr(1);
327 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Expected an observation for state " << state <<
" in line " << lineNumber);
331 if (line.starts_with(
"[")) {
333 size_t posEndReward = line.find(
']');
334 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing in line " << lineNumber <<
" .");
335 std::string rewardsStr = line.substr(1, posEndReward - 1);
337 std::vector<std::string> rewards;
338 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
339 if (stateRewards.size() < rewards.size()) {
340 stateRewards.resize(rewards.size());
342 auto stateRewardsIt = stateRewards.begin();
343 for (
auto const& rew : rewards) {
344 auto rewardValue =
parseValue(rew, placeholders, valueParser);
346 if (stateRewardsIt->empty()) {
347 stateRewardsIt->resize(nrStates, storm::utility::zero<ValueType>());
349 (*stateRewardsIt)[state] = std::move(rewardValue);
353 line = line.substr(posEndReward + 1);
358 std::vector<std::string> labels;
368 std::regex labelRegex(R
"(\"([^\"]+?)\"(?=(\s|$|\"))|([^\s\"]+?(?=(\s|$))))");
371 auto match_begin = std::sregex_iterator(line.begin(), line.end(), labelRegex);
372 auto match_end = std::sregex_iterator();
373 for (std::sregex_iterator i = match_begin; i != match_end; ++i) {
374 std::smatch match = *i;
376 if (match.length(1) > 0) {
377 labels.push_back(match.str(1));
379 labels.push_back(match.str(3));
383 for (std::string
const& label : labels) {
391 }
else if (line.starts_with(
"action ")) {
393 if (firstActionForState) {
394 firstActionForState =
false;
399 line = line.substr(7);
400 std::string curString = line;
401 size_t posEnd = line.find(
" ");
402 if (posEnd != std::string::npos) {
403 curString = line.substr(0, posEnd);
404 line = line.substr(posEnd + 1);
411 if (curString !=
"__NOLABEL__") {
412 if (!modelComponents.
choiceLabeling.value().containsLabel(curString)) {
415 modelComponents.
choiceLabeling.value().addLabelToChoice(curString, row);
419 if (line.starts_with(
"[")) {
421 size_t posEndReward = line.find(
']');
422 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing.");
423 std::string rewardsStr = line.substr(1, posEndReward - 1);
425 std::vector<std::string> rewards;
426 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
427 if (actionRewards.size() < rewards.size()) {
428 actionRewards.resize(rewards.size());
430 auto actionRewardsIt = actionRewards.begin();
431 for (
auto const& rew : rewards) {
432 auto rewardValue =
parseValue(rew, placeholders, valueParser);
434 if (actionRewardsIt->size() <= row) {
435 actionRewardsIt->resize(std::max(row + 1, nrStates), storm::utility::zero<ValueType>());
437 (*actionRewardsIt)[row] = std::move(rewardValue);
441 line = line.substr(posEndReward + 1);
446 size_t posColon = line.find(
':');
447 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
448 "':' not found in '" << line <<
"' on line " << lineNumber <<
".");
449 size_t target = parseNumber<size_t>(line.substr(0, posColon - 1));
450 std::string valueStr = line.substr(posColon + 2);
451 ValueType value =
parseValue(valueStr, placeholders, valueParser);
452 STORM_LOG_TRACE(
"Transition " << row <<
" -> " << target <<
": " << value);
453 STORM_LOG_THROW(target < nrStates, storm::exceptions::WrongFormatException,
454 "In line " << lineNumber <<
" target state " << target <<
" is greater than state size " << nrStates);
459 std::cout <<
"Parsed " << state <<
"/" << nrStates <<
" states before abort.\n";
460 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
467 if (nonDeterministic) {
469 "Number of actions detected (at least " << builder.
getLastRow() + 1 <<
") does not match number of actions declared (" << nrChoices
470 <<
", in @nr_choices).");
474 modelComponents.
transitionMatrix = builder.
build(row + 1, nrStates, nonDeterministic ? nrStates : 0);
478 uint64_t numRewardModels = std::max(stateRewards.size(), actionRewards.size());
479 for (uint64_t i = 0; i < numRewardModels; ++i) {
480 std::string rewardModelName;
482 rewardModelName =
"rew" + std::to_string(i);
486 std::optional<std::vector<ValueType>> stateRewardVector, actionRewardVector;
487 if (i < stateRewards.size() && !stateRewards[i].empty()) {
488 stateRewardVector = std::move(stateRewards[i]);
490 if (i < actionRewards.size() && !actionRewards[i].empty()) {
491 actionRewards[i].resize(row + 1, storm::utility::zero<ValueType>());
492 actionRewardVector = std::move(actionRewards[i]);