Beispiel #1
0
    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)
Beispiel #2
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
Beispiel #3
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
Beispiel #4
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")
Beispiel #5
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
Beispiel #6
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)
Beispiel #7
0
    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
Beispiel #8
0
 def version(self):
     args = [self.location, '-version']
     return run_tool(args, True)
Beispiel #9
0
 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]
Beispiel #10
0
    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
Beispiel #11
0
        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