def elaborate_Gelpia_error_intervals(self, constraints, symbolic_affine): results = {} logging_constraints = [] prob = constraints_probabilities #constraint_dict = {} #for constraint in constraints: # values=constraints[constraint][prob] # constraint_dict[str(constraint)]=[values[0], values[1]] second_order_lower, second_order_upper = \ SymbolicToGelpia(symbolic_affine.center, symbolic_affine.variables, constraints=constraints). \ compute_concrete_bounds(debug=True, zero_output_epsilon=True) center_interval = Interval(second_order_lower, second_order_upper, True, True, digits_for_range) #concrete_symbolic_interval = symbolic_affine.compute_interval_error(center_interval) #results["1"] = Interval(str(concrete_symbolic_interval.lower), # str(concrete_symbolic_interval.upper), # True,True,digits_for_range) print("Error for prob: " + str(prob)) logging_constraints.append((prob, constraints)) constraints_interval = symbolic_affine.compute_interval_error( center_interval, constraints=constraints) results[str(prob)] = Interval(str(constraints_interval.lower), str(constraints_interval.upper), True, True, digits_for_range) return results, logging_constraints
def subtraction(self, affine): new_center = self.center.subtraction(affine.center) new_coefficients = {} keys = set().union(self.coefficients, affine.coefficients) for key in keys: res_int = self.coefficients.get(key, Interval("0","0", True, True, digits_for_range))\ .subtraction(affine.coefficients.get(key, Interval("0","0", True, True, digits_for_range))) new_coefficients[key] = res_int return AffineInstance(new_center, new_coefficients)
def check_expression_is_constant_zero(expression): try: interval = Interval(expression.value, expression.value, True, True, digits_for_range) return check_interval_is_zero(interval) except: return False return False
def do_quantize(self, left_node, operator, right_node): if (operator=="+" or operator=="-") and \ check_interval_is_zero( Interval(left_node.discretization.intervals[0].interval.lower, left_node.discretization.intervals[-1].interval.upper, True, True, digits_for_range)): return False return True
def compute_interval(self): self_coefficients = self.add_all_coefficients_abs_exact() lower_expr = self.center.subtraction(self_coefficients) upper_expr = self.center.addition(self_coefficients) lower_concrete, _ = SymbolicToGelpia( lower_expr, self.variables).compute_concrete_bounds() _, upper_concrete = SymbolicToGelpia( upper_expr, self.variables).compute_concrete_bounds() return Interval(lower_concrete, upper_concrete, True, True, digits_for_range)
def compute_interval(self): with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: res_left = gmpy2.sub(mpfr(self.center.lower), mpfr(self.add_all_coefficients_lower_abs())) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: res_right = gmpy2.add(mpfr(self.center.upper), mpfr(self.add_all_coefficients_upper_abs())) if res_left <= res_right: return Interval( round_number_down_to_digits(res_left, digits_for_range), round_number_up_to_digits(res_right, digits_for_range), True, True, digits_for_range) else: return Interval( round_number_down_to_digits(res_right, digits_for_range), round_number_up_to_digits(res_left, digits_for_range), True, True, digits_for_range)
def round_value_to_interval(str_value): with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: res_left = mpfr(str_value) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: res_right = mpfr(str_value) return Interval( round_number_down_to_digits(res_left, digits_for_range), round_number_up_to_digits(res_right, digits_for_range), True, True, digits_for_range)
def compute_middle_point_given_interval(low, upper): with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: res_left = gmpy2.add(gmpy2.div(mpfr(upper), mpfr("2.0")), gmpy2.div(mpfr(low), mpfr("2.0"))) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: res_right = gmpy2.add(gmpy2.div(mpfr(upper), mpfr("2.0")), gmpy2.div(mpfr(low), mpfr("2.0"))) return Interval( round_number_down_to_digits(res_left, digits_for_range), round_number_up_to_digits(res_right, digits_for_range), True, True, digits_for_range)
def compute_interval_error(self, center_interval, constraints=None): tmp_variables = copy.deepcopy(self.variables) memorize_eps = Interval("-1.0", "1.0", True, True, digits_for_range) for var in tmp_variables: # for the moment there should be one if "eps" in var: memorize_eps = Interval(tmp_variables[var][0], tmp_variables[var][1], True, True, digits_for_range) tmp_variables[var] = ["-1.0", "1.0"] break self_coefficients = self.add_all_coefficients_abs_exact() _, coeff_upper = SymbolicToGelpia(self_coefficients, tmp_variables, constraints).compute_concrete_bounds( debug=True, zero_output_epsilon=True) coeff_interval=Interval("-"+coeff_upper,coeff_upper,True,True,digits_for_range).\ perform_interval_operation("*", memorize_eps) lower_concrete = center_interval.perform_interval_operation( "-", coeff_interval) upper_concrete = center_interval.perform_interval_operation( "+", coeff_interval) return Interval(lower_concrete.lower, upper_concrete.upper, True, True, digits_for_range)
def multiplication(self, affine, recursion_limit_for_pruning, dReal): new_center = self.center.multiplication(affine.center) new_coefficients = {} keys = set().union(self.coefficients, affine.coefficients) for key in keys: second_term = affine.center.multiplication( self.coefficients.get( key, Interval("0", "0", True, True, digits_for_range))) first_term = self.center.multiplication( affine.coefficients.get( key, Interval("0", "0", True, True, digits_for_range))) res = first_term.addition(second_term) new_coefficients[key] = res self_non_linear = Interval(self.add_all_coefficients_lower_abs(), self.add_all_coefficients_upper_abs(), True, True, digits_for_range) affine_non_linear = Interval(affine.add_all_coefficients_lower_abs(), affine.add_all_coefficients_upper_abs(), True, True, digits_for_range) res = self_non_linear.multiplication(affine_non_linear) value = find_max_abs_interval(res) #This MUST positive negative_value = "-" + value interval_value = Interval(negative_value, value, True, True, digits_for_range) if not check_interval_is_zero(interval_value): low_value, up_value = clean_non_linearity_affine( self.coefficients, affine.coefficients, interval_value, recursion_limit_for_pruning, dReal) middle_point_non_linear = AffineManager.compute_middle_point_given_interval( low_value, up_value) uncertainty_non_linear = AffineManager.compute_uncertainty_given_interval( low_value, up_value) new_center = new_center.addition(middle_point_non_linear) new_coefficients.update(uncertainty_non_linear) return AffineInstance(new_center, new_coefficients)
def compute_uncertainty_given_interval(low, upper): coefficients = {} with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: res_left = gmpy2.sub(gmpy2.div(mpfr(upper), mpfr("2.0")), gmpy2.div(mpfr(low), mpfr("2.0"))) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: res_right = gmpy2.sub(gmpy2.div(mpfr(upper), mpfr("2.0")), gmpy2.div(mpfr(low), mpfr("2.0"))) coefficients[AffineManager.get_new_error_index()]=\ Interval(round_number_down_to_digits(res_left, digits_for_range), round_number_up_to_digits(res_right, digits_for_range), True, True, digits_for_range) return coefficients
def compute_non_linearity(self): #tmp_variables=copy.deepcopy(self.variables) #memorize_eps=Interval("-1.0","1.0",True,True,digits_for_range) #for var in tmp_variables: # # for the moment there should be one # if "eps" in var: # memorize_eps=Interval(tmp_variables[var][0], tmp_variables[var][1], True, True, digits_for_range) # tmp_variables[var]=["-1.0","1.0"] # break _, coeff_upper = SymbolicToGelpia( self.expression, self.variables, self.constraints).compute_concrete_bounds(debug=True, zero_output_epsilon=True) interval = Interval("-" + coeff_upper, coeff_upper, True, True, digits_for_range) #lower_concrete=center_interval.perform_interval_operation("-", coeff_interval) #upper_concrete=center_interval.perform_interval_operation("+", coeff_interval) return interval
def createDSIfromDistribution(distribution, n=50): #np.logspace(-9, 5, base=2, num=50) spacing should be done by powers of 2 if distribution.range_()[0]==0.0 and distribution.range_()[-1]==1.0 and use_powers_of_two_spacing: lin_space = powers_of_two_spacing() elif "FTE" in distribution.name and use_powers_of_two_spacing: lin_space = powers_of_two_error(distribution.d.precision) else: lin_space = np.linspace(distribution.range_()[0], distribution.range_()[-1], num=n + 1, endpoint=True) if custom_spacing: try: lin_space = distribution.get_my_spacing() except: lin_space = np.linspace(distribution.range_()[0], distribution.range_()[-1], num=n + 1, endpoint=True) cdf_distr=distribution.get_piecewise_cdf() ret_list=[] for i in range(0, len(lin_space)-1): with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: lower=round_number_down_to_digits(gmpy2.mpfr(lin_space[i]), digits_for_input_discretization) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: upper=round_number_up_to_digits(gmpy2.mpfr(lin_space[i+1]), digits_for_input_discretization) cdf_low_bound=min(1.0, max(0.0, cdf_distr(float(lin_space[i])))) cdf_up_bound=min(1.0, max(0.0, cdf_distr(float(lin_space[i+1])))) cdf_low_string=dec2Str(round_near(cdf_low_bound, digits_for_input_cdf)) cdf_up_string=dec2Str(round_near(cdf_up_bound, digits_for_input_cdf)) pbox = PBox(Interval(lower, upper, True, False, digits_for_range), cdf_low_string, cdf_up_string) ret_list.append(pbox) ret_list=adjust_ret_list(ret_list) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundDown, precision=mpfr_proxy_precision) as ctx: ret_list[0].interval.lower = \ round_number_down_to_digits(gmpy2.mpfr(distribution.a_real), digits_for_input_discretization) with gmpy2.local_context(gmpy2.context(), round=gmpy2.RoundUp, precision=mpfr_proxy_precision) as ctx: ret_list[-1].interval.upper = \ round_number_up_to_digits(gmpy2.mpfr(distribution.b_real), digits_for_input_discretization) ret_list[-1].interval.include_upper = True mixarith=MixedArithmetic(ret_list[0].interval.lower,ret_list[-1].interval.upper,ret_list) return mixarith
def precise_create_exp_for_Gelpia(exact, error, real_precision_constraints): second_order_lower, second_order_upper = \ SymbolicToGelpia(error.center, error.variables, real_precision_constraints). \ compute_concrete_bounds(debug=True, zero_output_epsilon=True) center_interval = Interval(second_order_lower, second_order_upper, True, True, digits_for_range) err_interval = error.compute_interval_error( center_interval, constraints=real_precision_constraints) new_exact = copy.deepcopy(exact) if not check_interval_is_zero(err_interval): err_expression = SymbolicAffineManager.from_Interval_to_Expression( err_interval) new_exact = new_exact.add_constant_expression(err_expression) #The exact form has only a center (no error terms) encoding = "(" + GELPHIA_exponent_function_name + "(" + str( new_exact.center) + "))" return SymbolicAffineInstance(SymExpression(encoding), {}, copy.deepcopy(exact.variables))
def create_discretization(self): lower = self.wrapperInputDistribution.discretization.intervals[ 0].interval.lower upper = self.wrapperInputDistribution.discretization.intervals[ -1].interval.upper with gmpy2.local_context( set_context_precision(self.precision, self.exp), round=(gmpy2.RoundDown if not round_constants_to_nearest else gmpy2.RoundToNearest)) as ctx: lower = round_number_down_to_digits(mpfr(lower), digits_for_range) with gmpy2.local_context( set_context_precision(self.precision, self.exp), round=(gmpy2.RoundUp if not round_constants_to_nearest else gmpy2.RoundToNearest)) as ctx: upper = round_number_up_to_digits(mpfr(upper), digits_for_range) #The following somehow remind of a dirac distribution. return MixedArithmetic(lower, upper, [ PBox(Interval(lower, upper, True, True, digits_for_range), "0.0", "1.0") ])
def inverse(self): self_interval = self.compute_interval() new_coefficients = copy.deepcopy(self.coefficients) if Decimal(self_interval.lower) <= Decimal("0.0") <= Decimal( self_interval.upper): print("Division By Zero") exit(-1) min_a = find_min_abs_interval(self_interval) a = Interval(min_a, min_a, True, True, digits_for_range) max_b = find_max_abs_interval(self_interval) b = Interval(max_b, max_b, True, True, digits_for_range) b_square = b.perform_interval_operation("*", b) alpha = Interval("-1.0", "-1.0", True, True, digits_for_range).perform_interval_operation( "/", b_square) tmp_a = Interval("1.0", "1.0", True, True, digits_for_range).perform_interval_operation("/", a) d_max = tmp_a.perform_interval_operation( "-", alpha.perform_interval_operation("*", a)) tmp_b = Interval("1.0", "1.0", True, True, digits_for_range).perform_interval_operation("/", b) d_min = tmp_b.perform_interval_operation( "-", alpha.perform_interval_operation("*", b)) shift = AffineManager.compute_middle_point_given_interval( d_min.lower, d_max.upper) if Decimal(self_interval.lower) < Decimal("0.0"): shift = shift.multiplication( Interval("-1.0", "-1.0", True, True, digits_for_range)) #Error of the approximation with min-range #radius=AffineManager.compute_uncertainty_given_interval(d_min, d_max) radius = AffineManager.compute_uncertainty_given_interval( d_min.lower, d_max.upper) ##### res = AffineInstance(self.center, new_coefficients) res = res.mult_interval(alpha) res = res.add_constant_interval(shift) #The err radius is not shifted or scaled by shift and alpha #err_radius=AffineManager.get_new_error_index() res.coefficients.update(radius) res.update_interval() #res.coefficients[err_radius]=radius return res
def sum_cdfs(self, pbox): tmp=Interval(self.cdf_low, self.cdf_up, True, True)\ .addition(Interval(pbox.cdf_low, pbox.cdf_up, True, True)) return PBox(None, tmp.lower, tmp.upper)
def from_DSI_to_PBox(edges_lower, values_lower, edges_upper, values_upper): edges_lower=convertListToDecimals(edges_lower) values_lower=convertListToDecimals(values_lower) edges_upper=convertListToDecimals(edges_upper) values_upper=convertListToDecimals(values_upper) #plot_operation(edges_lower,values_lower,values_upper) ret_list=[] if not edges_lower==edges_upper: print("Lists should be identical") exit(-1) pair_values_lower=createPairsFromBounds(values_lower) pair_values_upper=createPairsFromBounds(values_upper) for pair_value_upper in pair_values_upper: index = bisect.bisect_left(values_lower, pair_value_upper[0]) pair_value_upper[1] = True #in case we go out of bounds we take the last one if index==len(values_lower): index=index-1 #the lower bound of the forward box is the one before the current box lower_index=pair_value_upper[2] if lower_index==0: ret_list.append(PBox(Interval(dec2Str(edges_lower[lower_index]), dec2Str(edges_lower[index]), True, False, digits_for_range), "", dec2Str(pair_value_upper[0]))) else: lower_index=lower_index-1 ret_list.append(PBox(Interval(dec2Str(edges_lower[lower_index]), dec2Str(edges_lower[index]), False, False, digits_for_range), "", dec2Str(pair_value_upper[0]))) for pair_value_lower in pair_values_lower: index = bisect.bisect_left(values_upper, pair_value_lower[0]) pair_value_lower[1] = True if index==len(values_upper): index=index-1 if index==pair_value_lower[2]: index=index-1 ret_list.append(PBox(Interval(dec2Str(edges_lower[index]), dec2Str(edges_lower[pair_value_lower[2]]), False, False, digits_for_range), "", dec2Str(pair_value_lower[0]))) continue if index>0: index = index - 1 ret_list.append(PBox(Interval(dec2Str(edges_lower[index]), dec2Str(edges_lower[pair_value_lower[2]]), False, False, digits_for_range), "", dec2Str(pair_value_lower[0]))) continue ret_list.append(PBox(Interval(dec2Str(edges_lower[index]), dec2Str(edges_lower[pair_value_lower[2]]), True, False, digits_for_range), "", dec2Str(pair_value_lower[0]))) #sort by cdf, in case they are equal sort by lower bound ret_list.sort(key=lambda x: (float(x.cdf_up), float(x.interval.lower))) prec="0.0" done=False for elem in ret_list: if (not Decimal(prec)>=Decimal(elem.cdf_up)) and (not done): elem.cdf_low=prec prec=elem.cdf_up else: elem.cdf_low="REMOVE" if elem.cdf_up=="1.0": done=True #remove useless ret_list= [x for x in ret_list if not x.cdf_low=="REMOVE"] ret_list[-1].interval.include_upper=True #plot_operation(edges_lower,values_lower,values_upper) #plot_boxing(ret_list) sum=0 for box in ret_list: sum=sum+Decimal(box.cdf_up)-Decimal(box.cdf_low) print("Check PDF from bounds to intervals: "+str(sum)) return ret_list
def compute_error_affine_form(self): if self.operator == "+": self.affine_error = self.leftoperand.affine_error.perform_affine_operation\ ("+",self.rightoperand.affine_error) elif self.operator == "-": self.affine_error = self.leftoperand.affine_error.perform_affine_operation \ ("-", self.rightoperand.affine_error) elif self.operator == "*": x_erry = self.exact_affines_forms[0].\ perform_affine_operation("*", self.rightoperand.affine_error, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) y_errx=self.exact_affines_forms[1].\ perform_affine_operation("*", self.leftoperand.affine_error, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) errx_erry=self.leftoperand.affine_error.\ perform_affine_operation("*", self.rightoperand.affine_error, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) self.affine_error = x_erry.perform_affine_operation( "+", y_errx.perform_affine_operation("+", errx_erry)) elif self.operator == "/": #val a = Interval.minAbs(rightInterval) #val errorMultiplier: Rational = -one / (a * a) total_affine_right = self.exact_affines_forms[1].\ perform_affine_operation("+", self.rightoperand.affine_error, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) total_interval_right = total_affine_right.compute_interval() if check_zero_is_in_interval(total_interval_right): print("Potential division by zero!") exit(-1) min_abs_string = find_min_abs_interval(total_interval_right) multiplier_interval = Interval( "-1.0", "-1.0", True, True, digits_for_range).perform_interval_operation( "/", Interval(min_abs_string, min_abs_string, True, True, digits_for_range).perform_interval_operation( "*", Interval(min_abs_string, min_abs_string, True, True, digits_for_range))) multiplier_affine = AffineInstance(multiplier_interval, {}) inv_erry = multiplier_affine.perform_affine_operation( "*", self.rightoperand.affine_error) x_err_one_over_y=self.exact_affines_forms[0].\ perform_affine_operation("*", inv_erry, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) one_over_y = self.exact_affines_forms[1].inverse() one_over_y_err_x = one_over_y.perform_affine_operation( "*", self.leftoperand.affine_error, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) errx_err_one_over_y = self.leftoperand.affine_error.\ perform_affine_operation("*", inv_erry, recursion_limit_for_pruning=recursion_limit_for_pruning_error, dReal=False) self.affine_error = x_err_one_over_y.perform_affine_operation( "+", one_over_y_err_x.perform_affine_operation( "+", errx_err_one_over_y)) elif self.operator == "*+": self.affine_error = self.leftoperand.affine_error.\ perform_affine_operation("+", self.exact_affines_forms[0].perform_affine_operation("+", self.leftoperand.affine_error). perform_affine_operation("*",self.rightoperand.discretization.affine)) else: print("Operation not supported!") exit(-1)
def clean_co_domain(pbox, smt_manager, expression_center, divisions_SMT, valid_for_exit_pruning, recursion_limit_for_pruning, start_recursion_limit=0, dReal=True): low, sup, inc_low, inc_sup = pbox.lower, pbox.upper, pbox.include_lower, pbox.include_upper if Decimal(low) == Decimal(sup): return pbox codomain_intervals = linear_space_with_decimals(low, sup, inc_low, inc_sup, divisions_SMT) if len(codomain_intervals) == 0: return pbox exists_true = 0 unknown_counter = 0 for interval in codomain_intervals: tmp_pbox = SMT_Interface.PBoxSolver(interval[0][0], interval[1][0], interval[0][1], interval[1][1]) smt_manager.set_expression_central(expression_center, tmp_pbox) smt_check = smt_manager.check(debug=False, dReal=dReal) if not smt_check: if exists_true >= 1: break else: if smt_check > 1: unknown_counter = unknown_counter + 1 interval[2] = True exists_true = exists_true + 1 if len(codomain_intervals) < divisions_SMT: exists_true = valid_for_exit_pruning + 1 double_check = False for interval in codomain_intervals: if interval[2]: double_check = True break if not double_check: smt_manager.operation_center = () print("Problem with cleaning. Z3:" + str(smt_manager.check(debug=False, dReal=False)) + ", dReal:" + str(smt_manager.check(debug=False, dReal=True))) ret_box = Interval(low, sup, inc_low, inc_sup, digits_for_range) return ret_box for ind, interval in enumerate(codomain_intervals[:-1]): if not interval[2]: low = dec2Str(codomain_intervals[ind + 1][0][0]) inc_low = codomain_intervals[ind + 1][0][1] else: break reversed_codomain = codomain_intervals[::-1] for ind, interval in enumerate(reversed_codomain[:-1]): if not interval[2]: sup = dec2Str(reversed_codomain[ind + 1][1][0]) inc_sup = reversed_codomain[ind + 1][1][1] else: break ret_box = Interval(low, sup, inc_low, inc_sup, digits_for_range) if start_recursion_limit > recursion_limit_for_pruning: print("Hit the recursion limit for pruning!!") print("Limit:" + str(recursion_limit_for_pruning)) print("Low,Sup", low, sup) if unknown_counter > 0: return ret_box if exists_true <= valid_for_exit_pruning and start_recursion_limit <= recursion_limit_for_pruning: return clean_co_domain(ret_box, smt_manager, expression_center, divisions_SMT, valid_for_exit_pruning, recursion_limit_for_pruning, start_recursion_limit=start_recursion_limit + 1, dReal=dReal) return ret_box
def _pbox_dependent_execution(self): left_operand_discr_SMT = copy.deepcopy( self.leftoperand.get_discretization()) right_operand_discr_SMT = copy.deepcopy( self.rightoperand.get_discretization()) expression_left = self.smt_triple[0] expression_right = self.smt_triple[1] smt_manager = self.smt_triple[2] expression_center = create_exp_for_BinaryOperation_SMT_LIB( expression_left, self.operator, expression_right) if self.is_error_computation: self.affine_error.update_interval() domain_affine_SMT = self.affine_error smt_manager.clean_expressions() self.symbolic_affine = self.symbolic_error constraint_expression = self.rightoperand.name #symbolic_affine.center second_order_lower, second_order_upper = \ SymbolicToGelpia(self.symbolic_affine.center,self.symbolic_affine.variables).\ compute_concrete_bounds(zero_output_epsilon=True) center_interval = Interval(second_order_lower, second_order_upper, True, True, digits_for_range) concrete_symbolic_interval = self.symbolic_affine.compute_interval_error( center_interval) print("Error domain: [" + str(concrete_symbolic_interval.lower) + ", " + str(concrete_symbolic_interval.upper) + "]") else: domain_affine_SMT = left_operand_discr_SMT.affine.perform_affine_operation( self.operator, right_operand_discr_SMT.affine) self.symbolic_affine = self.leftoperand.symbolic_affine.perform_affine_operation( self.operator, self.rightoperand.symbolic_affine, self.real_precision_constraints) constraint_expression = None center_interval = None concrete_symbolic_interval = self.symbolic_affine.compute_interval( ) insides_SMT = [] tmp_insides_SMT = [] evaluation_points = set() print("Left-Intervals: " + str(len(left_operand_discr_SMT.intervals))) print("Right-Intervals: " + str(len(right_operand_discr_SMT.intervals))) print("Pruning dependent operation...") pool = MyPool(processes=num_processes_dependent_operation ) #, maxtasksperchild=3) tmp_results = [] for index_left, left_op_box_SMT in enumerate( left_operand_discr_SMT.intervals): for index_right, right_op_box_SMT in enumerate( right_operand_discr_SMT.intervals): domain_interval = left_op_box_SMT.\ interval.perform_interval_operation(self.operator,right_op_box_SMT.interval) intersection_interval = domain_interval.intersection( domain_affine_SMT.interval) if not intersection_interval == empty_interval: intersection_interval = intersection_interval.intersection( concrete_symbolic_interval) if not intersection_interval == empty_interval: tmp_results.append( pool.apply_async( dependentIteration, args=[ index_left, index_right, smt_manager, expression_left, expression_center, expression_right, self.operator, left_op_box_SMT, right_op_box_SMT, domain_affine_SMT, self.is_error_computation, self.symbolic_affine, concrete_symbolic_interval, constraint_expression, center_interval ], callback=tmp_insides_SMT.append)) print("Number of jobs for dependent operation: " + str(len(tmp_results))) pool.close() pool.join() print("\nDone with dependent operation\n") for triple in tmp_insides_SMT: if not triple[2] == empty_interval: inside_box_SMT = PBox(triple[2], "prob", "prob") insides_SMT.append(inside_box_SMT) left_operand_discr_SMT.intervals[triple[0]].add_kid( inside_box_SMT) right_operand_discr_SMT.intervals[triple[1]].add_kid( inside_box_SMT) evaluation_points.add(Decimal(inside_box_SMT.interval.lower)) evaluation_points.add(Decimal(inside_box_SMT.interval.upper)) evaluation_points = sorted(evaluation_points) if len(evaluation_points ) > discretization_points and not self.is_error_computation: step = round(len(evaluation_points) / discretization_points) step = max(1, step) evaluation_points = sorted( set(evaluation_points[::step] + [evaluation_points[-1]])) lp_inst_SMT = LP_with_SMT(self.leftoperand.name, self.rightoperand.name, left_operand_discr_SMT.intervals, right_operand_discr_SMT.intervals, insides_SMT, evaluation_points) upper_bound_cdf_ind_SMT, upper_bound_cdf_val_SMT = lp_inst_SMT.optimize_max( ) lower_bound_cdf_ind_SMT, lower_bound_cdf_val_SMT = lp_inst_SMT.optimize_min( ) print("Done with LP optimization problem") if not lower_bound_cdf_ind_SMT == upper_bound_cdf_ind_SMT: print("Lists should be identical") exit(-1) edge_cdf = lower_bound_cdf_ind_SMT val_cdf_low = lower_bound_cdf_val_SMT val_cdf_up = upper_bound_cdf_val_SMT pboxes = from_DSI_to_PBox(edge_cdf, val_cdf_low, edge_cdf, val_cdf_up) self.discretization = MixedArithmetic.clone_MixedArith_from_Args( domain_affine_SMT, pboxes)
def add_constant_string(self, constant): constant = Interval(constant, constant, True, True, digits_for_range) new_center = self.center.addition(constant) return AffineInstance(new_center, copy.deepcopy(self.coefficients))
def mult_constant_string(self, constant): const_interval = Interval(constant, constant, True, True, digits_for_range) return self.mult_interval(const_interval)