コード例 #1
0
    def instantiate(self, one_or_more_pointlikes):
        """Create ParameterInstantiation(s) from point-like objects.

        Returns the same shape as the input, i.e., if the input is a single
        point-like object (i.e., iterable, hopefully of numbers), returns a
        single ParameterInstantiation; for a list of points, returns a list
        of ParameterInstantiations.
        """
        def looks_like_list_of_points(a):
            return isinstance(a, collections.abc.Sequence) and isinstance(
                a[0], collections.abc.Sized) and len(a[0]) == len(self)

        def looks_like_a_single_point(a):
            return isinstance(a, collections.abc.Sized) and len(a) == len(self)

        if looks_like_list_of_points(one_or_more_pointlikes):
            return [
                ParameterInstantiation.from_point(p, self)
                for p in one_or_more_pointlikes
            ]
        elif looks_like_a_single_point(one_or_more_pointlikes):
            return ParameterInstantiation.from_point(one_or_more_pointlikes,
                                                     self)
        else:
            raise RuntimeError(
                "Unexpected shape. This *may* be legitimate. See code and possibly add this case."
            )
コード例 #2
0
    def _divide(self, hyperrectangle, safe, growing, iters):

        minanchor = self._getminanchor(growing, hyperrectangle)
        maxanchor = self._getmaxanchor(growing, hyperrectangle)

        lower = minanchor
        upper = maxanchor
        lower_res = lower
        upper_res = upper

        for i in range(1, iters):
            logger.debug("Anchors are %s and %s", lower, upper)
            center = (lower + upper) * pc.Rational(0.5)
            logger.debug("Evaluating at %s", center)
            results = self._checker.perform_sampling(
                [ParameterInstantiation.from_point(center, self._parameters)],
                True)
            logger.debug("Result: %s", float(list(results.values())[0]))
            if list(results.values())[0] > self.threshold:
                upper = center
                upper_res = center
            else:
                lower = center
                lower_res = center

        below_threshold_region = HyperRectangle.from_extremal_points(
            minanchor, lower_res, boundtype=BoundType.open)
        above_threshold_region = HyperRectangle.from_extremal_points(
            maxanchor, upper_res, boundtype=BoundType.open)

        upper_on_min_projected = Point(minanchor[0], upper_res[1])
        max_on_min_projected = Point(minanchor[0], maxanchor[1])
        min_on_max_projected = Point(maxanchor[0], minanchor[1])
        lower_on_upper_projected = Point(lower_res[0], upper_res[1])

        mini_region = HyperRectangle.from_extremal_points(
            upper_on_min_projected, lower_res, boundtype=BoundType.closed)
        midi_region = HyperRectangle.from_extremal_points(
            max_on_min_projected, upper_res, boundtype=BoundType.closed)
        maxi_region = HyperRectangle.from_extremal_points(
            min_on_max_projected,
            lower_on_upper_projected,
            boundtype=BoundType.closed)

        safe_regions = [above_threshold_region]
        bad_regions = [below_threshold_region]

        logger.debug(
            "Area above: %s; Area below %s; Unknown area: %s (%s %)",
            float(above_threshold_region.size()),
            float(below_threshold_region.size()),
            float(mini_region.size() + midi_region.size() +
                  maxi_region.size()),
            float(100 * (mini_region.size() + midi_region.size() +
                         maxi_region.size()) / hyperrectangle.size()))
        logger.debug("Result: lower: %s upper: %s", lower_res, upper_res)

        return RegionCheckResult.Splitted, (safe_regions, bad_regions, [
            mini_region, midi_region, maxi_region
        ])
コード例 #3
0
    def fail_region(self, homogeneity=False):
        logger.debug("Failed checking the region.")
        # Split region and try again
        regionelem = self.regions[0]

        # failure ony applies for region that was already consistent
        self.regions = self.regions[1:]
        if regionelem.empty_checks == 1 and not homogeneity:
            logger.debug("Region has not been checked for inverse.")
            dist = self._compute_closest_inverse_sample(not regionelem.safe, regionelem.region)
            self.regions.insert(0, _AnnotatedRegion(regionelem.region, regionelem.samples, not regionelem.safe,
                                                    well_defined=regionelem.well_defined,
                                                    graph_preserving=regionelem.graph_preserving,
                                                    closest_inverse_sample_distance=dist))
            self.regions[0].empty_checks = 2
        else:
            logger.debug("Region has to be split.")
            newelems = self.split(regionelem)
            for newregion in newelems:

                wd = regionelem.well_defined
                gp = regionelem.graph_preserving
                if self.checker.supports_only_closed_regions():
                    newregion = newregion.close()
                elif True:#self.checker.prefers_closed_regions():
                    #newregion = newregion.close()
                    solver = Z3CliSolver()
                    solver.run()
                    wd_res = check_welldefinedness(solver, self.parameters, newregion.close(),
                                                   self.gp_constraints + self.wd_constraints)
                    solver.stop()
                    if wd_res == WelldefinednessResult.Welldefined:
                        newregion = newregion.close()
                logger.debug("Add region to consider later: {}".format(newregion))
                newsamples = []

                for pt, safe in regionelem.samples:
                    if not newregion.contains(pt):
                        continue
                    newsamples.append((pt, safe))
                if len(newsamples) == 0:
                    if self.sample_generator:
                        logger.debug("Sampling as there is no sample in the region.")
                        sampledict = self.sample_generator.perform_sampling(
                            [ParameterInstantiation.from_point(newregion.center(), self.parameters)],
                            surely_welldefined=True)
                        hypothesis = list(sampledict.items())[0][1] < self.threshold
                        newsamples = [(newregion.center(), hypothesis)]
                    else:
                        hypothesis = self._guess_hypothesis(newregion)
                else:
                    hypothesis = regionelem.safe

                dist = self._compute_closest_inverse_sample(hypothesis, newregion)
                self.regions.insert(0, _AnnotatedRegion(newregion, newsamples, hypothesis,
                                                        well_defined=wd,
                                                        graph_preserving=gp,
                                                        closest_inverse_sample_distance=dist))

        self._sort_regions()
コード例 #4
0
    def _evaluate(self, smt_model):
        sample = ParameterInstantiation()
        for par in self.parameters:
            value = smt_model[par.name]
            rational = pc.Rational(value)
            sample[par] = rational
        value = self.model_explorer.perform_sampling([sample])[sample]

        return InstantiationResult(sample, value)
コード例 #5
0
 def _smt_model_to_sample(self, smt_model):
     sample = ParameterInstantiation()
     try:
         for par in self.parameters:
             value = smt_model[par.name]
             rational = pc.Rational(value)
             sample[par] = rational
     except ValueError:
         logger.debug("Cannot translate into a rational instance")
         return None
     return sample
コード例 #6
0
 def _evaluate(self, point):
     logger.debug("Evaluating at {}".format(point))
     results = self._checker.perform_sampling(
         [ParameterInstantiation.from_point(point, self._parameters)], True)
     return list(results.values())[0]
コード例 #7
0
    def check_region(self, region, depth=0):
        """
        Check if the given region can be assumed safe or bad based on known samples.
        If samples are mixed, split the region and retry.
        Resulting regions are added to self.regions.
        :param region: Region.
        :param depth: Maximal depth for region refining.
        """
        if depth >= self.check_depth:
            self.parked_regions.append(region)
            return

        if self.checker.supports_only_closed_regions():
            region.region = region.region.close()

        # TODO check graph preserving seperately.
        if region.well_defined == WelldefinednessResult.Undecided:
            logger.info("Check well-definedness for the region")
            solver = Z3CliSolver()
            solver.run()
            wd_res = check_welldefinedness(solver, self.parameters, region.region,
                                           self.gp_constraints + self.wd_constraints)
            solver.stop()
            if wd_res == WelldefinednessResult.Illdefined:
                region.well_defined = WelldefinednessResult.Illdefined
                self.regions.append(region)
                return
            if wd_res == WelldefinednessResult.Welldefined:
                region.well_defined = WelldefinednessResult.Welldefined
                region.graph_preserving = WelldefinednessResult.Welldefined

        if region.well_defined == WelldefinednessResult.Welldefined:
            mixed = True

            if self.sample_generator and len(region.samples) == 0:
                logger.debug("Sampling as there is no sample in the region.")
                sampledict  =  self.sample_generator.perform_sampling([ParameterInstantiation.from_point(region.region.center(), self.parameters)], surely_welldefined=True)
                region.samples = [(region.region.center(), list(sampledict.items())[0][1] > self.threshold)]
                region.empty_checks = 0
            if len(region.samples) == 1:
                hypothesis_safe = region.samples[0][1]
                mixed = False
            elif len(region.samples) == 0:

                hypothesis_safe = self._guess_hypothesis(region.region)
                mixed = False
            elif all([sample[1] for sample in region.samples]):
                # All safe
                hypothesis_safe = True
                mixed = False
            elif all([not sample[1] for sample in region.samples]):
                # All bad
                hypothesis_safe = False
                mixed = False

            if not mixed:
                dist = self._compute_closest_inverse_sample(hypothesis_safe, region.region)
                region.safe = hypothesis_safe
                region.closest_inverse_sample_distance = dist
                self.regions.append(region)
                return

        # Mixed region, split.
        newelems = self.split(region)
        if newelems is None:
            return None
        for newregion in newelems:
            newsamples = []
            for pt, safe in region.samples:
                if newregion.contains(pt):
                    newsamples.append((pt, safe))
            self.check_region(_AnnotatedRegion(newregion, newsamples, well_defined=region.well_defined,
                                               graph_preserving=region.graph_preserving), depth + 1)
コード例 #8
0
ファイル: samplefile.py プロジェクト: oyendrila-dobe/prophesy
def read_samples_file(path, parameters):
    """
    Reads sample files.

    The first line specifies the parameters (with an optional "Result" for the last column).
    The second line optionally specifies a threshold. This is important if we have binary samples,
    (for which we do not know the value, but just whether it is above or below the threshold).
    The remaining lines give the parameter values and the value. This value is either a number or
    "above" or "below".

    :param path:
    :return:
    """
    threshold = None
    with open(path, 'r') as f:
        lines = [l.strip() for l in f.readlines()]
        if len(lines) <= 2:
            raise RuntimeError("Samples file is empty or malformed")

        # read first line with variable names
        parameter_names = lines[0].split()
        if parameter_names[-1] == "Result":
            parameter_names = parameter_names[:-1]
        start = 1

        for par_name, par in zip(parameter_names, parameters):
            if par_name != par.name:
                raise ValueError(
                    "Parameter names {} do not coincide with given parameters {}"
                    .format(parameter_names, parameters))

        #Ignore thresholds
        if lines[1].startswith("Threshold"):
            if len(lines[1].split()) != 2:
                raise IOError("Invalid input on line 2")
            threshold = Rational(lines[1].split()[1])
            start += 1

        samples = InstantiationResultDict(parameters=parameters)
        skip_next = False
        for i, line in enumerate(lines[start:]):
            if skip_next:
                skip_next = False
                continue
            items = line.split()
            if len(items) - 1 != len(parameter_names):
                # Prism reports that probs are negative:
                if line.find("are negative") > 0:
                    coords = map(Rational, items[:len(parameter_names)])
                    samples[ParameterInstantiation.from_point(
                        Point(*coords),
                        parameters)] = InstantiationResultFlag.NOT_WELLDEFINED
                    skip_next = True
                    continue
                logger.error("Invalid input in %s on line %s: '%s'", path,
                             str(i + start), line)
                continue
            if items[-1] == "below":
                #TODO
                raise NotImplementedError(
                    "Inexact sampling results are not yet supported in v2")
                #value = SAMPLE_BELOW
            elif items[-1] == "above":
                #TODO
                raise NotImplementedError(
                    "Inexact sampling results are not yet supported in v2")
            elif items[-1] == "InstantiationResultFlag.NOT_WELLDEFINED":
                value = InstantiationResultFlag.NOT_WELLDEFINED
            else:
                value = Rational(items[-1])
            coords = map(Rational, items[:-1])
            samples[ParameterInstantiation.from_point(Point(*coords),
                                                      parameters)] = value

    logger.debug("Parameters: %s", str(parameters))
    return parameters, threshold, samples
コード例 #9
0
 def _mc_check(self, param_values):
     parameter_assignments = dict([[x, param_values[x.id]] for x in self._variables])
     sample = ParameterInstantiation()
     for x, val in parameter_assignments.items():
         sample[x] = pc.Rational(val)
     return self._model_explorer.mc_single_point(sample)
コード例 #10
0
 def _evaluate_result(self, param_values):
     parameter_assignments = dict([[x, param_values[x.id]] for x in self._variables])
     sample = ParameterInstantiation()
     for x, val in parameter_assignments.items():
         sample[x] = pc.Rational(val)
     return sample, self._model_explorer.perform_sampling([sample])