14 if (gspn.getNumberOfTimedTransitions() == 0) {
16 }
else if (gspn.getNumberOfImmediateTransitions() == 0) {
22 uint64_t locId = addLocation(mainAutomaton);
23 addEdges(mainAutomaton, locId);
32 for (
auto const& place :
gspn.getPlaces()) {
33 std::shared_ptr<storm::jani::Variable> janiVar =
nullptr;
34 if (!place.hasRestrictedCapacity()) {
37 expressionManager->integer(place.getNumberOfInitialTokens()),
false);
39 STORM_LOG_ASSERT(place.hasRestrictedCapacity(),
"Place does not have restricted capacity.");
41 expressionManager->integer(place.getNumberOfInitialTokens()),
false,
42 expressionManager->integer(0), expressionManager->integer(place.getCapacity()));
45 STORM_LOG_ASSERT(vars.count(place.getID()) == 0,
"Variable already exists for this place.");
46 vars[place.getID()] = &model->
addVariable(*janiVar);
50uint64_t JaniGSPNBuilder::addLocation(storm::jani::Automaton& automaton) {
51 uint64_t janiLoc = automaton.
addLocation(storm::jani::Location(
"loc"));
56void JaniGSPNBuilder::addEdges(storm::jani::Automaton& automaton, uint64_t locId) {
57 uint64_t lastPriority = -1;
58 storm::expressions::Expression lastPriorityGuard = expressionManager->boolean(
false);
59 storm::expressions::Expression priorityGuard = expressionManager->boolean(
true);
61 for (
auto const& partition : gspn.getPartitions()) {
62 storm::expressions::Expression guard = expressionManager->boolean(
false);
64 STORM_LOG_ASSERT(lastPriority >= partition.priority,
"Priority decreased unexpectedly.");
65 if (lastPriority > partition.priority) {
66 priorityGuard = priorityGuard && !lastPriorityGuard;
67 lastPriority = partition.priority;
69 STORM_LOG_ASSERT(lastPriority == partition.priority,
"Priority mismatch after decrement.");
73 storm::expressions::Expression totalWeight = expressionManager->rational(0.0);
74 for (
auto const& transId : partition.transitions) {
75 auto const& trans = gspn.getImmediateTransitions()[transId];
76 if (trans.noWeightAttached()) {
79 storm::expressions::Expression destguard = expressionManager->boolean(
true);
80 for (
auto const& inPlaceEntry : trans.getInputPlaces()) {
81 destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
83 for (
auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
84 destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
86 totalWeight = totalWeight +
storm::expressions::ite(destguard, expressionManager->rational(trans.getWeight()), expressionManager->rational(0.0));
88 totalWeight = totalWeight.
simplify();
90 std::vector<storm::jani::OrderedAssignments> oas;
91 std::vector<storm::expressions::Expression> probabilities;
92 std::vector<uint64_t> destinationLocations;
93 for (
auto const& transId : partition.transitions) {
94 auto const& trans = gspn.getImmediateTransitions()[transId];
95 if (trans.noWeightAttached()) {
96 std::cout <<
"ERROR -- no weights attached at transition\n";
99 storm::expressions::Expression destguard = expressionManager->boolean(
true);
100 std::vector<storm::jani::Assignment> assignments;
101 for (
auto const& inPlaceEntry : trans.getInputPlaces()) {
102 destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
103 if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) {
104 assignments.emplace_back(storm::jani::LValue(*vars[inPlaceEntry.first]),
105 (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second);
108 for (
auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
109 destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
111 for (
auto const& outputPlaceEntry : trans.getOutputPlaces()) {
112 if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) {
113 assignments.emplace_back(storm::jani::LValue(*vars[outputPlaceEntry.first]),
114 (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second);
116 assignments.emplace_back(
117 storm::jani::LValue(*vars[outputPlaceEntry.first]),
118 (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second - trans.getInputPlaces().at(outputPlaceEntry.first));
122 guard = guard || destguard;
124 oas.emplace_back(assignments);
125 destinationLocations.emplace_back(locId);
126 probabilities.emplace_back(
127 storm::expressions::ite(destguard, (expressionManager->rational(trans.getWeight()) / totalWeight), expressionManager->rational(0.0)));
130 std::shared_ptr<storm::jani::TemplateEdge> templateEdge = std::make_shared<storm::jani::TemplateEdge>((priorityGuard && guard).
simplify());
133 for (
auto const& oa : oas) {
134 templateEdge->addDestination(storm::jani::TemplateEdgeDestination(oa));
138 lastPriorityGuard = lastPriorityGuard || guard;
140 for (
auto const& trans : gspn.getTimedTransitions()) {
142 STORM_LOG_WARN(
"Transitions with rate zero are not allowed in JANI. Skipping this transition");
145 storm::expressions::Expression guard = expressionManager->boolean(
true);
147 std::vector<storm::jani::Assignment> assignments;
148 for (
auto const& inPlaceEntry : trans.getInputPlaces()) {
149 guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
150 if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) {
151 assignments.emplace_back(storm::jani::LValue(*vars[inPlaceEntry.first]),
152 (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second);
155 for (
auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
156 guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
158 for (
auto const& outputPlaceEntry : trans.getOutputPlaces()) {
159 if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) {
160 assignments.emplace_back(storm::jani::LValue(*vars[outputPlaceEntry.first]),
161 (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second);
163 assignments.emplace_back(
164 storm::jani::LValue(*vars[outputPlaceEntry.first]),
165 (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second - trans.getInputPlaces().at(outputPlaceEntry.first));
169 std::shared_ptr<storm::jani::TemplateEdge> templateEdge = std::make_shared<storm::jani::TemplateEdge>(guard);
172 storm::expressions::Expression rate = expressionManager->rational(trans.getRate());
173 if (trans.hasInfiniteServerSemantics() || (trans.hasKServerSemantics() && !trans.hasSingleServerSemantics())) {
174 STORM_LOG_THROW(trans.hasKServerSemantics() || !trans.getInputPlaces().empty(), storm::exceptions::InvalidModelException,
175 "Unclear semantics: Found a transition with infinite-server semantics and without input place.");
176 storm::expressions::Expression enablingDegree;
177 bool firstArgumentOfMinExpression =
true;
178 if (trans.hasKServerSemantics()) {
179 enablingDegree = expressionManager->integer(trans.getNumberOfServers());
180 firstArgumentOfMinExpression =
false;
182 for (
auto const& inPlaceEntry : trans.getInputPlaces()) {
183 storm::expressions::Expression enablingDegreeInPlace =
184 vars[inPlaceEntry.first]->getExpressionVariable() / expressionManager->integer(inPlaceEntry.second);
185 if (firstArgumentOfMinExpression ==
true) {
186 enablingDegree = enablingDegreeInPlace;
187 firstArgumentOfMinExpression =
false;
192 rate = rate * enablingDegree;
195 templateEdge->addDestination(assignments);
201storm::jani::Variable
const& JaniGSPNBuilder::addDeadlockTransientVariable(storm::jani::Model* model, std::string name,
bool ignoreCapacities,
202 bool ignoreInhibitorArcs,
bool ignoreEmptyPlaces) {
203 storm::expressions::Expression transientValue = expressionManager->boolean(
true);
206 std::vector<storm::gspn::Transition const*> transitions;
207 transitions.reserve(gspn.getNumberOfImmediateTransitions() + gspn.getNumberOfTimedTransitions());
208 for (
auto const& t : gspn.getImmediateTransitions()) {
209 transitions.push_back(&t);
211 for (
auto const& t : gspn.getTimedTransitions()) {
212 transitions.push_back(&t);
214 bool firstTransition =
true;
215 for (
auto const& transition : transitions) {
217 storm::expressions::Expression transitionDisabled = expressionManager->boolean(
false);
218 bool firstPlace =
true;
219 if (!ignoreEmptyPlaces) {
220 for (
auto const& placeIdMult : transition->getInputPlaces()) {
221 storm::expressions::Expression placeBlocksTransition =
222 (vars.at(placeIdMult.first)->getExpressionVariable() < expressionManager->integer(placeIdMult.second));
224 transitionDisabled = placeBlocksTransition;
227 transitionDisabled = transitionDisabled || placeBlocksTransition;
231 if (!ignoreInhibitorArcs) {
232 for (
auto const& placeIdMult : transition->getInhibitionPlaces()) {
233 storm::expressions::Expression placeBlocksTransition =
234 (vars.at(placeIdMult.first)->getExpressionVariable() >= expressionManager->integer(placeIdMult.second));
236 transitionDisabled = placeBlocksTransition;
239 transitionDisabled = transitionDisabled || placeBlocksTransition;
243 if (!ignoreCapacities) {
244 for (
auto const& placeIdMult : transition->getOutputPlaces()) {
245 auto const& place = gspn.getPlace(placeIdMult.first);
246 if (place->hasRestrictedCapacity()) {
247 storm::expressions::Expression placeBlocksTransition =
248 (vars.at(placeIdMult.first)->getExpressionVariable() + expressionManager->integer(placeIdMult.second) >
249 expressionManager->integer(place->getCapacity()));
251 transitionDisabled = placeBlocksTransition;
254 transitionDisabled = transitionDisabled || placeBlocksTransition;
260 if (firstTransition) {
261 transientValue = transitionDisabled;
262 firstTransition =
false;
264 transientValue = transientValue && transitionDisabled;
272 auto exprVar = expressionManager->declareBooleanVariable(name);
275 model->
getAutomata().front().getLocations().front().addTransientAssignment(assignment);
280 std::string res = name;
281 while (manager.hasVariable(res)) {
288 std::shared_ptr<storm::logic::AtomicExpressionFormula> atomicFormula,
289 std::string name, std::string description,
bool maximal) {
290 std::vector<storm::jani::Property> standardProperties;
291 std::string dirShort = maximal ?
"Max" :
"Min";
292 std::string dirLong = maximal ?
"maximal" :
"minimal";
294 maximal ? storm::solver::OptimizationDirection::Maximize : storm::solver::OptimizationDirection::Minimize;
295 std::set<storm::expressions::Variable> emptySet;
298 auto reachFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(
301 standardProperties.emplace_back(dirShort +
"PrReach" + name, reachFormula, emptySet,
302 "The " + dirLong +
" probability to eventually reach " + description +
".");
306 auto exprTB = expressionManager->declareRationalVariable(
getUniqueVarName(*expressionManager,
"TIME_BOUND"));
312 auto trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(
true);
313 auto reachTimeBoundFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(
314 std::make_shared<storm::logic::BoundedUntilFormula>(trueFormula, atomicFormula, std::nullopt, tb, tbr),
316 standardProperties.emplace_back(dirShort +
"PrReach" + name +
"TB", reachTimeBoundFormula, emptySet,
317 "The " + dirLong +
" probability to reach " + description +
" within 'TIME_BOUND' steps.");
320 dirShort = maximal ?
"Min" :
"Max";
321 dirLong = maximal ?
"minimal" :
"maximal";
322 optimizationDirection = maximal ? storm::solver::OptimizationDirection::Minimize : storm::solver::OptimizationDirection::Maximize;
325 auto expTimeFormula = std::make_shared<storm::logic::TimeOperatorFormula>(
328 standardProperties.emplace_back(dirShort +
"ExpTime" + name, expTimeFormula, emptySet,
"The " + dirLong +
" expected time to reach " + description +
".");
329 return standardProperties;
333 auto const& deadlockVar = addDeadlockTransientVariable(model,
getUniqueVarName(*expressionManager,
"deadl"));
334 auto deadlockFormula = std::make_shared<storm::logic::AtomicExpressionFormula>(deadlockVar.getExpressionVariable().getExpression());