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 make_temporary_copy(self): """Makes a temporary copy of itself, which will be deleted automatically. Does nothing if a temporary copy already exists.""" if self._is_temp: return ensure_dir_exists(configuration.get_intermediate_dir()) fd, tmpfile = tempfile.mkstemp( suffix=".pm", dir=configuration.get_intermediate_dir(), text=True) os.close(fd) try: shutil.copyfile(self.location, tmpfile) self.location = tmpfile self._is_temp = True except: os.unlink(tmpfile) raise
def __init__(self, samples, parameters, region, threshold, checker, wd_constraints, gp_constraints, generate_plot=True, allow_homogeneity=False): """ Constructor. :param samples: List of samples. :param parameters: Parameters of the model. :param threshold: Threshold. :param checker: Region checker. :param wd_constraints: Well-defined constraints. :param gp_constraints: Graph-preserving constraints. """ self.safe_samples, self.bad_samples, self.illdefined_samples = samples.copy().split(threshold) self.parameters = parameters self.threshold = threshold self.max_area_sum = region.size() self.checker = checker # Stores all regions as triple ([constraint], polygon representation, bad/safe) self.all_polys = [] self.safe_polys = [] self.bad_polys = [] self.illdefined_polys = [] self.new_samples = {} self.wd_constraints = wd_constraints self.gp_constraints = gp_constraints self._records = [] self._iteration_timer = None # Options for plotting. self._plot_candidates = False self.plot = generate_plot self.plot_source_dir = None self._source_index = 1 if generate_plot and len(self.parameters) > 2: logger.warning("Plotting for more than two dimensions not supported") self.plot = False self.first_pdf = True from prophesy.config import configuration if self.plot: ensure_dir_exists(configuration.get_plots_dir()) _, self.result_file = tempfile.mkstemp(suffix=".pdf", prefix="result_", dir=configuration.get_plots_dir()) self.allow_homogenous_check = allow_homogeneity
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 initEnv(): from prophesy.config import configuration ensure_dir_exists(web_configuration.get_sessions_dir()) ensure_dir_exists(web_configuration.get_results_dir()) ensure_dir_exists(web_configuration.get_examples_dir()) # Check available model checkers, solvers and various other regions # and adjust capabilities based on that global satSolvers, samplers, ppmcs satSolvers = configuration.getAvailableSMTSolvers() samplers = configuration.getAvailableSamplers() ppmcs = configuration.getAvailableParametricMCs() # Preload some result files for easy startup print("Loading default result files...") rat_path = web_configuration.get_examples_dir() try: ratfiles = os.listdir(rat_path) for rfile in ratfiles: fullpath = os.path.join(rat_path, rfile) try: read_pstorm_result(fullpath) default_results[rfile] = fullpath except: pass except: pass print("Done checking environment")
def perform_sampling(self, samplepoints, surely_welldefined=False): if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if self.prismfile is None: raise NotEnoughInformationError("model missing") ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) fd, result_path = tempfile.mkstemp( suffix=".txt", dir=prophesy.config.configuration.get_intermediate_dir(), text=True) pctl_path = write_string_to_tmpfile(str(self.pctlformula)) os.close(fd) samples = InstantiationResultDict({ s: self.sample_single_point(s, result_path, pctl_path) for s in samplepoints }) os.remove(result_path) os.remove(pctl_path) return samples
def get_plots_dir(self): dir = self.get(ProphesyConfig.DIRECTORIES, "plots") util.ensure_dir_exists(dir) return dir
def get_intermediate_dir(self): dir = self.get(ProphesyConfig.DIRECTORIES, "intermediate_files") util.ensure_dir_exists(dir) return dir
def perform_sampling(self, sample_points, surely_welldefined=False): logger.info("Perform batch sampling") if self.pctlformula is None: raise NotEnoughInformationError("pctl formula missing") if not self._has_model_set(): raise NotEnoughInformationError("model missing") # create a temporary file for the result. ensure_dir_exists(prophesy.config.configuration.get_intermediate_dir()) 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 samples = InstantiationResultDict( {p: sample_single_point(p) for p in sample_points}) return samples