Example #1
0
    def generate_error_samples(self, sample_time, name, golden=False):
        """ Generate sample_nb samples of tree evaluation in the tree's working precision
                    :return an array of samples, absolute errors and relative errors """

        if golden and loadIfExists and os.path.exists(storage_path + name):
            print("Golden distribution is going to be loaded from disk!")
            return True, [], [], []

        print("Generating Samples...")

        rel_err = []
        abs_err = []
        err = []
        values = []
        set_context_precision(self.precision, self.exponent)
        start_time = time.time()
        end_time = 0
        while end_time <= sample_time:
            self.resetInit(self.tree)
            sample, lp_sample = self.evaluate_error_at_sample(self.tree)
            values.append(sample)
            tmp_abs = abs(float(printMPFRExactly(lp_sample)) - sample)
            err.append(sample - float(printMPFRExactly(lp_sample)))
            abs_err.append(tmp_abs)
            rel_err.append(tmp_abs / sample)
            end_time = time.time() - start_time
        self.resetInit(self.tree)
        reset_default_precision()
        print("... Done with generation")
        return False, np.asarray(values), np.asarray(abs_err), np.asarray(
            rel_err), np.asarray(err)
Example #2
0
    def subtraction(self, interval):
        reset_default_precision()
        res_inc_left = False
        res_inc_right = False
        if self.include_lower and interval.include_lower:
            res_inc_left = True
        if self.include_upper and interval.include_upper:
            res_inc_right = True
        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundDown,
                                 precision=mpfr_proxy_precision) as ctx:
            res_left = gmpy2.sub(mpfr(self.lower), mpfr(interval.upper))
        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundUp,
                                 precision=mpfr_proxy_precision) as ctx:
            res_right = gmpy2.sub(mpfr(self.upper), mpfr(interval.lower))

        if res_left <= res_right:
            res_right = round_number_up_to_digits(res_right, self.digits)
            res_left = round_number_down_to_digits(res_left, self.digits)
            return Interval(res_left, res_right, res_inc_left, res_inc_right,
                            self.digits)
        else:
            res_right = round_number_down_to_digits(res_right, self.digits)
            res_left = round_number_up_to_digits(res_left, self.digits)
            return Interval(res_right, res_left, res_inc_right, res_inc_left,
                            self.digits)
Example #3
0
 def _middle_segment(self, x):
     sum = 0.0
     err = x * self.unit_roundoff
     set_context_precision(self.precision, self.exponent)
     z = mpfr(printMPFRExactly(self.inf_val))
     # Loop through all floating point numbers in reduced precision
     while z <= self.sup_val:
         xp = float(printMPFRExactly(z)) / (1.0 - err)
         sum += self.input_distribution.get_piecewise_pdf()(xp) * abs(xp) * self.unit_roundoff / (1.0 - err)
         z = gmpy2.next_above(z)
     reset_default_precision()
     return sum
Example #4
0
 def __init__(self, wrapperInputDistribution, precision, exponent):
     self.wrapperInputDistribution = wrapperInputDistribution
     #self.inputdistribution = self.wrapperInputDistribution.execute()
     #self.inputdistribution.get_piecewise_pdf()
     tmp_value=wrapperInputDistribution.discretization.lower
     self.precision = precision
     self.exponent = exponent
     self.unit_roundoff = 2 ** -self.precision
     set_context_precision(self.precision, self.exponent)
     qValue = printMPFRExactly(mpfr(str(tmp_value)))
     reset_default_precision()
     error = float(tmp_value) - float(qValue)
     self.distribution = ConstDistr(float(error))
     self.distribution.get_piecewise_pdf()
 def _get_min_exponent(self):
     set_context_precision(self.precision, self.exponent)
     inf_val = gmpy2.mpfr(str(self.input_distribution.range_()[0]))
     self.min_sign = gmpy2.sign(inf_val)
     # For some reason the exponent returned by get_exp() is 1 too high and 0 for infinities
     if gmpy2.is_finite(inf_val):
         e = gmpy2.get_exp(inf_val) - 1
     else:
         e = 2 ** (self.exponent - 1)
     if self.min_sign > 0:
         self.min_exp = e
     else:
         if inf_val < -2 ** (float)(e):
             self.min_exp = e + 1
         else:
             self.min_exp = e
     reset_default_precision()
 def _get_max_exponent(self):
     set_context_precision(self.precision, self.exponent)
     sup_val = gmpy2.mpfr(str(self.input_distribution.range_()[1]))
     self.max_sign = gmpy2.sign(sup_val)
     # For some reason the exponent returned by get_exp() is 1 too high and 0 if sup_val is infinite
     if gmpy2.is_finite(sup_val):
         e = gmpy2.get_exp(sup_val) - 1
     else:
         e = 2 ** (self.exponent - 1)
     if self.max_sign < 0:
         self.max_exp = e
     else:
         if sup_val > 2 ** float(e):
             self.max_exp = e + 1
         else:
             self.max_exp = e
     reset_default_precision()
Example #7
0
    def __init__(self, input_distribution, input_name, precision, exponent, polynomial_precision=[0, 0]):
        """
        Constructor interpolates the density function using Chebyshev interpolation
        then uses this interpolation to build a PaCal object:
        the self.distribution attribute which contains all the methods we could possibly want
        Inputs:
        input_distribution: a PaCal object representing the distribution for which we want to compute
                            the rounding error distribution
        precision, exponent: specify the gmpy2 precision environment
        polynomial_precision: default precision as implemented in AbstractErrorModel will typically not converge
                              so it is re-implemented as dynamically setting polynomial_precision. For very low
                              precision, polynomial_precision needs to be high because the function is very
                              discontinuous (there are few floating points so it won't impact performance).
                              For higher precision it needs to be low for performance reason (but it won't impact
                              accuracy because the function becomes much more regular).
        Warning: the relative error is not defined in the interval rounding to 0. In low precision this interval might
                 have a large probability. This will be reflected by the distribution not integrating to 1.
                 Example: Uniform(-2,2) with 3 bit exponent, 4 bit mantissa and default polynomial_precision integrates
                 to 0.926 !
        """

        super(LowPrecisionErrorModel, self).__init__(input_distribution, precision, exponent, polynomial_precision)
        #self.name = "LPError(" + input_distribution.getName() + ")"
        self.name = "LPE_" + input_name
        set_context_precision(self.precision, self.exponent)
        self.inf_val = mpfr(str(self.input_distribution.range_()[0]))
        self.sup_val = mpfr(str(self.input_distribution.range_()[1]))
        if not gmpy2.is_finite(self.inf_val):
            self.inf_val = gmpy2.next_above(self.inf_val)
        if not gmpy2.is_finite(self.sup_val):
            self.sup_val = gmpy2.next_below(self.sup_val)
        self.max_exp = 2 ** (exponent - 1)
        if self.inf_val == 0:
            # take most negative exponent
            self.exp_inf_val = -self.max_exp
        else:
            self.exp_inf_val = floor(log(abs(self.inf_val), 2))
        if self.sup_val == 0:
            # take most negative exponent
            self.exp_sup_val = -self.max_exp
        else:
            self.exp_sup_val = floor(log(abs(self.sup_val), 2))
        reset_default_precision()
        if polynomial_precision == [0, 0]:
            self.polynomial_precision = [floor(400.0 / float(self.precision)), floor(100.0 / float(self.precision))]
Example #8
0
 def perform_interval_operation(self, operator, interval):
     reset_default_precision()
     check_intervals_digits_coincide(self, interval)
     if operator == "+":
         res_interval = self.addition(interval)
     elif operator == "-":
         res_interval = self.subtraction(interval)
     elif operator == "*":
         res_interval = self.multiplication(interval)
     elif operator == "/":
         res_interval = self.division(interval)
     elif operator == "*+":
         plus_one_interval = interval.addition(
             Interval("1.0", "1.0", True, True, self.digits))
         res_interval = self.multiplication(plus_one_interval)
     else:
         print("Interval Operation not supported")
         exit(-1)
     reset_default_precision()
     return res_interval
Example #9
0
    def division(self, interval):
        reset_default_precision()
        tmp_res_left = []
        tmp_res_right = []

        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundDown,
                                 precision=mpfr_proxy_precision) as ctx:
            new_right_lower = gmpy2.div(1.0, mpfr(interval.upper))
            new_right_upper = gmpy2.div(1.0, mpfr(interval.lower))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.lower), mpfr(new_right_lower)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.lower), mpfr(new_right_upper)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.upper), mpfr(new_right_lower)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.upper), mpfr(new_right_upper)))
            min_index = [
                i for i, value in enumerate(tmp_res_left)
                if value == min(tmp_res_left)
            ]

        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundUp,
                                 precision=mpfr_proxy_precision) as ctx:
            new_right_lower = gmpy2.div(1.0, mpfr(interval.upper))
            new_right_upper = gmpy2.div(1.0, mpfr(interval.lower))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.lower), mpfr(new_right_lower)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.lower), mpfr(new_right_upper)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.upper), mpfr(new_right_lower)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.upper), mpfr(new_right_upper)))
            max_index = [
                i for i, value in enumerate(tmp_res_right)
                if value == max(tmp_res_right)
            ]

        # We have to swap the boundaries here   1/[1,2]=[.5, 1]
        new_right_lower_inc = interval.include_upper
        new_right_upper_inc = interval.include_lower

        tmp_bounds = [
            self.include_lower * new_right_lower_inc,
            self.include_lower * new_right_upper_inc,
            self.include_upper * new_right_lower_inc,
            self.include_upper * new_right_upper_inc
        ]

        res_inc_left = any([tmp_bounds[index] for index in min_index])
        res_inc_right = any([tmp_bounds[index] for index in max_index])

        res_left = round_number_down_to_digits(tmp_res_left[min_index[0]],
                                               self.digits)
        res_right = round_number_up_to_digits(tmp_res_right[max_index[0]],
                                              self.digits)

        return Interval(res_left, res_right, res_inc_left, res_inc_right,
                        self.digits)
Example #10
0
    def multiplication(self, interval):
        reset_default_precision()
        tmp_res_left = []
        tmp_res_right = []

        zero_is_included = self.check_zero_is_in_interval(
        ) or interval.check_zero_is_in_interval()

        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundDown,
                                 precision=mpfr_proxy_precision) as ctx:
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.lower), mpfr(interval.lower)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.lower), mpfr(interval.upper)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.upper), mpfr(interval.lower)))
            tmp_res_left.append(
                gmpy2.mul(mpfr(self.upper), mpfr(interval.upper)))
            min_index = [
                i for i, value in enumerate(tmp_res_left)
                if value == min(tmp_res_left)
            ]

        with gmpy2.local_context(gmpy2.context(),
                                 round=gmpy2.RoundUp,
                                 precision=mpfr_proxy_precision) as ctx:
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.lower), mpfr(interval.lower)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.lower), mpfr(interval.upper)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.upper), mpfr(interval.lower)))
            tmp_res_right.append(
                gmpy2.mul(mpfr(self.upper), mpfr(interval.upper)))
            max_index = [
                i for i, value in enumerate(tmp_res_right)
                if value == max(tmp_res_right)
            ]

        tmp_bounds = [
            self.include_lower * interval.include_lower,
            self.include_lower * interval.include_upper,
            self.include_upper * interval.include_lower,
            self.include_upper * interval.include_upper
        ]

        res_inc_left = any([tmp_bounds[index] for index in min_index])
        res_inc_right = any([tmp_bounds[index] for index in max_index])

        min_value = tmp_res_left[min_index[0]]
        max_value = tmp_res_right[max_index[0]]

        if gmpy2.is_zero(min_value) and zero_is_included:
            res_inc_left = True

        if gmpy2.is_zero(max_value) and zero_is_included:
            res_inc_right = True

        res_left = round_number_down_to_digits(min_value, self.digits)
        res_right = round_number_up_to_digits(max_value, self.digits)
        return Interval(res_left, res_right, res_inc_left, res_inc_right,
                        self.digits)