113 bool sawModelType{
false}, sawParameters{
false};
115 if (line.empty() || line.starts_with(
"//")) {
119 if (line.starts_with(
"@type: ")) {
121 STORM_LOG_THROW(!sawModelType, storm::exceptions::WrongFormatException,
"Type declared twice.");
125 "Stochastic Two Player Games in DRN format are not supported.");
127 }
else if (line.starts_with(
"@value_type: ")) {
131 }
else if (line ==
"@parameters") {
133 STORM_LOG_THROW(!sawParameters, storm::exceptions::WrongFormatException,
"Parameters declared twice.");
136 boost::split(header.
parameters, line, boost::is_any_of(
" "));
138 sawParameters =
true;
139 }
else if (line ==
"@placeholders") {
142 size_t posColon = line.find(
':');
143 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
"':' not found.");
144 std::string placeName = line.substr(0, posColon - 1);
145 STORM_LOG_THROW(placeName.front() ==
'$', storm::exceptions::WrongFormatException,
"Placeholder must start with dollar symbol $.");
146 std::string valueStr = line.substr(posColon + 2);
147 auto ret = header.
placeholders.emplace(placeName.substr(1), valueStr);
148 STORM_LOG_THROW(ret.second, storm::exceptions::WrongFormatException,
"Placeholder '$" << placeName <<
"' was already defined before.");
149 if (file.peek() ==
'@') {
154 }
else if (line ==
"@reward_models") {
159 }
else if (line ==
"@nr_states") {
161 STORM_LOG_THROW(header.
nrStates == 0, storm::exceptions::WrongFormatException,
"Number states declared twice.");
164 }
else if (line ==
"@nr_choices") {
165 STORM_LOG_THROW(header.
nrChoices == 0, storm::exceptions::WrongFormatException,
"Number of actions declared twice.");
168 }
else if (line ==
"@model") {
170 STORM_LOG_THROW(sawModelType, storm::exceptions::WrongFormatException,
"Model type has to be declared before model.");
171 STORM_LOG_THROW(header.
nrStates != 0, storm::exceptions::WrongFormatException,
"No. of states has to be declared before model.");
172 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.");
180 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Could not parse line '" << line <<
"'.");
200std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>>
parseModel(std::istream& file,
DrnHeader const& header,
209 for (std::string
const& parameter : header.
parameters) {
213 std::unordered_map<std::string, ValueType> placeholders;
214 for (
auto const& [placeName, valueStr] : header.
placeholders) {
215 ValueType v =
parseValue(valueStr, placeholders, valueParser);
217 placeholders.emplace(placeName, std::move(v));
219 size_t const nrStates = header.
nrStates;
220 size_t const nrChoices = header.
nrChoices;
230 STORM_LOG_THROW(nrChoices != 0, storm::exceptions::WrongFormatException,
231 "No. of actions (@nr_choices) has to be declared when building a model with choice labeling.");
234 std::vector<std::vector<ValueType>> stateRewards;
235 std::vector<std::vector<ValueType>> actionRewards;
236 if (continuousTime) {
237 modelComponents.
exitRates = std::vector<ValueType>(nrStates);
251 uint64_t lineNumber = 0;
252 bool firstState =
true;
253 bool firstActionForState =
true;
256 if (line.starts_with(
"//")) {
263 boost::trim_left(line);
264 if (line.starts_with(
"state ")) {
272 firstActionForState =
true;
274 STORM_LOG_THROW(state <= nrStates, storm::exceptions::WrongFormatException,
"More states detected than declared (in @nr_states).");
277 line = line.substr(6);
278 std::string curString = line;
279 size_t posEnd = line.find(
" ");
280 if (posEnd != std::string::npos) {
281 curString = line.substr(0, posEnd);
282 line = line.substr(posEnd + 1);
287 STORM_LOG_THROW(state == parsedId, storm::exceptions::WrongFormatException,
288 "In line " << lineNumber <<
" state ids are not ordered and without gaps. Expected " << state <<
" but got " << parsedId <<
".");
289 if (nonDeterministic) {
292 STORM_LOG_THROW(nrChoices == 0 ||
builder.getCurrentRowGroupCount() <= nrChoices, storm::exceptions::WrongFormatException,
293 "More actions detected than declared (in @nr_choices).");
296 if (continuousTime) {
298 STORM_LOG_THROW(line.starts_with(
"!"), storm::exceptions::WrongFormatException,
"Exit rate missing in " << lineNumber <<
".");
299 line = line.substr(1);
301 posEnd = line.find(
" ");
302 if (posEnd != std::string::npos) {
303 curString = line.substr(0, posEnd);
304 line = line.substr(posEnd + 1);
308 ValueType exitRate =
parseValue(curString, placeholders, valueParser);
313 modelComponents.
exitRates.get()[state] = exitRate;
317 if (line.starts_with(
"{")) {
318 size_t posEndObservation = line.find(
"}");
319 std::string observation = line.substr(1, posEndObservation - 1);
322 line = line.substr(posEndObservation + 1);
324 STORM_LOG_THROW(line.starts_with(
" "), storm::exceptions::WrongFormatException,
325 "Expected whitespace after observation in line " << lineNumber <<
".");
327 line = line.substr(1);
331 "Expected an observation for state " << state <<
" in line " << lineNumber <<
".");
335 if (line.starts_with(
"[")) {
337 size_t posEndReward = line.find(
']');
338 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing in line " << lineNumber <<
" .");
339 std::string rewardsStr = line.substr(1, posEndReward - 1);
341 std::vector<std::string> rewards;
342 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
343 if (stateRewards.size() < rewards.size()) {
344 stateRewards.resize(rewards.size());
346 auto stateRewardsIt = stateRewards.begin();
347 for (
auto const& rew : rewards) {
348 auto rewardValue =
parseValue(rew, placeholders, valueParser);
350 if (stateRewardsIt->empty()) {
353 (*stateRewardsIt)[state] = std::move(rewardValue);
357 line = line.substr(posEndReward + 1);
362 std::vector<std::string> labels;
372 std::regex labelRegex(R
"(\"([^\"]+?)\"(?=(\s|$|\"))|([^\s\"]+?(?=(\s|$))))");
375 auto match_begin = std::sregex_iterator(line.begin(), line.end(), labelRegex);
376 auto match_end = std::sregex_iterator();
377 for (std::sregex_iterator i = match_begin; i != match_end; ++i) {
378 std::smatch match = *i;
380 if (match.length(1) > 0) {
381 labels.push_back(match.str(1));
383 std::string
const& unquotedLabel = match.str(3);
384 STORM_LOG_THROW(!unquotedLabel.starts_with(
"["), storm::exceptions::WrongFormatException,
385 "Unexpected token '" << unquotedLabel <<
"' among labels in line " << lineNumber <<
". Did you mix up the order?");
386 labels.push_back(unquotedLabel);
390 for (std::string
const& label : labels) {
398 }
else if (line.starts_with(
"action ")) {
400 if (firstActionForState) {
401 firstActionForState =
false;
406 line = line.substr(7);
407 std::string curString = line;
408 size_t posEnd = line.find(
" ");
409 if (posEnd != std::string::npos) {
410 curString = line.substr(0, posEnd);
411 line = line.substr(posEnd + 1);
418 if (curString !=
"__NOLABEL__") {
419 if (!modelComponents.
choiceLabeling.value().containsLabel(curString)) {
422 modelComponents.
choiceLabeling.value().addLabelToChoice(curString, row);
426 if (line.starts_with(
"[")) {
428 size_t posEndReward = line.find(
']');
429 STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException,
"] missing.");
430 std::string rewardsStr = line.substr(1, posEndReward - 1);
432 std::vector<std::string> rewards;
433 boost::split(rewards, rewardsStr, boost::is_any_of(
","));
434 if (actionRewards.size() < rewards.size()) {
435 actionRewards.resize(rewards.size());
437 auto actionRewardsIt = actionRewards.begin();
438 for (
auto const& rew : rewards) {
439 auto rewardValue =
parseValue(rew, placeholders, valueParser);
441 if (actionRewardsIt->size() <= row) {
444 (*actionRewardsIt)[row] = std::move(rewardValue);
448 line = line.substr(posEndReward + 1);
453 size_t posColon = line.find(
':');
454 STORM_LOG_THROW(posColon != std::string::npos, storm::exceptions::WrongFormatException,
455 "':' not found in '" << line <<
"' on line " << lineNumber <<
".");
457 std::string valueStr = line.substr(posColon + 2);
458 ValueType value =
parseValue(valueStr, placeholders, valueParser);
459 STORM_LOG_TRACE(
"Transition " << row <<
" -> " << target <<
": " << value);
460 STORM_LOG_THROW(target < nrStates, storm::exceptions::WrongFormatException,
461 "In line " << lineNumber <<
" target state " << target <<
" is greater than state size " << nrStates <<
".");
462 builder.addNextValue(row, target, value);
466 std::cout <<
"Parsed " << state <<
"/" << nrStates <<
" states before abort.\n";
467 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
474 if (nonDeterministic) {
475 STORM_LOG_THROW(nrChoices == 0 ||
builder.getLastRow() + 1 == nrChoices, storm::exceptions::WrongFormatException,
476 "Number of actions detected (at least " <<
builder.getLastRow() + 1 <<
") does not match number of actions declared (" << nrChoices
477 <<
", in @nr_choices).");
485 uint64_t numRewardModels = std::max(stateRewards.size(), actionRewards.size());
486 for (uint64_t i = 0; i < numRewardModels; ++i) {
487 std::string rewardModelName;
489 rewardModelName =
"rew" + std::to_string(i);
493 std::optional<std::vector<ValueType>> stateRewardVector, actionRewardVector;
494 if (i < stateRewards.size() && !stateRewards[i].empty()) {
495 stateRewardVector = std::move(stateRewards[i]);
497 if (i < actionRewards.size() && !actionRewards[i].empty()) {
499 actionRewardVector = std::move(actionRewards[i]);