43template<
typename ValueType,
typename StateType>
49template<
typename ValueType,
typename StateType>
54 hasStateActionRewards(false),
55 evaluateRewardExpressionsAtEdges(false),
56 evaluateRewardExpressionsAtDestinations(false) {
58 "JANI next-state generator cannot generate choice labels.");
65 if (features.hasArrays()) {
70 STORM_LOG_THROW(features.empty(), storm::exceptions::NotSupportedException,
71 "The explicit next-state generator does not support the following model feature(s): " << features.toString() <<
".");
76 bool hasNonTrivialRewardExpressions =
false;
82 for (
auto const& rewardModelName : this->
options.getRewardModelNames()) {
90 if (!hasNonTrivialRewardExpressions) {
91 for (
auto const& rewExpr : rewardExpressions) {
92 STORM_LOG_ASSERT(rewExpr.second.isVariable(),
"Expected trivial reward expression to be a variable. Got " << rewExpr.second <<
" instead.");
94 if (var.isTransient() && var.hasInitExpression() && !
storm::utility::isZero(var.getInitExpression().evaluateAsRational())) {
95 hasNonTrivialRewardExpressions =
true;
107 evaluateRewardExpressionsAtEdges =
true;
111 this->createSynchronizationInformation();
118 this->transientVariableInformation = TransientVariableInformation<ValueType>(this->model, this->parallelAutomata);
119 this->transientVariableInformation.registerArrayVariableReplacements(arrayEliminatorData);
123 this->
evaluator = std::make_unique<storm::expressions::ExpressionEvaluator<ValueType>>(this->model.
getManager());
124 this->transientVariableInformation.setDefaultValuesInEvaluator(*this->
evaluator);
127 buildRewardModelInformation();
131 for (
auto const& expressionOrLabelAndBool : this->
options.getTerminalStates()) {
132 if (expressionOrLabelAndBool.first.isExpression()) {
133 this->
terminalStates.emplace_back(expressionOrLabelAndBool.first.getExpression(), expressionOrLabelAndBool.second);
136 if (!this->
isSpecialLabel(expressionOrLabelAndBool.first.getLabel())) {
138 storm::exceptions::InvalidArgumentException,
139 "Terminal states refer to illegal label '" << expressionOrLabelAndBool.first.getLabel() <<
"'.");
143 storm::exceptions::InvalidArgumentException,
144 "Terminal states refer to non-boolean variable '" << expressionOrLabelAndBool.first.getLabel() <<
"'.");
146 "Terminal states refer to non-transient variable '" << expressionOrLabelAndBool.first.getLabel() <<
"'.");
155template<
typename ValueType,
typename StateType>
167template<
typename ValueType,
typename StateType>
175 if (!features.empty()) {
176 STORM_LOG_INFO(
"The model can not be build as it contains these unsupported features: " << features.toString());
184template<
typename ValueType,
typename StateType>
196 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Invalid model type.");
200template<
typename ValueType,
typename StateType>
205template<
typename ValueType,
typename StateType>
210template<
typename ValueType,
typename StateType>
215template<
typename ValueType,
typename StateType>
217 if (locationVariable.
bitWidth == 0) {
224template<
typename ValueType,
typename StateType>
225void JaniNextStateGenerator<ValueType, StateType>::setLocation(
CompressedState& state, LocationVariableInformation
const& locationVariable,
226 uint64_t locationIndex)
const {
227 if (locationVariable.bitWidth != 0) {
228 state.setFromInt(locationVariable.bitOffset, locationVariable.bitWidth, locationIndex);
232template<
typename ValueType,
typename StateType>
233std::vector<uint64_t> JaniNextStateGenerator<ValueType, StateType>::getLocations(
CompressedState const& state)
const {
234 std::vector<uint64_t> result(this->variableInformation.locationVariables.size());
236 auto resultIt = result.begin();
237 for (
auto it = this->variableInformation.locationVariables.begin(), ite = this->variableInformation.locationVariables.end(); it !=
ite; ++it, ++resultIt) {
238 if (it->bitWidth == 0) {
241 *resultIt = state.getAsInt(it->bitOffset, it->bitWidth);
248template<
typename ValueType,
typename StateType>
250 std::vector<StateType> initialStateIndices;
257 std::vector<storm::expressions::Expression> rangeExpressions = model.
getAllRangeExpressions(this->parallelAutomata);
258 for (
auto const& expression : rangeExpressions) {
259 solver->add(expression);
266 CompressedState initialState(this->variableInformation.getTotalBitOffset(
true));
271 std::shared_ptr<storm::solver::SmtSolver::ModelReference> model = solver->getModel();
272 for (
auto const& booleanVariable : this->variableInformation.booleanVariables) {
273 bool variableValue = model->getBooleanValue(booleanVariable.variable);
275 blockingExpression = blockingExpression.
isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression;
276 initialState.
set(booleanVariable.bitOffset, variableValue);
278 for (
auto const& integerVariable : this->variableInformation.integerVariables) {
279 int_fast64_t variableValue = model->getIntegerValue(integerVariable.variable);
280 if (integerVariable.forceOutOfBoundsCheck || this->getOptions().isExplorationChecksSet()) {
281 STORM_LOG_THROW(variableValue >= integerVariable.lowerBound, storm::exceptions::WrongFormatException,
282 "The initial value for variable " << integerVariable.variable.getName() <<
" is lower than the lower bound.");
283 STORM_LOG_THROW(variableValue <= integerVariable.upperBound, storm::exceptions::WrongFormatException,
284 "The initial value for variable " << integerVariable.variable.getName() <<
" is higher than the upper bound");
287 blockingExpression = blockingExpression.
isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression;
288 initialState.
setFromInt(integerVariable.bitOffset, integerVariable.bitWidth,
289 static_cast<uint_fast64_t
>(variableValue - integerVariable.lowerBound));
293 std::vector<std::set<uint64_t>::const_iterator> initialLocationsIts;
294 std::vector<std::set<uint64_t>::const_iterator> initialLocationsItes;
295 for (
auto const& automatonRef : this->parallelAutomata) {
296 auto const& automaton = automatonRef.get();
297 initialLocationsIts.push_back(automaton.getInitialLocationIndices().cbegin());
298 initialLocationsItes.push_back(automaton.getInitialLocationIndices().cend());
301 initialLocationsIts, initialLocationsItes,
302 [
this, &initialState](uint64_t index, uint64_t value) { setLocation(initialState, this->variableInformation.locationVariables[index], value); },
303 [&stateToIdCallback, &initialStateIndices, &initialState]() {
305 StateType
id = stateToIdCallback(initialState);
306 initialStateIndices.push_back(
id);
314 solver->add(blockingExpression);
317 STORM_LOG_DEBUG(
"Enumerated " << initialStateIndices.size() <<
" initial states using SMT solving.");
320 std::vector<std::vector<uint64_t>> allValues;
321 for (
auto const& aRef : this->parallelAutomata) {
322 auto const& aInitLocs = aRef.get().getInitialLocationIndices();
323 allValues.emplace_back(aInitLocs.begin(), aInitLocs.end());
325 uint64_t locEndIndex = allValues.size();
326 for (
auto const& intVar : this->variableInformation.integerVariables) {
327 STORM_LOG_ASSERT(intVar.lowerBound <= intVar.upperBound,
"Expecting variable with non-empty set of possible values.");
329 allValues.push_back(storm::utility::vector::buildVectorForRange<uint64_t>(
static_cast<uint64_t
>(0), intVar.upperBound + 1 - intVar.lowerBound));
331 uint64_t intEndIndex = allValues.size();
333 allValues.resize(allValues.size() + this->variableInformation.booleanVariables.size(),
334 std::vector<uint64_t>({static_cast<uint64_t>(0), static_cast<uint64_t>(1)}));
336 std::vector<std::vector<uint64_t>::const_iterator> its;
337 std::vector<std::vector<uint64_t>::const_iterator> ites;
338 for (
auto const& valVec : allValues) {
339 its.push_back(valVec.cbegin());
340 ites.push_back(valVec.cend());
344 CompressedState initialState(this->variableInformation.getTotalBitOffset(
true));
347 [
this, &initialState, &locEndIndex, &intEndIndex](uint64_t index, uint64_t value) {
349 if (index < locEndIndex) {
351 setLocation(initialState, this->variableInformation.locationVariables[index], value);
352 }
else if (index < intEndIndex) {
354 auto const& intVar = this->variableInformation.integerVariables[index - locEndIndex];
355 initialState.
setFromInt(intVar.bitOffset, intVar.bitWidth, value);
358 STORM_LOG_ASSERT(index - intEndIndex < this->variableInformation.booleanVariables.size(),
"Unexpected index");
359 auto const& boolVar = this->variableInformation.booleanVariables[index - intEndIndex];
361 initialState.
set(boolVar.bitOffset,
static_cast<bool>(value));
364 [&stateToIdCallback, &initialStateIndices, &initialState]() {
366 StateType
id = stateToIdCallback(initialState);
367 initialStateIndices.push_back(
id);
370 STORM_LOG_DEBUG(
"Enumerated " << initialStateIndices.size() <<
" initial states using brute force enumeration.");
372 return initialStateIndices;
375template<
typename ValueType,
typename StateType>
384 auto assignmentIt = assignments.
begin();
385 auto assignmentIte = assignments.end();
388 auto boolIt = this->variableInformation.booleanVariables.begin();
389 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsVariable() && assignmentIt->getExpressionVariable().hasBooleanType(); ++assignmentIt) {
390 while (assignmentIt->getExpressionVariable() != boolIt->variable) {
393 state.
set(boolIt->bitOffset, expressionEvaluator.asBool(assignmentIt->getAssignedExpression()));
397 auto integerIt = this->variableInformation.integerVariables.begin();
398 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsVariable() && assignmentIt->getExpressionVariable().hasIntegerType(); ++assignmentIt) {
399 while (assignmentIt->getExpressionVariable() != integerIt->variable) {
402 int_fast64_t assignedValue = expressionEvaluator.asInt(assignmentIt->getAssignedExpression());
404 if (assignedValue < integerIt->lowerBound || assignedValue > integerIt->upperBound) {
405 state = this->outOfBoundsState;
407 }
else if (integerIt->forceOutOfBoundsCheck || this->options.isExplorationChecksSet()) {
408 STORM_LOG_THROW(assignedValue >= integerIt->lowerBound, storm::exceptions::WrongFormatException,
409 "The update " << assignmentIt->getExpressionVariable().getName() <<
" := " << assignmentIt->getAssignedExpression()
410 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
411 << assignmentIt->getExpressionVariable().getName() <<
"'.");
412 STORM_LOG_THROW(assignedValue <= integerIt->upperBound, storm::exceptions::WrongFormatException,
413 "The update " << assignmentIt->getExpressionVariable().getName() <<
" := " << assignmentIt->getAssignedExpression()
414 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
415 << assignmentIt->getExpressionVariable().getName() <<
"'.");
417 state.
setFromInt(integerIt->bitOffset, integerIt->bitWidth, assignedValue - integerIt->lowerBound);
418 STORM_LOG_ASSERT(
static_cast<int_fast64_t
>(state.
getAsInt(integerIt->bitOffset, integerIt->bitWidth)) + integerIt->lowerBound == assignedValue,
419 "Writing to the bit vector bucket failed (read " << state.
getAsInt(integerIt->bitOffset, integerIt->bitWidth) <<
" but wrote "
420 << assignedValue <<
").");
423 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsArrayAccess(); ++assignmentIt) {
424 auto const& arrayIndicesAsExpr = assignmentIt->getLValue().getArrayIndexVector();
425 std::vector<uint64_t> arrayIndices;
426 arrayIndices.reserve(arrayIndicesAsExpr.size());
427 for (
auto const& i : arrayIndicesAsExpr) {
428 arrayIndices.push_back(
static_cast<uint64_t
>(expressionEvaluator.asInt(i)));
430 if (assignmentIt->getAssignedExpression().hasIntegerType()) {
431 IntegerVariableInformation
const& intInfo =
432 this->variableInformation.getIntegerArrayVariableReplacement(assignmentIt->getLValue().getVariable().getExpressionVariable(), arrayIndices);
433 int_fast64_t assignedValue = expressionEvaluator.asInt(assignmentIt->getAssignedExpression());
436 if (assignedValue < intInfo.lowerBound || assignedValue > intInfo.upperBound) {
437 state = this->outOfBoundsState;
440 STORM_LOG_THROW(assignedValue >= intInfo.lowerBound, storm::exceptions::WrongFormatException,
441 "The update " << assignmentIt->getLValue() <<
" := " << assignmentIt->getAssignedExpression()
442 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
443 << assignmentIt->getExpressionVariable().getName() <<
"'.");
444 STORM_LOG_THROW(assignedValue <= intInfo.upperBound, storm::exceptions::WrongFormatException,
445 "The update " << assignmentIt->getLValue() <<
" := " << assignmentIt->getAssignedExpression()
446 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
447 << assignmentIt->getExpressionVariable().getName() <<
"'.");
449 state.
setFromInt(intInfo.bitOffset, intInfo.bitWidth, assignedValue - intInfo.lowerBound);
450 STORM_LOG_ASSERT(
static_cast<int_fast64_t
>(state.
getAsInt(intInfo.bitOffset, intInfo.bitWidth)) + intInfo.lowerBound == assignedValue,
451 "Writing to the bit vector bucket failed (read " << state.
getAsInt(intInfo.bitOffset, intInfo.bitWidth) <<
" but wrote "
452 << assignedValue <<
").");
453 }
else if (assignmentIt->getAssignedExpression().hasBooleanType()) {
454 BooleanVariableInformation
const& boolInfo =
455 this->variableInformation.getBooleanArrayVariableReplacement(assignmentIt->getLValue().getVariable().getExpressionVariable(), arrayIndices);
456 state.
set(boolInfo.bitOffset, expressionEvaluator.asBool(assignmentIt->getAssignedExpression()));
458 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Unhandled type of base variable.");
463 STORM_LOG_ASSERT(assignmentIt == assignmentIte,
"Not all assignments were consumed.");
466template<
typename ValueType,
typename StateType>
467void JaniNextStateGenerator<ValueType, StateType>::applyTransientUpdate(TransientVariableValuation<ValueType>& transientValuation,
470 auto assignmentIt = transientAssignments.
begin();
471 auto assignmentIte = transientAssignments.
end();
474 auto boolIt = this->transientVariableInformation.booleanVariableInformation.begin();
475 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsVariable() && assignmentIt->getExpressionVariable().hasBooleanType(); ++assignmentIt) {
476 while (assignmentIt->getExpressionVariable() != boolIt->variable) {
479 transientValuation.booleanValues.emplace_back(&(*boolIt), expressionEvaluator.asBool(assignmentIt->getAssignedExpression()));
482 auto integerIt = this->transientVariableInformation.integerVariableInformation.begin();
483 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsVariable() && assignmentIt->getExpressionVariable().hasIntegerType(); ++assignmentIt) {
484 while (assignmentIt->getExpressionVariable() != integerIt->variable) {
487 int64_t assignedValue = expressionEvaluator.asInt(assignmentIt->getAssignedExpression());
489 STORM_LOG_THROW(!integerIt->lowerBound || assignedValue >= integerIt->lowerBound.get(), storm::exceptions::WrongFormatException,
490 "The update " << assignmentIt->getExpressionVariable().getName() <<
" := " << assignmentIt->getAssignedExpression()
491 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
492 << assignmentIt->getExpressionVariable().getName() <<
"'.");
493 STORM_LOG_THROW(!integerIt->upperBound || assignedValue <= integerIt->upperBound.get(), storm::exceptions::WrongFormatException,
494 "The update " << assignmentIt->getExpressionVariable().getName() <<
" := " << assignmentIt->getAssignedExpression()
495 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
496 << assignmentIt->getExpressionVariable().getName() <<
"'.");
498 transientValuation.integerValues.emplace_back(&(*integerIt), assignedValue);
501 auto rationalIt = this->transientVariableInformation.rationalVariableInformation.begin();
502 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsVariable() && assignmentIt->getExpressionVariable().hasRationalType(); ++assignmentIt) {
503 while (assignmentIt->getExpressionVariable() != rationalIt->variable) {
506 transientValuation.rationalValues.emplace_back(&(*rationalIt), expressionEvaluator.asRational(assignmentIt->getAssignedExpression()));
510 for (; assignmentIt != assignmentIte && assignmentIt->lValueIsArrayAccess(); ++assignmentIt) {
511 auto const& arrayIndicesAsExpr = assignmentIt->getLValue().getArrayIndexVector();
512 std::vector<uint64_t> arrayIndices;
513 arrayIndices.reserve(arrayIndicesAsExpr.size());
514 for (
auto const& i : arrayIndicesAsExpr) {
515 arrayIndices.push_back(
static_cast<uint64_t
>(expressionEvaluator.asInt(i)));
517 storm::expressions::Type const& baseType = assignmentIt->getLValue().getVariable().getExpressionVariable().getType();
519 auto const& intInfo = this->transientVariableInformation.getIntegerArrayVariableReplacement(
520 assignmentIt->getLValue().getVariable().getExpressionVariable(), arrayIndices);
521 int64_t assignedValue = expressionEvaluator.asInt(assignmentIt->getAssignedExpression());
523 STORM_LOG_THROW(assignedValue >= intInfo.lowerBound, storm::exceptions::WrongFormatException,
524 "The update " << assignmentIt->getLValue() <<
" := " << assignmentIt->getAssignedExpression()
525 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
526 << assignmentIt->getExpressionVariable().getName() <<
"'.");
527 STORM_LOG_THROW(assignedValue <= intInfo.upperBound, storm::exceptions::WrongFormatException,
528 "The update " << assignmentIt->getLValue() <<
" := " << assignmentIt->getAssignedExpression()
529 <<
" leads to an out-of-bounds value (" << assignedValue <<
") for the variable '"
530 << assignmentIt->getExpressionVariable().getName() <<
"'.");
532 transientValuation.integerValues.emplace_back(&intInfo, assignedValue);
534 auto const& boolInfo = this->transientVariableInformation.getBooleanArrayVariableReplacement(
535 assignmentIt->getLValue().getVariable().getExpressionVariable(), arrayIndices);
536 transientValuation.booleanValues.emplace_back(&boolInfo, expressionEvaluator.asBool(assignmentIt->getAssignedExpression()));
538 auto const& rationalInfo = this->transientVariableInformation.getRationalArrayVariableReplacement(
539 assignmentIt->getLValue().getVariable().getExpressionVariable(), arrayIndices);
540 transientValuation.rationalValues.emplace_back(&rationalInfo, expressionEvaluator.asRational(assignmentIt->getAssignedExpression()));
542 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Unhandled type of base variable.");
547 STORM_LOG_ASSERT(assignmentIt == assignmentIte,
"Not all assignments were consumed.");
550template<
typename ValueType,
typename StateType>
551TransientVariableValuation<ValueType> JaniNextStateGenerator<ValueType, StateType>::getTransientVariableValuationAtLocations(
553 uint64_t automatonIndex = 0;
554 TransientVariableValuation<ValueType> transientVariableValuation;
555 for (
auto const& automatonRef : this->parallelAutomata) {
556 auto const& automaton = automatonRef.get();
557 uint64_t currentLocationIndex = locations[automatonIndex];
563 return transientVariableValuation;
566template<
typename ValueType,
typename StateType>
569 transientVariableInformation.setDefaultValuesInEvaluator(evaluator);
570 auto transientVariableValuation = getTransientVariableValuationAtLocations(getLocations(state), evaluator);
571 transientVariableValuation.setInEvaluator(evaluator, this->getOptions().isExplorationChecksSet());
574template<
typename ValueType,
typename StateType>
578 for (
auto const& varInfo : transientVariableInformation.booleanVariableInformation) {
579 result.addVariable(varInfo.variable);
581 for (
auto const& varInfo : transientVariableInformation.integerVariableInformation) {
582 result.addVariable(varInfo.variable);
584 for (
auto const& varInfo : transientVariableInformation.rationalVariableInformation) {
585 result.addVariable(varInfo.variable);
590template<
typename ValueType,
typename StateType>
593 std::vector<bool> booleanValues;
594 booleanValues.reserve(this->variableInformation.booleanVariables.size() + transientVariableInformation.booleanVariableInformation.size());
595 std::vector<int64_t> integerValues;
596 integerValues.reserve(this->variableInformation.locationVariables.size() + this->variableInformation.integerVariables.size() +
597 transientVariableInformation.integerVariableInformation.size());
598 std::vector<storm::RationalNumber> rationalValues;
599 rationalValues.reserve(transientVariableInformation.rationalVariableInformation.size());
602 extractVariableValues(*this->state, this->variableInformation, integerValues, booleanValues, integerValues);
605 auto transientVariableValuation = getTransientVariableValuationAtLocations(getLocations(*this->state), *this->evaluator);
607 auto varIt = transientVariableValuation.booleanValues.begin();
608 auto varIte = transientVariableValuation.booleanValues.end();
609 for (
auto const& varInfo : transientVariableInformation.booleanVariableInformation) {
610 if (varIt != varIte && varIt->first->variable == varInfo.variable) {
611 booleanValues.push_back(varIt->second);
614 booleanValues.push_back(varInfo.defaultValue);
619 auto varIt = transientVariableValuation.integerValues.begin();
620 auto varIte = transientVariableValuation.integerValues.end();
621 for (
auto const& varInfo : transientVariableInformation.integerVariableInformation) {
622 if (varIt != varIte && varIt->first->variable == varInfo.variable) {
623 integerValues.push_back(varIt->second);
626 integerValues.push_back(varInfo.defaultValue);
631 auto varIt = transientVariableValuation.rationalValues.begin();
632 auto varIte = transientVariableValuation.rationalValues.end();
633 for (
auto const& varInfo : transientVariableInformation.rationalVariableInformation) {
634 if (varIt != varIte && varIt->first->variable == varInfo.variable) {
635 rationalValues.push_back(storm::utility::convertNumber<storm::RationalNumber>(varIt->second));
638 rationalValues.push_back(storm::utility::convertNumber<storm::RationalNumber>(varInfo.defaultValue));
643 valuationsBuilder.
addState(currentStateIndex, std::move(booleanValues), std::move(integerValues), std::move(rationalValues));
646template<
typename ValueType,
typename StateType>
654 std::vector<uint64_t> locations = getLocations(*this->state);
658 auto transientVariableValuation = getTransientVariableValuationAtLocations(locations, *this->evaluator);
659 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
664 if (!this->terminalStates.empty()) {
665 for (
auto const& expressionBool : this->terminalStates) {
666 if (this->evaluator->asBool(expressionBool.first) == expressionBool.second) {
668 this->transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
675 this->transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
679 std::vector<Choice<ValueType>> allChoices;
680 if (this->getOptions().isApplyMaximalProgressAssumptionSet()) {
682 allChoices = getActionChoices(locations, *this->state, stateToIdCallback, EdgeFilter::WithoutRate);
683 if (allChoices.empty()) {
685 allChoices = getActionChoices(locations, *this->state, stateToIdCallback, EdgeFilter::WithRate);
688 allChoices = getActionChoices(locations, *this->state, stateToIdCallback);
690 std::size_t totalNumberOfChoices = allChoices.size();
694 if (totalNumberOfChoices == 0) {
699 if (this->isDeterministicModel() && totalNumberOfChoices > 1) {
703 this->overlappingGuardStates->push_back(stateToIdCallback(*this->state));
708 ValueType totalExitRate = this->isDiscreteTimeModel() ?
static_cast<ValueType
>(totalNumberOfChoices) : storm::utility::zero<ValueType>();
711 for (
auto const& choice : allChoices) {
712 for (
auto const& stateProbabilityPair : choice) {
713 if (this->isDiscreteTimeModel()) {
714 globalChoice.
addProbability(stateProbabilityPair.first, stateProbabilityPair.second / totalNumberOfChoices);
716 globalChoice.
addProbability(stateProbabilityPair.first, stateProbabilityPair.second);
720 if (hasStateActionRewards && !this->isDiscreteTimeModel()) {
721 totalExitRate += choice.getTotalMass();
725 std::vector<ValueType> stateActionRewards(rewardExpressions.size(), storm::utility::zero<ValueType>());
726 for (
auto const& choice : allChoices) {
727 if (hasStateActionRewards) {
728 for (uint_fast64_t rewardVariableIndex = 0; rewardVariableIndex < rewardExpressions.size(); ++rewardVariableIndex) {
729 stateActionRewards[rewardVariableIndex] += choice.getRewards()[rewardVariableIndex] * choice.getTotalMass() / totalExitRate;
737 globalChoice.
addRewards(std::move(stateActionRewards));
741 allChoices.push_back(std::move(globalChoice));
745 for (
auto& choice : allChoices) {
749 this->postprocess(result);
754template<
typename ValueType,
typename StateType>
757 StateToIdCallback stateToIdCallback) {
759 boost::optional<ValueType> exitRate = boost::none;
761 exitRate = this->evaluator->asRational(edge.
getRate());
764 Choice<ValueType> choice(edge.
getActionIndex(),
static_cast<bool>(exitRate));
765 std::vector<ValueType> stateActionRewards;
768 TransientVariableValuation<ValueType> transientVariableValuation;
770 stateActionRewards.resize(rewardModelInformation.size(), storm::utility::zero<ValueType>());
774 transientVariableValuation.clear();
776 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
778 stateActionRewards = evaluateRewardExpressions();
779 transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
783 ValueType probabilitySum = storm::utility::zero<ValueType>();
784 for (
auto const& destination : edge.getDestinations()) {
787 if (probability != storm::utility::zero<ValueType>()) {
788 bool evaluatorChanged =
false;
795 applyUpdate(newState, destination, this->variableInformation.locationVariables[automatonIndex], assignmentLevel, *this->evaluator);
796 if (hasTransientAssignments) {
798 "Transition rewards are not supported and scaling to action rewards is disabled.");
799 transientVariableValuation.clear();
802 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
803 evaluatorChanged =
true;
805 if (assignmentLevel < highestLevel) {
806 while (assignmentLevel < highestLevel) {
809 evaluatorChanged =
true;
810 applyUpdate(newState, destination, this->variableInformation.locationVariables[automatonIndex], assignmentLevel, *this->evaluator);
811 if (hasTransientAssignments) {
812 transientVariableValuation.clear();
815 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
816 evaluatorChanged =
true;
820 if (evaluateRewardExpressionsAtDestinations) {
822 evaluatorChanged =
true;
823 addEvaluatedRewardExpressions(stateActionRewards, probability);
826 if (evaluatorChanged) {
829 if (hasTransientAssignments) {
830 this->transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
834 StateType stateIndex = stateToIdCallback(newState);
837 probability = exitRate ? exitRate.get() * probability : probability;
838 choice.addProbability(stateIndex, probability);
841 probabilitySum += probability;
847 choice.addRewards(std::move(stateActionRewards));
852 storm::exceptions::WrongFormatException,
"Probabilities do not sum to one for edge (actually sum to " << probabilitySum <<
").");
858template<
typename ValueType,
typename StateType>
859void JaniNextStateGenerator<ValueType, StateType>::generateSynchronizedDistribution(
storm::storage::BitVector const& state,
860 AutomataEdgeSets
const& edgeCombination,
861 std::vector<EdgeSetWithIndices::const_iterator>
const& iteratorList,
863 std::vector<ValueType>& stateActionRewards, EdgeIndexSet& edgeIndices,
864 StateToIdCallback stateToIdCallback) {
866 int64_t lowestDestinationAssignmentLevel = std::numeric_limits<int64_t>::max();
867 int64_t highestDestinationAssignmentLevel = std::numeric_limits<int64_t>::min();
868 int64_t lowestEdgeAssignmentLevel = std::numeric_limits<int64_t>::max();
869 int64_t highestEdgeAssignmentLevel = std::numeric_limits<int64_t>::min();
870 uint64_t numDestinations = 1;
871 for (uint_fast64_t i = 0;
i < iteratorList.size(); ++
i) {
872 if (this->getOptions().isBuildChoiceOriginsSet()) {
873 auto automatonIndex = model.
getAutomatonIndex(parallelAutomata[edgeCombination[i].first].get().getName());
887 TransientVariableValuation<ValueType> transientVariableValuation;
888 if (evaluateRewardExpressionsAtEdges && lowestEdgeAssignmentLevel <= highestEdgeAssignmentLevel) {
889 for (int64_t assignmentLevel = lowestEdgeAssignmentLevel; assignmentLevel <= highestEdgeAssignmentLevel; ++assignmentLevel) {
890 transientVariableValuation.clear();
891 for (uint_fast64_t i = 0;
i < iteratorList.size(); ++
i) {
895 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
897 addEvaluatedRewardExpressions(stateActionRewards, storm::utility::one<ValueType>());
898 transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
901 std::vector<storm::jani::EdgeDestination const*> destinations;
902 std::vector<LocationVariableInformation const*> locationVars;
903 destinations.reserve(iteratorList.size());
904 locationVars.reserve(iteratorList.size());
906 for (uint64_t destinationId = 0; destinationId < numDestinations; ++destinationId) {
908 destinations.clear();
909 locationVars.clear();
910 transientVariableValuation.clear();
912 ValueType successorProbability = storm::utility::one<ValueType>();
914 uint64_t destinationIndex = destinationId;
915 for (uint64_t i = 0;
i < iteratorList.size(); ++
i) {
919 destinations.push_back(&edge.
getDestination(localDestinationIndex));
920 locationVars.push_back(&this->variableInformation.locationVariables[edgeCombination[i].first]);
922 ValueType probability = this->evaluator->asRational(destinations.back()->getProbability());
924 successorProbability *= probability * this->evaluator->asRational(edge.
getRate());
926 successorProbability *= probability;
932 applyUpdate(successorState, *destinations.back(), *locationVars.back(), lowestDestinationAssignmentLevel, *this->evaluator);
933 applyTransientUpdate(transientVariableValuation,
934 destinations.back()->getOrderedAssignments().getTransientAssignments(lowestDestinationAssignmentLevel), *this->evaluator);
938 bool evaluatorChanged =
false;
940 for (int64_t assignmentLevel = lowestDestinationAssignmentLevel + 1; assignmentLevel <= highestDestinationAssignmentLevel; ++assignmentLevel) {
942 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
943 transientVariableValuation.clear();
944 evaluatorChanged =
true;
945 auto locationVarIt = locationVars.begin();
946 for (
auto const& destPtr : destinations) {
947 applyUpdate(successorState, *destPtr, **locationVarIt, assignmentLevel, *this->evaluator);
948 applyTransientUpdate(transientVariableValuation, destinations.back()->getOrderedAssignments().getTransientAssignments(assignmentLevel),
953 if (!transientVariableValuation.empty()) {
954 evaluatorChanged =
true;
955 transientVariableValuation.setInEvaluator(*this->evaluator, this->getOptions().isExplorationChecksSet());
957 if (evaluateRewardExpressionsAtDestinations) {
959 evaluatorChanged =
true;
960 addEvaluatedRewardExpressions(stateActionRewards, successorProbability);
962 if (evaluatorChanged) {
965 this->transientVariableInformation.setDefaultValuesInEvaluator(*this->evaluator);
968 StateType
id = stateToIdCallback(successorState);
969 distribution.
add(
id, successorProbability);
974template<
typename ValueType,
typename StateType>
975void JaniNextStateGenerator<ValueType, StateType>::expandSynchronizingEdgeCombination(AutomataEdgeSets
const& edgeCombination, uint64_t outputActionIndex,
977 std::vector<Choice<ValueType>>& newChoices) {
980 checkGlobalVariableWritesValid(edgeCombination);
983 std::vector<EdgeSetWithIndices::const_iterator> iteratorList(edgeCombination.size());
986 for (
size_t i = 0;
i < edgeCombination.size(); ++
i) {
987 iteratorList[
i] = edgeCombination[
i].second.cbegin();
995 distribution.
clear();
997 EdgeIndexSet edgeIndices;
998 std::vector<ValueType> stateActionRewards(rewardExpressions.size(), storm::utility::zero<ValueType>());
1001 generateSynchronizedDistribution(state, edgeCombination, iteratorList, distribution, stateActionRewards, edgeIndices, stateToIdCallback);
1007 newChoices.emplace_back(outputActionIndex);
1010 Choice<ValueType>& choice = newChoices.back();
1013 if (this->getOptions().isBuildChoiceOriginsSet()) {
1014 choice.addOriginData(boost::any(std::move(edgeIndices)));
1018 choice.addRewards(std::move(stateActionRewards));
1021 ValueType probabilitySum = storm::utility::zero<ValueType>();
1022 choice.reserve(std::distance(distribution.
begin(), distribution.
end()));
1023 for (
auto const& stateProbability : distribution) {
1024 choice.addProbability(stateProbability.getState(), stateProbability.getValue());
1027 probabilitySum += stateProbability.getValue();
1034 storm::exceptions::WrongFormatException,
1035 "Sum of update probabilities do not sum to one for some edge (actually sum to " << probabilitySum <<
").");
1039 bool movedIterator =
false;
1040 for (uint64_t j = 0; !movedIterator && j < iteratorList.size(); ++j) {
1042 if (iteratorList[j] != edgeCombination[j].second.end()) {
1043 movedIterator =
true;
1046 iteratorList[j] = edgeCombination[j].second.begin();
1050 done = !movedIterator;
1054template<
typename ValueType,
typename StateType>
1055std::vector<Choice<ValueType>> JaniNextStateGenerator<ValueType, StateType>::getActionChoices(std::vector<uint64_t>
const& locations,
1057 EdgeFilter
const& edgeFilter) {
1058 std::vector<Choice<ValueType>> result;
1062 std::vector<EdgeSetWithIndices const*> edgeSetsMemory;
1064 std::vector<typename EdgeSetWithIndices::const_iterator> edgeIteratorMemory;
1066 for (OutputAndEdges
const& outputAndEdges : edges) {
1067 auto const& edges = outputAndEdges.second;
1068 if (edges.size() == 1) {
1070 auto const& nonsychingEdges = edges.front();
1071 uint64_t automatonIndex = nonsychingEdges.first;
1073 auto edgesIt = nonsychingEdges.second.find(locations[automatonIndex]);
1074 if (edgesIt != nonsychingEdges.second.end()) {
1075 for (
auto const& indexAndEdge : edgesIt->second) {
1076 if (edgeFilter != EdgeFilter::All) {
1077 STORM_LOG_ASSERT(edgeFilter == EdgeFilter::WithRate || edgeFilter == EdgeFilter::WithoutRate,
"Unexpected edge filter.");
1078 if ((edgeFilter == EdgeFilter::WithRate) != indexAndEdge.second->hasRate()) {
1082 if (!this->evaluator->asBool(indexAndEdge.second->getGuard())) {
1086 result.push_back(expandNonSynchronizingEdge(*indexAndEdge.second,
1087 outputAndEdges.first ? outputAndEdges.first.get() : indexAndEdge.second->getActionIndex(),
1088 automatonIndex, state, stateToIdCallback));
1090 if (this->getOptions().isBuildChoiceOriginsSet()) {
1091 auto modelAutomatonIndex = model.
getAutomatonIndex(parallelAutomata[automatonIndex].get().getName());
1093 result.back().addOriginData(boost::any(std::move(edgeIndex)));
1099 STORM_LOG_ASSERT(outputAndEdges.first,
"Need output action index for synchronization.");
1101 uint64_t outputActionIndex = outputAndEdges.first.get();
1104 bool productiveCombination =
true;
1107 edgeSetsMemory.clear();
1108 for (
auto const& automatonAndEdges : outputAndEdges.second) {
1109 uint64_t automatonIndex = automatonAndEdges.first;
1110 LocationsAndEdges
const& locationsAndEdges = automatonAndEdges.second;
1111 auto edgesIt = locationsAndEdges.find(locations[automatonIndex]);
1112 if (edgesIt == locationsAndEdges.end()) {
1113 productiveCombination =
false;
1116 edgeSetsMemory.push_back(&edgesIt->second);
1119 if (productiveCombination) {
1121 edgeIteratorMemory.clear();
1122 for (
auto const& edgesIt : edgeSetsMemory) {
1123 bool atLeastOneEdge =
false;
1124 EdgeSetWithIndices
const& edgeSetWithIndices = *edgesIt;
1125 for (
auto indexAndEdgeIt = edgeSetWithIndices.begin(), indexAndEdgeIte = edgeSetWithIndices.end(); indexAndEdgeIt != indexAndEdgeIte;
1128 if (edgeFilter != EdgeFilter::All) {
1129 STORM_LOG_ASSERT(edgeFilter == EdgeFilter::WithRate || edgeFilter == EdgeFilter::WithoutRate,
"Unexpected edge filter.");
1130 if ((edgeFilter == EdgeFilter::WithRate) != indexAndEdgeIt->second->hasRate()) {
1135 if (!this->evaluator->asBool(indexAndEdgeIt->second->getGuard())) {
1140 atLeastOneEdge =
true;
1141 edgeIteratorMemory.push_back(indexAndEdgeIt);
1146 if (!atLeastOneEdge) {
1147 productiveCombination =
false;
1154 if (productiveCombination) {
1155 AutomataEdgeSets automataEdgeSets;
1156 automataEdgeSets.reserve(outputAndEdges.second.size());
1157 STORM_LOG_ASSERT(edgeSetsMemory.size() == outputAndEdges.second.size(),
"Unexpected number of edge sets stored.");
1158 STORM_LOG_ASSERT(edgeIteratorMemory.size() == outputAndEdges.second.size(),
"Unexpected number of edge iterators stored.");
1159 auto edgeSetIt = edgeSetsMemory.begin();
1160 auto edgeIteratorIt = edgeIteratorMemory.begin();
1161 for (
auto const& automatonAndEdges : outputAndEdges.second) {
1162 EdgeSetWithIndices enabledEdgesOfAutomaton;
1163 uint64_t automatonIndex = automatonAndEdges.first;
1164 EdgeSetWithIndices
const& edgeSetWithIndices = **edgeSetIt;
1165 auto indexAndEdgeIt = *edgeIteratorIt;
1167 enabledEdgesOfAutomaton.emplace_back(*indexAndEdgeIt);
1168 auto indexAndEdgeIte = edgeSetWithIndices.end();
1169 for (++indexAndEdgeIt; indexAndEdgeIt != indexAndEdgeIte; ++indexAndEdgeIt) {
1171 if (edgeFilter != EdgeFilter::All) {
1172 STORM_LOG_ASSERT(edgeFilter == EdgeFilter::WithRate || edgeFilter == EdgeFilter::WithoutRate,
"Unexpected edge filter.");
1173 if ((edgeFilter == EdgeFilter::WithRate) != indexAndEdgeIt->second->hasRate()) {
1178 if (!this->evaluator->asBool(indexAndEdgeIt->second->getGuard())) {
1182 enabledEdgesOfAutomaton.emplace_back(*indexAndEdgeIt);
1184 automataEdgeSets.emplace_back(std::move(automatonIndex), std::move(enabledEdgesOfAutomaton));
1189 expandSynchronizingEdgeCombination(automataEdgeSets, outputActionIndex, state, stateToIdCallback, result);
1197template<
typename ValueType,
typename StateType>
1198void JaniNextStateGenerator<ValueType, StateType>::checkGlobalVariableWritesValid(AutomataEdgeSets
const& enabledEdges)
const {
1201 std::map<storm::expressions::Variable, uint64_t> writtenGlobalVariables;
1202 for (
auto edgeSetIt = enabledEdges.begin(), edgeSetIte = enabledEdges.end(); edgeSetIt != edgeSetIte; ++edgeSetIt) {
1203 for (
auto const& indexAndEdge : edgeSetIt->second) {
1204 for (
auto const& globalVariable : indexAndEdge.second->getWrittenGlobalVariables()) {
1205 auto it = writtenGlobalVariables.find(globalVariable);
1207 auto index = std::distance(enabledEdges.begin(), edgeSetIt);
1208 if (it != writtenGlobalVariables.end()) {
1209 STORM_LOG_THROW(it->second ==
static_cast<uint64_t
>(index), storm::exceptions::WrongFormatException,
1210 "Multiple writes to global variable '" << globalVariable.getName() <<
"' in synchronizing edges.");
1212 writtenGlobalVariables.emplace(globalVariable, index);
1219template<
typename ValueType,
typename StateType>
1221 return rewardExpressions.size();
1224template<
typename ValueType,
typename StateType>
1226 return rewardModelInformation[index];
1229template<
typename ValueType,
typename StateType>
1231 std::vector<StateType>
const& initialStateIndices,
1232 std::vector<StateType>
const& deadlockStateIndices,
1233 std::vector<StateType>
const& unexploredStateIndices) {
1236 std::vector<std::pair<std::string, storm::expressions::Expression>> transientVariableExpressions;
1238 if (variable.getType().isBasicType() && variable.getType().asBasicType().isBooleanType()) {
1240 transientVariableExpressions.emplace_back(variable.getName(), variable.getExpressionVariable().getExpression());
1245 transientVariableExpressions);
1248template<
typename ValueType,
typename StateType>
1250 std::vector<ValueType> result;
1251 result.reserve(rewardExpressions.size());
1252 for (
auto const& rewardExpression : rewardExpressions) {
1253 result.push_back(this->evaluator->asRational(rewardExpression.second));
1258template<
typename ValueType,
typename StateType>
1259void JaniNextStateGenerator<ValueType, StateType>::addEvaluatedRewardExpressions(std::vector<ValueType>& rewards, ValueType
const& factor)
const {
1260 assert(rewards.size() == rewardExpressions.size());
1261 auto rewIt = rewards.begin();
1262 for (
auto const& rewardExpression : rewardExpressions) {
1263 (*rewIt) += factor * this->evaluator->asRational(rewardExpression.second);
1268template<
typename ValueType,
typename StateType>
1269void JaniNextStateGenerator<ValueType, StateType>::buildRewardModelInformation() {
1270 for (
auto const& rewardModel : rewardExpressions) {
1272 rewardModelInformation.emplace_back(rewardModel.first, info.hasStateRewards(),
false,
false);
1274 "Transition rewards are not supported and a reduction to action-based rewards was not possible.");
1275 if (info.hasTransitionRewards()) {
1276 evaluateRewardExpressionsAtDestinations =
true;
1278 if (info.hasActionRewards() || (this->options.isScaleAndLiftTransitionRewardsSet() && info.hasTransitionRewards())) {
1279 hasStateActionRewards =
true;
1280 rewardModelInformation.back().setHasStateActionRewards();
1283 if (!hasStateActionRewards) {
1284 evaluateRewardExpressionsAtDestinations =
false;
1285 evaluateRewardExpressionsAtEdges =
false;
1289template<
typename ValueType,
typename StateType>
1290void JaniNextStateGenerator<ValueType, StateType>::createSynchronizationInformation() {
1295 this->parallelAutomata.push_back(automaton);
1297 LocationsAndEdges locationsAndEdges;
1298 uint64_t edgeIndex = 0;
1299 for (
auto const& edge : automaton.getEdges()) {
1304 AutomataAndEdges automataAndEdges;
1305 automataAndEdges.emplace_back(std::make_pair(0, std::move(locationsAndEdges)));
1307 this->edges.emplace_back(std::make_pair(boost::none, std::move(automataAndEdges)));
1312 uint64_t automatonIndex = 0;
1313 for (
auto const& composition : parallelComposition.getSubcompositions()) {
1314 STORM_LOG_THROW(composition->isAutomatonComposition(), storm::exceptions::WrongFormatException,
"Expected flat parallel composition.");
1315 STORM_LOG_THROW(composition->asAutomatonComposition().getInputEnabledActions().empty(), storm::exceptions::NotSupportedException,
1316 "Input-enabled actions are not supported right now.");
1318 this->parallelAutomata.push_back(this->model.
getAutomaton(composition->asAutomatonComposition().getAutomatonName()));
1321 LocationsAndEdges locationsAndEdges;
1322 uint64_t edgeIndex = 0;
1323 for (
auto const& edge : parallelAutomata.back().get().getEdges()) {
1330 if (!locationsAndEdges.empty()) {
1331 AutomataAndEdges automataAndEdges;
1332 automataAndEdges.emplace_back(std::make_pair(automatonIndex, std::move(locationsAndEdges)));
1333 this->edges.emplace_back(std::make_pair(boost::none, std::move(automataAndEdges)));
1338 for (
auto const& vector : parallelComposition.getSynchronizationVectors()) {
1339 uint64_t outputActionIndex = this->model.
getActionIndex(vector.getOutput());
1341 AutomataAndEdges automataAndEdges;
1342 bool atLeastOneEdge =
true;
1343 uint64_t automatonIndex = 0;
1344 for (
auto const& element : vector.getInput()) {
1346 LocationsAndEdges locationsAndEdges;
1348 uint64_t edgeIndex = 0;
1349 for (
auto const& edge : parallelAutomata[automatonIndex].get().getEdges()) {
1355 if (locationsAndEdges.empty()) {
1356 atLeastOneEdge =
false;
1359 automataAndEdges.emplace_back(std::make_pair(automatonIndex, std::move(locationsAndEdges)));
1364 if (atLeastOneEdge) {
1365 this->edges.emplace_back(std::make_pair(outputActionIndex, std::move(automataAndEdges)));
1370 STORM_LOG_TRACE(
"Number of synchronizations: " << this->edges.size() <<
".");
1373template<
typename ValueType,
typename StateType>
1375 std::vector<boost::any>& dataForChoiceOrigins)
const {
1376 if (!this->getOptions().isBuildChoiceOriginsSet()) {
1380 std::vector<uint_fast64_t> identifiers;
1381 identifiers.reserve(dataForChoiceOrigins.size());
1383 std::map<EdgeIndexSet, uint_fast64_t> edgeIndexSetToIdentifierMap;
1386 edgeIndexSetToIdentifierMap.insert(std::make_pair(
EdgeIndexSet(), 0));
1387 uint_fast64_t currentIdentifier = 1;
1388 for (boost::any& originData : dataForChoiceOrigins) {
1389 STORM_LOG_ASSERT(originData.empty() || boost::any_cast<EdgeIndexSet>(&originData) !=
nullptr,
1390 "Origin data has unexpected type: " << originData.type().name() <<
".");
1392 EdgeIndexSet currentEdgeIndexSet = originData.empty() ?
EdgeIndexSet() : boost::any_cast<EdgeIndexSet>(std::move(originData));
1393 auto insertionRes = edgeIndexSetToIdentifierMap.emplace(std::move(currentEdgeIndexSet), currentIdentifier);
1394 identifiers.push_back(insertionRes.first->second);
1395 if (insertionRes.second) {
1396 ++currentIdentifier;
1400 std::vector<EdgeIndexSet> identifierToEdgeIndexSetMapping(currentIdentifier);
1401 for (
auto const& setIdPair : edgeIndexSetToIdentifierMap) {
1402 identifierToEdgeIndexSetMapping[setIdPair.second] = setIdPair.first;
1405 return std::make_shared<storm::storage::sparse::JaniChoiceOrigins>(std::make_shared<storm::jani::Model>(model), std::move(identifiers),
1406 std::move(identifierToEdgeIndexSetMapping));
1409template<
typename ValueType,
typename StateType>
1411 STORM_LOG_WARN(
"There are no observation labels in JANI currenty");
1415template<
typename ValueType,
typename StateType>
1416void JaniNextStateGenerator<ValueType, StateType>::checkValid()
const {
1418#ifdef STORM_HAVE_CARL
1423 std::vector<std::reference_wrapper<storm::jani::Constant const>> undefinedConstants = model.
getUndefinedConstants();
1424 std::stringstream stream;
1425 bool printComma =
false;
1426 for (
auto const& constant : undefinedConstants) {
1432 stream << constant.get().getName() <<
" (" << constant.get().getType() <<
")";
1435 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Program still contains these undefined constants: " + stream.str());
1437#ifdef STORM_HAVE_CARL
1440 "The input model contains undefined constants that influence the graph structure of the underlying model, which is not allowed.");
1445template class JaniNextStateGenerator<double>;
1447#ifdef STORM_HAVE_CARL
1448template class JaniNextStateGenerator<storm::RationalNumber>;
1449template class JaniNextStateGenerator<storm::RationalFunction>;
uint64_t getReservedBitsForUnboundedVariables() const
bool isScaleAndLiftTransitionRewardsSet() const
bool isBuildAllRewardModelsSet() const
bool isBuildChoiceLabelsSet() const
bool isBuildChoiceOriginsSet() const
BuilderOptions & substituteExpressions(std::function< storm::expressions::Expression(storm::expressions::Expression const &)> const &substitutionFunction)
Substitutes all expressions occurring in these options.
bool isExplorationChecksSet() const
bool isBuildAllLabelsSet() const
bool hasTerminalStates() const
bool isAddOverlappingGuardLabelSet() const
bool isAddOutOfBoundsStateSet() const
std::set< std::string > const & getLabelNames() const
Which labels are built.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this expression.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
Expression integer(int_fast64_t value) const
Creates an expression that characterizes the given integer literal.
bool isBooleanType() const
Checks whether this type is a boolean type.
bool isIntegerType() const
Checks whether this type is an integral type.
bool isRationalType() const
Checks whether this type is a rational type.
storm::expressions::Expression getExpression() const
Retrieves an expression that represents the variable.
void clear()
Clears this distribution.
ContainerType::iterator begin()
Access to iterators over the entries of the distribution.
void compress()
Compresses the internal storage by summing the values of entries which agree on the index.
ContainerType::iterator end()
void add(DistributionEntry< IndexType, ValueType > const &entry)
Adds the given entry to the distribution.
storm::storage::FlatSet< uint_fast64_t > EdgeIndexSet
virtual ModelType getModelType() const override
static storm::jani::ModelFeatures getSupportedJaniFeatures()
Returns the jani features with which this builder can deal natively.
virtual std::shared_ptr< storm::storage::sparse::ChoiceOrigins > generateChoiceOrigins(std::vector< boost::any > &dataForChoiceOrigins) const override
virtual void addStateValuation(storm::storage::sparse::state_type const ¤tStateIndex, storm::storage::sparse::StateValuationsBuilder &valuationsBuilder) const override
Adds the valuation for the currently loaded state to the given builder.
virtual StateBehavior< ValueType, StateType > expand(StateToIdCallback const &stateToIdCallback) override
virtual bool isDiscreteTimeModel() const override
virtual std::vector< StateType > getInitialStates(StateToIdCallback const &stateToIdCallback) override
JaniNextStateGenerator(storm::jani::Model const &model, NextStateGeneratorOptions const &options=NextStateGeneratorOptions())
virtual storm::builder::RewardModelInformation getRewardModelInformation(uint64_t const &index) const override
virtual bool isDeterministicModel() const override
virtual bool isPartiallyObservable() const override
virtual std::size_t getNumberOfRewardModels() const override
virtual storm::storage::sparse::StateValuationsBuilder initializeStateValuationsBuilder() const override
Initializes a builder for state valuations by adding the appropriate variables.
static bool canHandle(storm::jani::Model const &model)
A quick check to detect whether the given model is not supported.
NextStateGenerator< ValueType, StateType >::StateToIdCallback StateToIdCallback
virtual storm::models::sparse::StateLabeling label(storm::storage::sparse::StateStorage< StateType > const &stateStorage, std::vector< StateType > const &initialStateIndices={}, std::vector< StateType > const &deadlockStateIndices={}, std::vector< StateType > const &unexploredStateIndices={}) override
virtual void unpackTransientVariableValuesIntoEvaluator(CompressedState const &state, storm::expressions::ExpressionEvaluator< ValueType > &evaluator) const override
Sets the values of all transient variables in the current state to the given evaluator.
std::unique_ptr< storm::expressions::ExpressionEvaluator< ValueType > > evaluator
An evaluator used to evaluate expressions.
bool isSpecialLabel(std::string const &label) const
Checks if the input label has a special purpose (e.g.
void initializeSpecialStates()
Initializes the out-of-bounds state and states with overlapping guards.
virtual storm::storage::sparse::StateValuationsBuilder initializeStateValuationsBuilder() const
Initializes a builder for state valuations by adding the appropriate variables.
std::vector< std::pair< storm::expressions::Expression, bool > > terminalStates
The expressions that define terminal states.
NextStateGeneratorOptions options
The options to be used for next-state generation.
VariableInformation variableInformation
Information about how the variables are packed.
virtual storm::models::sparse::StateLabeling label(storm::storage::sparse::StateStorage< StateType > const &stateStorage, std::vector< StateType > const &initialStateIndices={}, std::vector< StateType > const &deadlockStateIndices={}, std::vector< StateType > const &unexploredStateIndices={})=0
void addChoice(Choice< ValueType, StateType > &&choice)
Adds the given choice to the behavior of the state.
void addStateRewards(std::vector< ValueType > &&stateRewards)
Adds the given state rewards to the behavior of the state.
void setExpanded(bool newValue=true)
Sets whether the state was expanded.
std::string const & getAutomatonName() const
Retrieves the name of the automaton this composition element refers to.
bool isBooleanType() const
virtual bool isAutomatonComposition() const
virtual bool isParallelComposition() const
AutomatonComposition const & asAutomatonComposition() const
ParallelComposition const & asParallelComposition() const
storm::expressions::Expression const & getProbability() const
Retrieves the probability of choosing this destination.
bool hasTransientAssignment() const
Retrieves whether this destination has transient assignments.
OrderedAssignments const & getOrderedAssignments() const
Retrieves the assignments to make when choosing this destination.
uint64_t getLocationIndex() const
Retrieves the id of the destination location.
uint64_t getActionIndex() const
Retrieves the id of the action with which this edge is labeled.
bool hasRate() const
Retrieves whether this edge has an associated rate.
uint64_t getSourceLocationIndex() const
Retrieves the index of the source location.
OrderedAssignments const & getAssignments() const
Retrieves the assignments of this edge.
storm::expressions::Expression const & getRate() const
Retrieves the rate of this edge.
int64_t const & getHighestAssignmentLevel() const
Retrieves the highest assignment level occurring in a destination assignment If no assignment exists,...
std::size_t getNumberOfDestinations() const
Retrieves the number of destinations of this edge.
int64_t const & getLowestAssignmentLevel() const
Retrieves the lowest assignment level occurring in a destination assignment.
EdgeDestination const & getDestination(uint64_t index) const
Retrieves the destination with the given index.
virtual bool isBasicType() const
BasicType const & asBasicType() const
OrderedAssignments const & getAssignments() const
Retrieves the assignments of this location.
ModelFeatures & add(ModelFeature const &modelFeature)
void remove(ModelFeature const &modelFeature)
bool hasUndefinedConstants() const
Retrieves whether the model still has undefined constants.
storm::expressions::ExpressionManager & getManager() const
Retrieves the expression manager responsible for the expressions in the model.
std::vector< storm::expressions::Expression > getAllRangeExpressions(std::vector< std::reference_wrapper< storm::jani::Automaton const > > const &automata={}) const
Retrieves a list of expressions that characterize the legal values of the variables in this model.
VariableSet & getGlobalVariables()
Retrieves the variables of this automaton.
storm::expressions::ExpressionManager & getExpressionManager() const
Retrieves the manager responsible for the expressions in the JANI model.
storm::expressions::Expression getRewardModelExpression(std::string const &identifier) const
Retrieves the defining reward expression of the reward model with the given identifier.
static uint64_t encodeAutomatonAndEdgeIndices(uint64_t automatonIndex, uint64_t edgeIndex)
Encode and decode a tuple of automaton and edge index in one 64-bit index.
Composition const & getSystemComposition() const
Retrieves the system composition expression.
void liftTransientEdgeDestinationAssignments(int64_t maxLevel=0)
Lifts the common edge destination assignments of transient variables to edge assignments.
storm::expressions::Expression getInitialStatesExpression() const
Retrieves the expression defining the legal initial values of the variables.
static const uint64_t SILENT_ACTION_INDEX
The index of the silent action.
ModelType const & getModelType() const
Retrieves the type of the model.
bool hasNonTrivialRewardExpression() const
Returns true iff there is a non-trivial reward model, i.e., a reward model that does not consist of a...
bool undefinedConstantsAreGraphPreserving() const
Checks that undefined constants (parameters) of the model preserve the graph of the underlying model.
void pushEdgeAssignmentsToDestinations()
std::vector< std::pair< std::string, storm::expressions::Expression > > getAllRewardModelExpressions() const
Retrieves all available reward model names and expressions of the model.
bool isNonTrivialRewardModelExpression(std::string const &identifier) const
Returns true iff the given identifier corresponds to a non-trivial reward expression i....
bool isDeterministicModel() const
Determines whether this model is a deterministic one in the sense that each state only has one choice...
void simplifyComposition()
Attempts to simplify the composition.
bool isDiscreteTimeModel() const
Determines whether this model is a discrete-time model.
ModelFeatures const & getModelFeatures() const
Retrieves the enabled model features.
Automaton & getAutomaton(std::string const &name)
Retrieves the automaton with the given name.
bool hasNonTrivialInitialStates() const
Retrieves whether there are non-trivial initial states in the model or any of the contained automata.
uint64_t getActionIndex(std::string const &name) const
Get the index of the action.
bool usesAssignmentLevels(bool onlyTransient=false) const
Retrieves whether the model uses an assignment level other than zero.
uint64_t getAutomatonIndex(std::string const &name) const
Retrieves the index of the given automaton.
ArrayEliminatorData eliminateArrays(bool keepNonTrivialArrayAccess=false)
Eliminates occurring array variables and expressions by replacing array variables by multiple basic v...
std::vector< std::reference_wrapper< Constant const > > getUndefinedConstants() const
Retrieves all undefined constants of the model.
bool hasMultipleLevels(bool onlyTransient=false) const
Checks whether the assignments have several levels.
bool empty(bool onlyTransient=false) const
Retrieves whether this set of assignments is empty.
int64_t getLowestLevel(bool onlyTransient=false) const
Retrieves the lowest level among all assignments.
detail::ConstAssignments getNonTransientAssignments() const
Returns all non-transient assignments in this set of assignments.
detail::ConstAssignments getTransientAssignments() const
Returns all transient assignments in this set of assignments.
int64_t getHighestLevel(bool onlyTransient=false) const
Retrieves the highest level among all assignments.
static bool isNoActionInput(std::string const &action)
storm::expressions::Variable const & getExpressionVariable() const
Retrieves the associated expression variable.
bool hasVariable(std::string const &name) const
Retrieves whether this variable set contains a variable with the given name.
Variable const & getVariable(std::string const &name) const
Retrieves the variable with the given name.
detail::ConstVariables< Variable > getTransientVariables() const
Retrieves the transient variables in this variable set.
This class manages the labeling of the state space with a number of (atomic) labels.
A bit vector that is internally represented as a vector of 64-bit values.
void setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value)
Sets the selected number of lowermost bits of the provided value at the given bit index.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
uint_fast64_t getAsInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const
Retrieves the content of the current bit vector at the given index for the given number of bits as an...
static uint_fast64_t getIdentifierForChoicesWithNoOrigin()
void addState(storm::storage::sparse::state_type const &state, std::vector< bool > &&booleanValues={}, std::vector< int64_t > &&integerValues={})
Adds a new state.
virtual std::unique_ptr< storm::solver::SmtSolver > create(storm::expressions::ExpressionManager &manager) const
Creates a new SMT solver instance.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
void unpackStateIntoEvaluator(CompressedState const &state, VariableInformation const &variableInformation, storm::expressions::ExpressionEvaluator< ValueType > &evaluator)
Unpacks the compressed state into the evaluator.
void extractVariableValues(CompressedState const &state, VariableInformation const &variableInformation, std::vector< int64_t > &locationValues, std::vector< bool > &booleanValues, std::vector< int64_t > &integerValues)
Appends the values of the given variables in the given state to the corresponding result vectors.
storm::storage::BitVector CompressedState
bool isDiscreteTimeModel(ModelType const &modelType)
void forEach(std::vector< IteratorType > const &its, std::vector< IteratorType > const &ites, std::function< void(uint64_t, decltype(*std::declval< IteratorType >()))> const &setValueCallback, std::function< bool()> const &newCombinationCallback)
bool isConstant(ValueType const &)
bool isZero(ValueType const &a)
void addOriginData(boost::any const &data)
Adds the given data that specifies the origin of this choice w.r.t.
void addRewards(std::vector< ValueType > &&values)
Adds the given choices rewards to this choice.
void addProbability(StateType const &state, ValueType const &value)
Adds the given probability value to the given state in the underlying distribution.
storm::expressions::Expression transformExpression(storm::expressions::Expression const &arrayExpression) const