def _build_model(self, instance, with_origins=True, register_stats=True): """ Build a (sparse) model from the given prism program instance :param instance: A highlevel description of the model :param with_origins: If the model is to be analysed with highlevel counterex, then this flag should be true. :param register_stats: Should the stats for this model be registered. Put to False, when the model is just build for debugging purposes. :return: The Markov chain. """ start_mb = time.time() assert len(self.properties) + len(self.qualitative_properties) > 0 or self._optimality if with_origins: raw_formulae = [p.property.raw_formula for p in self.properties] if self._optimality: raw_formulae.append(self._optimality.criterion.raw_formula) options = stormpy.BuilderOptions(raw_formulae) options.set_build_with_choice_origins(True) options.set_add_overlapping_guards_label() model = stormpy.build_sparse_model_with_options(instance, options) else: model = stormpy.build_model(instance, [p.property for p in self.properties]) self._print_overlapping_guards(model) model.reduce_to_state_based_rewards() building_time = time.time() - start_mb if register_stats: self.stats.report_model_building(building_time, model.nr_states) logger.debug("Build model with {} states in {} seconds".format(model.nr_states, building_time)) assert len(model.initial_states) == 1 #logger.debug(instance) return model
def example_simulator_01(): path = stormpy.examples.files.prism_dtmc_die prism_program = stormpy.parse_prism_program(path) model = stormpy.build_model(prism_program) simulator = stormpy.simulator.create_simulator(model, seed=42) final_outcomes = dict() for n in range(1000): while not simulator.is_done(): observation = simulator.step() if observation not in final_outcomes: final_outcomes[observation] = 1 else: final_outcomes[observation] += 1 simulator.restart() print(final_outcomes) options = stormpy.BuilderOptions([]) options.set_build_state_valuations() model = stormpy.build_sparse_model_with_options(prism_program, options) simulator = stormpy.simulator.create_simulator(model, seed=42) simulator.set_observation_mode(stormpy.simulator.SimulatorObservationMode.PROGRAM_LEVEL) final_outcomes = dict() for n in range(1000): while not simulator.is_done(): observation = simulator.step() if observation not in final_outcomes: final_outcomes[observation] = 1 else: final_outcomes[observation] += 1 simulator.restart() print(", ".join([f"{str(k)}: {v}" for k,v in final_outcomes.items()]))
def build_pomdp(program, formula): options = sp.BuilderOptions([formula]) options.set_build_state_valuations() options.set_build_choice_labels() options.set_build_all_labels() logger.debug("Start building the POMDP") return sp.build_sparse_model_with_options(program, options)
def read_prism(self, sketch_path, constant_str, properties_path): # read PRISM file prism, self.hole_expressions, self.design_space, constant_map = PrismParser.read_prism_sketch( sketch_path, constant_str) # parse specification specification = PrismParser.parse_specification( properties_path, prism, constant_map) # if PRISM describes a DTMC, unfold hole options in jani if prism.model_type == stormpy.storage.PrismModelType.DTMC: # unfold hole options in Jani self.jani_unfolder = JaniUnfolder(prism, self.hole_expressions, specification, self.design_space) specification = self.jani_unfolder.specification quotient_mdp = self.jani_unfolder.quotient_mdp # specification is now finalized and will be used during the # construction of Markov chains self.prism = prism self.update_specification(specification) # construct the quotient if one has not been constructed yet if prism.model_type == stormpy.storage.PrismModelType.MA: quotient_mdp = stormpy.build_sparse_model_with_options( prism, MarkovChain.builder_options) if prism.model_type in [ stormpy.storage.PrismModelType.MDP, stormpy.storage.PrismModelType.POMDP ]: MarkovChain.builder_options.set_build_choice_labels(True) quotient_mdp = stormpy.build_sparse_model_with_options( prism, MarkovChain.builder_options) MarkovChain.builder_options.set_build_choice_labels(False) # forbid overlapping guards og = quotient_mdp.labeling.get_states( "overlap_guards").number_of_set_bits() assert og == 0, "explicit model has overlapping guards" # success self.explicit_quotient = quotient_mdp logger.debug( "Constructed quotient MDP having {} states and {} actions.".format( quotient_mdp.nr_states, quotient_mdp.nr_choices))
def test_choice_origins(self): program, _ = stormpy.parse_jani_model(get_example_path("dtmc", "die.jani")) a = stormpy.FlatSet() options = stormpy.BuilderOptions() options.set_build_with_choice_origins() model = stormpy.build_sparse_model_with_options(program, options) a = model.choice_origins.get_edge_index_set(3)
def build_pomdp(program): options = sp.BuilderOptions([]) options.set_build_state_valuations() options.set_build_choice_labels() options.set_build_all_labels() options.set_build_all_reward_models() model = sp.build_sparse_model_with_options(program, options) model = sp.pomdp.make_canonic(model) return model
def example_simulator_02(): path = stormpy.examples.files.prism_mdp_maze prism_program = stormpy.parse_prism_program(path) model = stormpy.build_model(prism_program) simulator = stormpy.simulator.create_simulator(model, seed=42) # 5 paths of at most 20 steps. paths = [] for m in range(5): path = [] state, reward, labels = simulator.restart() path = [f"{state}"] for n in range(20): actions = simulator.available_actions() select_action = random.randint(0,len(actions)-1) #print(f"Randomly select action nr: {select_action} from actions {actions}") path.append(f"--act={actions[select_action]}-->") state, reward, labels = simulator.step(actions[select_action]) #print(state) path.append(f"{state}") if simulator.is_done(): #print("Trapped!") break paths.append(path) for path in paths: print(" ".join(path)) options = stormpy.BuilderOptions() options.set_build_state_valuations() options.set_build_choice_labels(True) model = stormpy.build_sparse_model_with_options(prism_program, options) print(model) simulator = stormpy.simulator.create_simulator(model, seed=42) simulator.set_observation_mode(stormpy.simulator.SimulatorObservationMode.PROGRAM_LEVEL) simulator.set_action_mode(stormpy.simulator.SimulatorActionMode.GLOBAL_NAMES) # 5 paths of at most 20 steps. paths = [] for m in range(5): path = [] state, reward, labels = simulator.restart() path = [f"{state}"] for n in range(20): actions = simulator.available_actions() select_action = random.randint(0,len(actions)-1) #print(f"Randomly select action nr: {select_action} from actions {actions}") path.append(f"--act={actions[select_action]}-->") state, reward, labels = simulator.step(actions[select_action]) #print(state) path.append(f"{state}") if simulator.is_done(): #print("Trapped!") break paths.append(path) for path in paths: print(" ".join(path))
def restrict_prism(self, assignment): assert assignment.size == 1 substitution = {} for hole_index, hole in enumerate(assignment): ev = self.prism.get_constant(hole.name).expression_variable expr = self.hole_expressions[hole_index][hole.options[0]] substitution[ev] = expr program = self.prism.define_constants(substitution) model = stormpy.build_sparse_model_with_options( program, MarkovChain.builder_options) return model
def test_label(self): program = stormpy.parse_prism_program( get_example_path("dtmc", "brp-16-2.pm")) properties = stormpy.parse_properties_for_prism_program( "P=? [ F s=5 ]", program) options = stormpy.BuilderOptions([p.raw_formula for p in properties]) options.set_build_choice_labels(True) model = stormpy.build_sparse_model_with_options(program, options) clabeling = model.choice_labeling clabels = clabeling.get_labels() assert len(clabels) == 7 assert "aB" in clabels assert "aA" in clabels assert "NewFile" in clabeling.get_labels_of_choice(0) assert "aG" in clabeling.get_labels_of_choice(7)
def build_model(self): ## Different build functions depending on the model format. if self.file_type == ".prism" or self.file_type == ".jani": ## Defining build options to ensure that choice labels remain. options = stormpy.BuilderOptions() options.set_build_state_valuations() options.set_build_choice_labels() self.model = stormpy.build_sparse_model_with_options( self.program, options) elif self.file_type == ".drn": ## Defining build options to ensure that choice labels remain. parser_options = stormpy.DirectEncodingParserOptions() parser_options.build_choice_labels = True self.model = stormpy.build_model_from_drn(self.file_path, parser_options) else: raise Exception("Model file type not supported to build models")
def createHypothesis(self): print() print('Building hypothesis MRM...') RM = self.OT.build_hypothesis() print('Hypothesis MRM built !') self.buildProductAutomaton( RM) # Write the prism file with the hypothesis program = stormpy.parse_prism_program(TMP_MODEL_PATH) properties = stormpy.parse_properties_for_prism_program( "Rmax=? [ LRA ]", program) options = stormpy.BuilderOptions(True, True) #To keep rewards and labels self.h = stormpy.build_sparse_model_with_options(program, options) self.result_h = stormpy.model_checking(self.h, properties[0], extract_scheduler=True).at(0) self.scheduler = stormpy.model_checking( self.h, properties[0], extract_scheduler=True).scheduler
def example_analysis_04(): path = stormpy.examples.files.prism_dtmc_die prism_program = stormpy.parse_prism_program(path) formula_str = "P=? [F s=7 & d=2]" properties = stormpy.parse_properties(formula_str, prism_program) options = stormpy.BuilderOptions([p.raw_formula for p in properties]) options.set_build_state_valuations() model = stormpy.build_sparse_model_with_options(prism_program, options) result = stormpy.model_checking(model, properties[0]) # Print the model checking result for all states print("Model checking results:") for i in range(len(model.states)): print("\tstate #{}\t {}:\t {}".format( i, model.state_valuations.get_string(i), result.at(i)))
def build_model(self, jani_program, formulae, alt_formulae): if self._model: logger.warning("Rebuilding a model...") logger.info("Build model...") options = stormpy.BuilderOptions(formulae) options.set_build_with_choice_origins(True) options.set_add_overlapping_guards_label() self._formulae = formulae self._alt_formulae = alt_formulae self._expression_manager = jani_program.expression_manager result = stormpy.build_sparse_model_with_options(jani_program, options) logger.info( "done. Model has {} states, {} actions and {} transitions".format( result.nr_states, result.nr_choices, result.nr_transitions)) self._model = result self._submodel = self._model self._print_overlapping_guards(self._model) return self._model
def build_model(program, formula, exact_arithmetic): """ Takes a model and a formula that describes the bad event. :param program: PRISM program :param formula: a PCTL specification for a bad event :param exact_arithmetic: Flag for using exact arithmetic. :return: A sparse MDP """ options = sp.BuilderOptions([formula]) options.set_build_state_valuations() options.set_build_observation_valuations() options.set_build_choice_labels() options.set_build_all_labels() logger.debug("Start building the MDP") if exact_arithmetic: return sp.build_sparse_exact_model_with_options(program, options) else: return sp.build_sparse_model_with_options(program, options)
def main(): path = stormpy.examples.files.prism_pomdp_maze prism_program = stormpy.parse_prism_program(path) options = stormpy.BuilderOptions() options.set_build_state_valuations() options.set_build_choice_labels() pomdp = stormpy.build_sparse_model_with_options(prism_program, options) pomdp = stormpy.pomdp.make_canonic(pomdp) memory_builder = stormpy.pomdp.PomdpMemoryBuilder() memory = memory_builder.build( stormpy.pomdp.PomdpMemoryPattern.selective_counter, 2) pomdp = stormpy.pomdp.unfold_memory(pomdp, memory,\ add_memory_labels=True, keep_state_valuations=True) pomdp = stormpy.pomdp.make_simple(pomdp, keep_state_valuations=True) pmc = stormpy.pomdp.apply_unknown_fsc( pomdp, stormpy.pomdp.PomdpFscApplicationMode.simple_linear) stormpy.export_to_drn(pmc, "test.drn") test = stormpy.build_parametric_model_from_drn("test.drn")
def execute(self): to_add = [self.states[-1]] while len(to_add) > 0: next_add = to_add.pop(0) to_add += self.createNewMdp(next_add[0], next_add[1]) self.createPrismModel() program = stormpy.parse_prism_program(TMP_MODEL_PATH) if self.mode == MODE_MAX: prop = 'Pmax=? [F "target"]' if self.mode == MODE_MIN: prop = 'Rmin=? [F "target"]' properties = stormpy.parse_properties_for_prism_program(prop, program) options = stormpy.BuilderOptions(True, True) #To keep rewards and labels built_model = stormpy.build_sparse_model_with_options(program, options) #compute prop--------------------------------------------------------------- result = stormpy.model_checking(built_model, properties[0], extract_scheduler=True) #extract scheduler---------------------------------------------------------- scheduler = result.scheduler #print(scheduler) self.scheduler_nrmdp = [] for i in range(len(self.model.map.states)): self.scheduler_nrmdp.append([]) for j in range(len(self.observations) + 1): self.scheduler_nrmdp[-1].append(-1) for state in built_model.states: if not "sink" in state.labels: state_lbl = self.getStateInNRMDP(state.labels) self.scheduler_nrmdp[state_lbl[0]][ state_lbl[1]] = scheduler.get_choice( state).get_deterministic_choice()
def prism_to_consmdp(filename, constants=None, state_valuations=True, action_labels=True, return_targets=False): """ Build a ConsMDP from a PRISM symbolic description using Stormpy. The model must specify `consumption` reward on each action (choice) and it needs to contain `reload` label. The following code sets the consumption of each action to `1` and marks each state where the variable `rel` is equal to `1` as a reloading state. >>> rewards "consumption" >>> [] true: 1; >>> endrewards >>> label "reload" = (rel=1); The dict `constants` must be given if a parametric prism model is to be read. It must defined all unused constants of the parametric model that affect the model's state space. On the other hand, it must not be defined if the model is not parametric. The format of the dictionary is `{ "constant_name" : constant_value }` where constant value is either an integer or a string that contains a name of other constant. :param filename: Path to the PRISM model. Must be an mdp. :param constants: Dictionary for uninitialized constant initialization. :type: constants: dict[str(constant_names) -> int/str(constant_names)] :param state_valuations: If True (default), set the valuation of states as names in the resulting ConsMDP. :param action_labels: If True (default), copies the choice labels in the PRISM model into the ConsMDP as action labels. :param return_targets: If True (default False), return also the list of states labeled by the label `target`. :return: ConsMDP object for the given model, or `ConsMDP, targets` if `return_targets` """ prism_prog = stormpy.parse_prism_program(filename) if constants is None: constants = {} elif not prism_prog.has_undefined_constants and len(constants) > 0: raise ValueError("There are no constants to be defined") prism_constants = {} man = prism_prog.expression_manager for const, value in constants.items(): var = man.get_variable(const) if type(value) == int: expression = man.create_integer(value) elif type(value) == str: expression = man.get_variable(value).get_expression() # elif type(value) == stormpy.storage.Expression: # expression = value else: raise ValueError("Constants values must be either int, " "str (a name of another constant), or " "a stormpy Expression.") prism_constants[var] = expression prism_prog = prism_prog.define_constants(prism_constants) options = stormpy.BuilderOptions() if state_valuations: options.set_build_state_valuations() if action_labels: options.set_build_choice_labels() model = stormpy.build_sparse_model_with_options(prism_prog, options) res = storm_sparsemdp_to_consmdp(model, state_valuations=state_valuations, action_labels=action_labels, return_targets=return_targets) return res
def __init__(self, prism, hole_expressions, specification, design_space): logger.debug("Constructing JANI program...") # pack properties properties = specification.stormpy_properties() # construct jani jani, new_properties = prism.to_jani(properties) # unpack properties properties = new_properties opt = None eps = None if specification.has_optimality: properties = new_properties[:-1] opt = new_properties[-1] eps = specification.optimality.epsilon # when translating PRISM to JANI, some properties may change their # atoms, so we need to re-wrap all properties properties = [Property(p) for p in properties] optimality_property = OptimalityProperty( opt, eps) if opt is not None else None self.specification = Specification(properties, optimality_property) MarkovChain.initialize(self.specification.stormpy_formulae()) # unfold holes in the program self.hole_expressions = hole_expressions self.jani_unfolded = None self.combination_coloring = None self.edge_to_color = None self.unfold_jani(jani, design_space) # construct the coloring quotient_mdp = stormpy.build_sparse_model_with_options( self.jani_unfolded, MarkovChain.builder_options) # associate each action of a quotient MDP with hole options # TODO handle conflicting colors action_to_hole_options = [] tm = quotient_mdp.transition_matrix for choice in range(quotient_mdp.nr_choices): edges = quotient_mdp.choice_origins.get_edge_index_set(choice) hole_options = {} for edge in edges: combination = self.edge_to_hole_options.get(edge, None) if combination is None: continue for hole_index, option in combination.items(): options = hole_options.get(hole_index, set()) options.add(option) hole_options[hole_index] = options for hole_index, options in hole_options.items(): assert len(options) == 1 hole_options = { hole_index: list(options)[0] for hole_index, options in hole_options.items() } action_to_hole_options.append(hole_options) self.quotient_mdp = quotient_mdp self.action_to_hole_options = action_to_hole_options return