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
        ])
Beispiel #2
0
def test_hyperrectangle_vertices():
    i = Interval(0.0, BoundType.closed, 2.0, BoundType.closed)
    j = Interval(4.0, BoundType.closed, 8.0, BoundType.closed)
    r = HyperRectangle(i, j)
    vertices = r.vertices()
    assert len(vertices) == 4
    assert Point(0.0, 4.0) in vertices
    assert Point(2.0, 4.0) in vertices
Beispiel #3
0
    def post(self):
        logger.debug("Samples post request")
        #print(self.request.body)
        sampling_information = json_decode(self.request.body)
        #print(sampling_information)
        coordinates = sampling_information

        # Get the current prism file and save it temporarily
        prism_files = self._get_session("prism-files", {})
        #assert sampling_information["prism_file"] in prism_files
        #prism_file = PrismFile(prism_files[sampling_information["prism_file"]])
        if coordinates is None:
            return self._json_error("Unable to read coordinates", 400)
        result = self._getResultData(self._get_session('current_result', None))
        samples = self._get_session(
            'samples', InstantiationResultDict(parameters=result.parameters))
        socket = self._get_socket()
        sampling_interface = getSampler(self._get_session('sampler'), result)
        coordinates = [Point(Rational(x), Rational(y)) for x, y in coordinates]
        sample_points = result.parameters.instantiate(coordinates)
        new_samples = sampling_interface.perform_sampling(sample_points)
        if socket is not None:
            socket.send_samples(new_samples)

        samples.update(new_samples)
        self._set_session('samples', samples)

        return self._json_ok(_jsonSamples(new_samples))
Beispiel #4
0
 def get_point(self, parameters):
     """Return the Point corresponding to this sample, given variable
     ordering provided as argument
     :param parameters: Must correspond to parameters of this sample point.
     :type parameters: Iterable[Parameter]
     """
     return Point(*[self[par] for par in parameters])
 def get_vertex(self, pick_min_bound):
     """
     Get the vertex that corresponds to the left/right bound for the ith parameter, depending on the argument
     :param pick_min_bound: Array indicating to take the min (True) or the max (False)
     :return: 
     """
     assert len(pick_min_bound) == self.dimension()
     return Point(
         *[(interval.left_bound() if pmb else interval.right_bound())
           for interval, pmb in zip(self.intervals, pick_min_bound)])
 def vertices(self):
     result = []
     for i in range(0, pow(2, self.dimension()), 1):
         num_bits = self.dimension()
         bits = [(i >> bit) & 1 for bit in range(num_bits - 1, -1, -1)]
         result.append(
             Point(*[(self.intervals[i].left_bound() if x ==
                      0 else self.intervals[i].right_bound())
                     for i, x in zip(range(0, self.dimension()), bits)]))
     return result
    def split_by_growing_rectangles(region):
        """
        Split the region according to growing rectangles.
        :param region: Region.
        :return: New regions after splitting.
        """
        logger.debug("Split region {}".format(region.region))

        # Get all anchor points
        bounds = [(interv.left_bound(), interv.right_bound()) for interv in region.region.intervals]
        anchor_points = [Point(*val) for val in itertools.product(*bounds)]

        best_candidate = None
        for anchor in anchor_points:
            for anchor2, safe_anchor in region.samples:
                rectangle = HyperRectangle.from_extremal_points(anchor, anchor2,
                                                                BoundType.closed)  # TODO handle open intervals
                size = rectangle.size()
                if size <= 0 or size >= region.region.size():
                    # Rectangle too small or too large
                    continue
                if best_candidate is not None and size <= best_candidate[0]:
                    # Larger candidate already known
                    continue

                # Check candidate
                valid = True
                for pt, safe in region.samples:
                    if rectangle.contains(pt) and safe != safe_anchor:
                        valid = False
                        break
                if valid:
                    # Found better candidate
                    best_candidate = (size, anchor, anchor2)

        if best_candidate is None:
            # No good sample inside the region found -> split uniformly
            logger.debug("No candidate region found, split uniformly as fallback.")
            return HyperRectangleRegions.split_uniformly_in_every_dimension(region)

        logger.debug(
            "Candidate: {} for anchor {} and sample {}".format(best_candidate[0], best_candidate[1], best_candidate[2]))
        # Construct hyperrectangle for each anchor and the sample point
        result = []
        for anchor in anchor_points:
            new_rectangle = HyperRectangle.from_extremal_points(anchor, best_candidate[2], BoundType.closed)
            result.append(new_rectangle)

        logger.debug("New regions:\n\t{}".format("\n\t".join([str(region) for region in result])))
        return result
def test_perform_sampling(MCType, name):
    tool = MCType()
    prism_file = PrismFile(get_example_path("funny_defined", "fun.pm"))
    pctl_file = PctlFile(get_example_path("funny_defined", "property1.pctl"))
    tool.load_model_from_prismfile(prism_file)
    tool.set_pctl_formula(pctl_file.get(0))

    parameters = copy.copy(prism_file.parameters)
    parameters.make_intervals_closed(
        pc.Rational(pc.Integer(1), pc.Integer(1000)))

    points = [(Point(pc.Rational(0.25), pc.Rational(0.5)))]
    sample_points = parameters.instantiate(points)
    assert len(sample_points) == 1
    result = tool.perform_sampling(sample_points)
    assert len(result) == 1
    for instantiation, val in result.items():
        assert val == pc.Rational(0.75)
Beispiel #9
0
    def perform_uniform_sampling(self, parameters, region,
                                 samples_per_dimension):
        """
        Samples a uniform grid of points.

        Given a list of intervals (i.e., the first and last point;
        for each dimension, in order) and the number of samples per
        dimension, a uniformly-spaced grid of points (the cartesian
        product) is sampled.
        
        :param parameters: Parameters together with their region.
        :param samples_per_dimension: In how many points should the region be divided.
        """
        logger.debug("Uniform sampling: Fallback to sampling list of samples")
        if samples_per_dimension <= 1:
            raise RuntimeError("No. of samples per dimension must be >= 2")

        # points evenly spaced over the interval, for each dimension
        ranges = []

        if region:
            intervals = region.intervals
        else:
            intervals = parameters.get_parameter_bounds()
        for i in intervals:
            minNum = i.left_bound() if i.left_bound_type(
            ) == BoundType.closed else i.left_bound(
            ) + prophesy.config.configuration.get_sampling_epsilon()
            maxNum = i.right_bound() if i.right_bound_type(
            ) == BoundType.closed else i.right_bound(
            ) - prophesy.config.configuration.get_sampling_epsilon()
            ranges.append(
                map(
                    Rational,
                    linspace(float(minNum), float(maxNum),
                             samples_per_dimension)))
        # turned into grid via cartesian product
        all_points = itertools.product(*ranges)
        all_points = [Point(*coords) for coords in all_points]

        sample_points = parameters.instantiate(all_points)

        return self.perform_sampling(sample_points)
    def _shrink(self, hyperrectangle, safe, growing):
        def _iterate_above(min, max):
            i = 0
            result = None
            center = (min + max) * pc.Rational(0.5)
            while i < 7:
                value = self._evaluate(center)
                if value > self.threshold:
                    result = center
                    center = (center + min) * pc.Rational(0.5)
                    i += 1
                else:
                    center = (center + max) * pc.Rational(0.5)
                    i += 2
            return result

        def _iterate_below(min, max):
            i = 0
            result = None
            center = (min + max) * pc.Rational(0.5)
            while i < 7:
                value = self._evaluate(center)
                if value < self.threshold:
                    result = center
                    center = (center + max) * pc.Rational(0.5)
                    i += 1
                else:
                    center = (center + min) * pc.Rational(0.5)
                    i += 2
            return result

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

        value = self._evaluate(minanchor)
        if value > self.threshold:
            logger.debug("Minimum value is {}".format(value))
            return RegionCheckResult.Splitted, ([hyperrectangle], [], [])
        value = self._evaluate(maxanchor)
        if value < self.threshold:
            logger.debug("Maximum value is {}".format(value))
            return RegionCheckResult.Splitted, ([], [hyperrectangle], [])

        safe_regions = []  # [above_threshold_region]
        bad_regions = []  # [below_threshold_region]

        # First, shrink horizontally:
        max_on_min_projected = Point(minanchor[0], maxanchor[1])
        res = _iterate_above(minanchor, max_on_min_projected)
        if res is not None:
            logger.debug("Found {}".format(res))
            reg = HyperRectangle.from_extremal_points(
                res, maxanchor, boundtype=BoundType.closed)
            assert reg.size() > pc.Rational(0)
            logger.debug("Add safe region: {} (type 1)".format(reg))
            safe_regions.append(reg)
            maxanchor = Point(maxanchor[0], res[1])

        min_on_max_projected = Point(maxanchor[0], minanchor[1])
        res = _iterate_above(minanchor, min_on_max_projected)
        if res is not None:
            logger.debug("Found {}".format(res))
            reg = HyperRectangle.from_extremal_points(
                res, maxanchor, boundtype=BoundType.closed)
            assert reg.size() > pc.Rational(0)
            logger.debug("Add safe region: {} (type 2)".format(reg))
            safe_regions.append(reg)
            maxanchor = Point(res[0], maxanchor[1])

        max_on_min_projected = Point(minanchor[0], maxanchor[1])
        res = _iterate_below(max_on_min_projected, maxanchor)
        if res is not None:
            logger.debug("Found {}".format(res))
            reg = HyperRectangle.from_extremal_points(
                res, minanchor, boundtype=BoundType.closed)
            logger.debug("Add bad region: {} (type 1)".format(reg))
            assert reg.size() > pc.Rational(0)
            bad_regions.append(reg)
            minanchor = Point(res[0], minanchor[1])

        min_on_max_projected = Point(maxanchor[0], minanchor[1])
        res = _iterate_below(min_on_max_projected, maxanchor)
        if res is not None:
            logger.debug("Found {}".format(res))
            reg = HyperRectangle.from_extremal_points(
                res, minanchor, boundtype=BoundType.closed)
            logger.debug("Add bad region: {} (type 2)".format(reg))
            assert reg.size() > pc.Rational(0)
            bad_regions.append(reg)
            minanchor = Point(minanchor[0], res[1])

        remaining = HyperRectangle.from_extremal_points(
            minanchor, maxanchor, boundtype=BoundType.closed)
        assert remaining.size() > 0
        logger.debug("Remaining: {}".format(remaining))

        logger.debug(
            "Safe area {}, Bad area {}, Remaining area {} ({} %)".format(
                float(sum([r.size() for r in safe_regions])),
                float(sum([r.size() for r in bad_regions])),
                float(remaining.size()),
                100 * float(remaining.size() / hyperrectangle.size())))

        return RegionCheckResult.Splitted, (safe_regions, bad_regions,
                                            [remaining])
Beispiel #11
0
def test_to_float():
    p = Point(*[3, 4]).to_float()
    assert p[0] == 3.0
 def center(self):
     return Point(*[interval.center() for interval in self.intervals])
Beispiel #13
0
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
Beispiel #14
0
def _coords_to_rational_point(coords):
    return Point(*(pc.Rational(component) for component in coords))