Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All-in-one support #156

Merged
merged 4 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions examples/highlevel_models/02-highlevel-models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import stormpy

import stormpy.examples
import stormpy.examples.files


def example_highlevel_models():
"""
This method considers a grid with a constant V.
We create an all-in-one MDP, i.e., we create an MDP that contains copies for different values of V.
By model checking, we obtain values for different values of V.
"""
path = stormpy.examples.files.prism_mdp_slipgrid_sketch
prism_program = stormpy.parse_prism_program(path)
prop_string = "Rmin=? [F \"target\"]"
properties = stormpy.parse_properties(prop_string, prism_program)
# Note: The following is necessary for the code to work correctly, as otherwise there will be a default initial value injected.
prism_program = prism_program.replace_variable_initialization_by_init_expression()

emgr = prism_program.expression_manager
Vvar = prism_program.get_constant("V")
Vvalues = {2,4,6,8,10,12}
all_in_one_program = prism_program.replace_constant_by_variable(Vvar, emgr.create_integer(min(Vvalues)), emgr.create_integer(max(Vvalues)))
options = [stormpy.Expression.Eq(Vvar.expression_variable.get_expression(), emgr.create_integer(val)) for val in Vvalues]
all_in_one_program.update_initial_states_expression(stormpy.Expression.And(all_in_one_program.initial_states_expression, stormpy.Expression.Disjunction(options)))
print(all_in_one_program)

for v in all_in_one_program.constants:
print(f"Variable {v.name} is {v.definition}")
build_options = stormpy.BuilderOptions([p.raw_formula for p in properties])
build_options.set_build_state_valuations()
sparse_model = stormpy.build_sparse_model_with_options(all_in_one_program, build_options)
print(sparse_model)
result = stormpy.check_model_sparse(sparse_model, properties[0], extract_scheduler=True, only_initial_states=True)
filter_sparse = stormpy.create_filter_initial_states_sparse(sparse_model)
result.filter(filter_sparse)
result_for_vvar = {int(sparse_model.state_valuations.get_integer_value(x, Vvar.expression_variable)) : result.at(x) for x in sparse_model.initial_states}
print(result_for_vvar)

dd_model = stormpy.build_symbolic_model(all_in_one_program)
print(dd_model)
filter_dd = stormpy.create_filter_initial_states_symbolic(dd_model)
result = stormpy.check_model_dd(dd_model, properties[0], only_initial_states=True)
result.filter(filter_dd)

resultvalues = result.get_values()
# Notice that the manager seems to be different than the manager for the prism program. So we solve it like this
result_for_vvar = {int(valuation.get_integer_value(valuation.expression_manager.get_variable("V"))) : mc_result for valuation, mc_result in resultvalues }
print(result_for_vvar)

if __name__ == '__main__':
example_highlevel_models()
2 changes: 2 additions & 0 deletions lib/stormpy/examples/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def _path(folder, file):
prism_mdp_maze = _path("mdp", "maze_2.nm")
"""Prism example for the maze MDP"""
prism_mdp_slipgrid = _path("mdp", "slipgrid.nm")
"""Prism example for the maze MDP towards sketching"""
prism_mdp_slipgrid_sketch = _path("mdp", "slipgrid_sketch.nm")
"""Prism example for a slippery grid with fixed dimensions"""
drn_pomdp_maze = _path("pomdp", "maze.drn")
"""DRN example for the maze POMDP"""
Expand Down
31 changes: 31 additions & 0 deletions lib/stormpy/examples/files/mdp/slipgrid_sketch.nm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
mdp

const double p = 0.4;
const int N = 10;
const int M = 10;
const int V;

module grid
x : [1..N] init 1;
y : [1..M] init 1;
[north] x > 1 -> 1-p: (x'=x-1) + p: (x'=x);
[south] x < V -> 1-p: (x'=x+1) + p: (x'=x);
[east] y > 1 -> 1-p: (y'=y-1) + p: (x'=x);
[west] y < M -> 1-p: (y'=y+1) + p: (x'=x);
endmodule

// reward structure (number of steps to reach the target)
rewards

[east] true : 1;
[west] true : 1;
[north] true : 1;
[south] true : V;

endrewards

// target observation
label "target" = x=3 & y=3;
label "goal" = x=N & y=M;


6 changes: 6 additions & 0 deletions src/storage/prism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <boost/variant.hpp>
#include <boost/algorithm/string/join.hpp>
#include <random>
#include <optional>
#include "src/helpers.h"
#include <storm/storage/expressions/ExpressionManager.h>
#include <storm/storage/expressions/ExpressionEvaluator.h>
Expand Down Expand Up @@ -48,6 +49,11 @@ void define_prism(py::module& m) {
.def("substitute_nonstandard_predicates", &Program::substituteNonStandardPredicates, "Remove nonstandard predicates from the prism program")
.def("used_constants",&Program::usedConstants, "Compute Used Constants")
.def("label_unlabelled_commands", &Program::labelUnlabelledCommands, "Label unlabelled commands", py::arg("name_suggestions"))
.def("replace_variable_initialization_by_init_expression", &Program::replaceVariableInitializationByInitExpression, "Replaces initializations from the individual variables to a init expression.")
.def("replace_constant_by_variable", &Program::replaceConstantByVariable, py::arg("constant"), py::arg("lower_bound"), py::arg("upper_bound"), py::arg("observable") = true, "Operation to take a constant and make it into a global variable (ranging from lower to upper bound).")
.def_property_readonly("has_initial_states_expression", &Program::hasInitialConstruct, "Is an initial states expression given.")
.def_property_readonly("initial_states_expression", [](Program const& p) {return p.hasInitialConstruct() ? std::make_optional(p.getInitialStatesExpression()) : std::nullopt;}, "Get the initial states expression, or none, if none exists")
.def("update_initial_states_expression", &Program::updateInitialStatesExpression, py::arg("new_expression"), "Replace initial expression. Can only be called if initial expression exists.")
.def("has_constant", &Program::hasConstant, py::arg("name"))
.def("get_constant", &Program::getConstant, py::arg("name"), "Requires that the program has a constant with this name")
.def("has_reward_model", [](Program const& p, std::string const& name) {return p.hasRewardModel(name);}, py::arg("name"), "Is a reward model with the specified name defined?")
Expand Down
Loading