示例#1
0
    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
示例#2
0
    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
示例#3
0
    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")
示例#4
0
 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
示例#6
0
    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
示例#7
0
    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)
示例#8
0
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")
示例#9
0
    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
示例#10
0
 def get_plots_dir(self):
     dir = self.get(ProphesyConfig.DIRECTORIES, "plots")
     util.ensure_dir_exists(dir)
     return dir
示例#11
0
 def get_intermediate_dir(self):
     dir = self.get(ProphesyConfig.DIRECTORIES, "intermediate_files")
     util.ensure_dir_exists(dir)
     return dir
示例#12
0
    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