def check_tools(self): storm_loc = self.get_storm() if storm_loc: try: output = util.run_tool([storm_loc, '--version'], True) except: raise ConfigurationError("Storm is not found at " + storm_loc) if not re.match(r"Storm ", output, re.MULTILINE): raise ConfigurationError("Storm is not found at " + storm_loc) storm_pars_loc = self.get_storm_pars() if storm_pars_loc: try: output = util.run_tool([storm_pars_loc, '--version'], True) except: raise ConfigurationError("Storm-pars is not found at " + storm_pars_loc) if not re.match(r"Storm-pars", output, re.MULTILINE): raise ConfigurationError("Storm-pars is not found at " + storm_pars_loc) prism_loc = self.get_prism() if prism_loc: try: output = util.run_tool([prism_loc, '--version'], True) except: raise ConfigurationError("Prism is not found at " + prism_loc) if not re.match(r"PRISM", output, re.MULTILINE): raise ConfigurationError("Prism is not found at " + prism_loc) param_loc = self.get_param() if param_loc: # TODO check param similar to other tools try: util.run_tool([param_loc], True) except: raise ConfigurationError("Param is not found at " + param_loc) z3_loc = self.get_z3() if z3_loc: try: output = util.run_tool([z3_loc, '--version'], True) except: raise ConfigurationError("Z3 is not found at " + z3_loc) if not re.match(r"Z3", output, re.MULTILINE): raise ConfigurationError("Z3 is not found at " + z3_loc) yices_loc = self.get_yices() if yices_loc: # TODO check yices similar to other tools try: util.run_tool([yices_loc, '-h'], True) except: raise ConfigurationError("Yices is not found at " + yices_loc) isat_loc = self.get_isat() if isat_loc: # TODO check isat similar to other tools try: util.run_tool([isat_loc], True) except: raise ConfigurationError("ISat is not found at " + isat_loc)
def perform_uniform_sampling(self, parameters, region, samples_per_dimension): logger.info("Perform uniform sampling") if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if self.prismfile is None: raise NotEnoughInformationError("model missing") assert len(self.prismfile.parameters) == len( parameters ), "Number of intervals does not match number of parameters" assert samples_per_dimension > 1 if region is None: intervals = parameters.get_parameter_bounds() else: intervals = region.intervals ranges = [ prophesy.data.range.create_range_from_interval( interval, samples_per_dimension, prophesy.config.configuration.get_sampling_epsilon()) for interval in intervals ] range_strings = [ "{0}:{1}:{2}".format(float(r.start), float(r.step), float(r.stop)) for r in ranges ] const_values_string = ",".join([ "{}={}".format(v.name, r) for v, r in zip(parameters, range_strings) ]) constants_string = self.constants.to_key_value_string() if constants_string != "": const_values_string = const_values_string + "," + constants_string ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) fd, resultpath = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) pctlpath = write_string_to_tmpfile(str(self.pctlformula)) args = [ self.location, self.prismfile.location, pctlpath, "-const", const_values_string, "-exportresults", resultpath ] logger.info("Call prism") ret_code = run_tool(args) if ret_code != 0: logger.warning("Return code %s after call with %s", ret_code, " ".join(args)) else: logger.info("Prism call finished successfully") found_parameters, _, samples = read_samples_file( resultpath, parameters) os.remove(resultpath) os.remove(pctlpath) return samples
def get_rational_function(self): logger.info("Compute solution function") if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if not self._has_model_set(): raise NotEnoughInformationError("model missing") if self.drnfile: if self.drnfile.model_type != ModelType.DTMC: raise UnsupportedModel( "Rational functions can only be computed for DTMCs.") elif self.prismfile: if self.prismfile.model_type != ModelType.DTMC: raise UnsupportedModel( "Rational functions can only be computed for DTMCs.") # create a temporary file for the result. ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) fd, resultfile = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) constants_string = self.constants.to_key_value_string( to_float=False) if self.constants else "" args = [ self.parameter_location, '--prop', str(self.pctlformula), '--parametric', '--parametric:resultfile', resultfile, '--elimination:order', 'fwrev' ] if self.bisimulation == BisimulationType.strong: args.append('--bisimulation') if constants_string != "": args.append('-const') args.append(constants_string) if self.drnfile: args += ['-drn', self.drnfile.location] elif self.prismfile: args += ['--prism', self.prismfile.location] logger.info("Call storm") ret_code = run_tool(args, False) if ret_code != 0: raise RuntimeError("Storm crashed with return code %s.", ret_code) else: logger.info("Storm call finished successfully") param_result = read_pstorm_result(resultfile) os.remove(resultfile) return param_result
def get_rational_function(self): logger.info("Compute solution function") if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if self.prismfile is None: raise NotEnoughInformationError("model missing") # create a temporary file for the result. ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) file, resultfile = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(file) constants_string = self.constants.to_key_value_string() args = [ self.location, self.prismfile.location, '--pctl', str(self.pctlformula), '-exportresults', resultfile, '-paramelimorder', 'fwrev' ] if self.bisimulation == BisimulationType.strong: args.append('-parambisim') args.append('strong') if constants_string != "": args.append('-const') args.append(constants_string) args.append('-param') args.append('{}'.format(','.join( [p.name for p in self.prismfile.parameters]))) logger.info("Call prism") ret_code = run_tool(args, False) if ret_code != 0: # TODO throw exception? logger.warning("Return code %s after call with %s", ret_code, " ".join(args)) else: logger.info("Prism call finished successfully") # TODO: return result in correct format result = "" with open(resultfile, 'r') as f: result += f.read() + "\n" os.remove(resultfile) logger.debug("Result: {}".format(result)) raise NotImplementedError("Writing of prism result is not implemented")
def get_parameter_constraints(self): if not self._has_model_set(): raise NotEnoughInformationError("model missing") if self.pctlformula is None: raise NotEnoughInformationError( "pctl formula missing") # TODO not strictly necessary ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) fd, resultfile = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) constants_string = self.constants.to_key_value_string( to_float=False) if self.constants else "" args = [ self.parameter_location, '--prop', str(self.pctlformula), '--parametric', '--parametric:resultfile', resultfile, '--onlyconstraints' ] if constants_string != "": args.append('-const') args.append(constants_string) if self.drnfile: args += ['-drn', self.drnfile.location] elif self.prismfile: args += ['--prism', self.prismfile.location] logger.info("Call storm") ret_code = run_tool(args, False) if ret_code != 0: # TODO throw exception? RuntimeError("Return code %s after call with %s", ret_code, " ".join(args)) else: logger.info("Storm call finished successfully") param_result = read_pstorm_result(resultfile, False) return param_result.welldefined_constraints, param_result.graph_preservation_constraints
def check(self): ensure_dir_exists(configuration.get_intermediate_dir()) (_, resultfile) = tempfile.mkstemp( suffix=".hys", dir=configuration.get_intermediate_dir(), text=True) with open(resultfile, "w") as f: f.write("DECL\n") for decls in self.declstack: for decl in decls: f.write("\t" + decl + ";\n") f.write("EXPR\n") for constrs in self.constraintstack: for constr in constrs: f.write("\t" + constr + ";\n") args = [self.location, resultfile, "--msw=0.0001", "--prabs=0.00001"] result = run_tool(args) logger.debug(result) os.unlink(resultfile)
def sample_single_point(self, parameter_instantiation, result_path=None, pctl_path=None): if result_path is None: fd, result_path = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) if pctl_path is None: pctl_path = write_string_to_tmpfile(str(self.pctlformula)) const_values_string = ",".join([ "{}={}".format(parameter.name, float(val)) for parameter, val in parameter_instantiation.items() ]) constants_string = self.constants.to_key_value_string() if constants_string != "": const_values_string = const_values_string + "," + constants_string args = [ self.location, self.prismfile.location, pctl_path, "-const", const_values_string, "-exportresults", result_path ] logger.info("Call prism...") ret_code = run_tool(args) if ret_code != 0: logger.warning("Return code %s after call with %s", ret_code, " ".join(args)) else: logger.info("Prism call finished successfully") with open(result_path) as f: f.readline() tmp = f.readline() assert tmp is not None assert tmp != "" sample_value = Rational(tmp) return sample_value
def version(self): args = [self.location, '-version'] return run_tool(args, True)
def version(self): args = [self.main_location, '--version'] outputstr = run_tool(args, True) output = outputstr.split("\n") output = output[0].split(maxsplit=1) return output[1]
def check_hyperrectangle(self, parameters, hyperrectangle, threshold, safe): logger.info("Check region") if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if not self._has_model_set(): raise NotEnoughInformationError("model missing") region_string = hyperrectangle.to_region_string(parameters) logger.debug("Region string is {}".format(region_string)) property_to_check = copy.deepcopy(self.pctlformula) property_to_check.bound = OperatorBound(pc.Relation.LESS, threshold) hypothesis = "allviolated" if safe else "allsat" fd, resultfile = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) constants_string = self.constants.to_key_value_string( to_float=False) if self.constants else "" args = [ self.parameter_location, '--prop', str(property_to_check), '--region', region_string, '--hypothesis', hypothesis, '--resultfile', resultfile, '--noillustration' ] if self.bisimulation == BisimulationType.strong: args.append('--bisimulation') if constants_string != "": args.append('-const') args.append(constants_string) if self.drnfile: args += ['-drn', self.drnfile.location] elif self.prismfile: args += ['--prism', self.prismfile.location] logger.info("Call storm") ret_code = run_tool(args, False) if ret_code != 0: logger.warning("Return code %s after call with %s", ret_code, " ".join(args)) raise RuntimeError("Storm-pars crashed.") else: logger.info("Storm call finished successfully") regions = [] with open(resultfile) as f: for line in f: line = line.strip() if line[-1] != ";": raise ValueError("Expect line to end with a semicolon") line = line[:-1] res_line = line.split(":") if len(res_line) != 2: raise ValueError("Unexpected content in result file") if res_line[0] == "AllViolated": if hypothesis == "allviolated": region_result = RegionCheckResult.Satisfied else: assert hypothesis == "allsat" raise RuntimeError("Contradiction of hypothesis") elif res_line[0] == "AllSat": if hypothesis == "allsat": region_result = RegionCheckResult.Satisfied else: assert hypothesis == "allviolated" raise RuntimeError("Contradiction of hypothesis") elif res_line[0] == "ExistsBoth": raise RuntimeError( "Unexpected outcome, something went wrong.") elif res_line[0] == "Unknown": region_result = RegionCheckResult.Unknown elif res_line[0] == "CenterSat" or res_line[ 0] == "CenterViolated": logger.warning("Center sat is not expected.") region_result = RegionCheckResult.Unknown else: raise RuntimeError( "Unexpected content '{}' in result file".format( res_line[0])) region_string_out = res_line[1].strip() region = HyperRectangle.from_region_string( region_string_out, parameters) regions.append((region_result, region)) return regions
def sample_single_point(parameter_instantiation): fd, resultfile = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) os.close(fd) const_values_string = ",".join([ "{}={}".format(parameter.name, val) for parameter, val in parameter_instantiation.items() ]) constants_string = self.constants.to_key_value_string( to_float=False) if self.constants else "" if constants_string != "": const_values_string = const_values_string + "," + constants_string args = [ self. main_location, # Parametric DRN not supported with main version. '--prop', str(self.pctlformula), "-const", const_values_string ] if self.drnfile: args += ['-drn', self.drnfile.location] elif self.prismfile: args += ['--prism', self.prismfile.location] if self.prismfile.model_type == ModelType.CTMC: args += ['-pc'] if self.bisimulation == BisimulationType.strong: args.append('--bisimulation') logger.info("Call storm") ret_code = run_tool(args, quiet=False, outputfile=resultfile) if ret_code != 0: logger.debug("Storm output logged in %s", resultfile) # Do not crash here else: logger.info("Storm call finished successfully") logger.debug("Storm output logged in %s", resultfile) result = None with open(resultfile) as f: result_in_next_line = False for line in f: if result_in_next_line: result = pc.Rational(line) break if "Substitution yielding negative" in line: result = InstantiationResultFlag.NOT_WELLDEFINED ret_code = 0 break match = re.search(r"Result (.*):(.*)", line) if match: # Check for exact result match_exact = re.search(r"(.*) \(approx. .*\)", match.group(2)) if match_exact: result = pc.Rational(match_exact.group(1)) break else: if match.group(2).strip() == "": result_in_next_line = True continue result = pc.Rational(match.group(2)) break if ret_code != 0: raise RuntimeError("Storm crashed.") if result is None: raise RuntimeError( "Could not find result from storm in {}".format( resultfile)) os.remove(resultfile) return result