def try_assumptions(self, pot, decompose_variant): self.assumptions += decompose_variant.assumptions self.assumptions = dedup(self.assumptions) symbol_intervals = deepcopy( pot.symbol_intervals ) for assumption in self.assumptions: assumption_deps = assumption.depends() deps_len = len(assumption_deps) if deps_len == 0: if assumption.test() == result.not_possible: return False continue if deps_len == 1: symbol = assumption_deps[0] if symbol not in symbol_intervals: symbol_intervals[symbol] = intervals() lim = decompose(assumption) if not lim: print("[warn] decompose failed:", assumption) return False res = symbol_intervals[symbol] res *= lim if res.is_zero(): return False symbol_intervals[symbol] = res continue for symbol_assumption in decompose_variant.symbol_assumptions: self._add_symbol_assumption(symbol_assumption) self._update_symbol_assumptions() if not self._test_symbol_assumptions(): return False return self.test_by_symbol_intervals(symbol_intervals)
def get_linear_data_intervals(sym_lims, exp): ret = intervals(interval(0, True, 0, True)) expcd = exp.as_coefficients_dict() for mn in expcd: k = expcd[mn] one = intervals(interval(k, False, k, False)) c, mns = mn.as_coeff_mul() for omns in mns: pomns = omns.as_powers_dict() for s in pomns: p = pomns[s] if s in sym_lims: one = one.get_mult_intervals(sym_lims[s].get_intervals_by_pow(p)) else: one = one.get_mult_intervals(intervals(interval(float('-inf'), True, float('inf'), True))) ret = ret.get_add_intervals(one) return ret
def test_linear_assumption(sym_lims, a): a_interval = get_linear_data_intervals(sym_lims, a.exp) if a.sign == '>=': need = intervals(interval(0, False, float('inf'), True)) elif a.sign == '>': need = intervals(interval(0, True, float('inf'), True)) elif a.sign == '<': need = intervals(interval(float('-inf'), True, 0, True)) elif a.sign == '<=': need = intervals(interval(float('-inf'), True, 0, False)) elif a.sign == '==': need = intervals(interval(0, False, 0, False)) elif a.sign == '!=': need = intervals(interval(float('-inf'), True, 0, True)) + interval(0, True, float('inf'), True) else: raise Exception('unknown sign: ', a.sign) result = a_interval * need return not result.is_zero()
def get_poly_interval(a, n, sign, roots): roots = sorted(roots) i = intervals(interval(0, True, 0, True)) if sign == "==": for x in roots: i += interval(x, False, x, False) return i if sign == "!=": r = float("-inf") for x in roots: l, r = r, x i += interval(l, True, r, True) l, r = r, float("inf") i += interval(l, True, r, True) return i need_neg = False strong = True if sign == ">=": strong = False if sign == "<" or sign == "<=": need_neg = True if sign == "<=": strong = False f = get_fx(a, n) neg = False if f(float("-inf")) < 0: neg = True r = float("-inf") for x in roots: l, r = r, x if not neg ^ need_neg: i += interval(l, strong, r, strong) neg = not neg l, r = r, float("inf") if not neg ^ need_neg: i += interval(l, strong, r, strong) return i
def get_intervals(poly, sign, roots, minimum): i = intervals(interval(0, True, 0, True)) if sign == "==": for x in roots: i += interval(x, False, x, False) return i if sign == "!=": r = float("-inf") for x in roots: l, r = r, x i += interval(l, True, r, True) l, r = r, float("inf") i += interval(l, True, r, True) return i need_neg = False strong = True if sign == ">=": strong = False if sign == "<" or sign == "<=": need_neg = True if sign == "<=": strong = False neg = False if poly(minimum - Number(100)).is_negative: neg = True r = float("-inf") for x in roots: l, r = r, x if not neg ^ need_neg: i += interval(l, strong, r, strong) neg = not neg l, r = r, float("inf") if not neg ^ need_neg: i += interval(l, strong, r, strong) return i
def get_linear(res, sign): a_, b_, p = res if len(a_) == 1 and len(b_) <= 1 and p > 0: a, mn_a = a_[0] if len(b_) == 1: b, mn_b = b_[0] else: b, mn_b = 0.0, [] if len(mn_a) == 0 and len(mn_b) == 0: c = -b / a if a < 0: if sign == ">": sign = "<" elif sign == ">=": sign = "<=" if p % 2 == 0: if c <= 0: if sign == ">": return intervals(interval(0, True, float("inf"), True)) elif sign == ">=": return intervals(interval(0, False, float("inf"), True)) elif sign == "==": if c == 0: return intervals(interval(0, False, 0, False)) else: intervals(interval(0, True, 0, True)) elif sign == "!=": if c == 0: return intervals(interval(0, True, float("inf"), True)) else: return intervals(interval(0, False, float("inf"), True)) else: if sign == "<=" and c == 0: return intervals(interval(0, False, 0, False)) return intervals(interval(0, True, 0, True)) d = math.pow(c, 1 / p) if sign == ">": return intervals(interval(float("-inf"), True, -d, True)) + interval(d, True, float("inf"), True) elif sign == ">=": return intervals(interval(float("-inf"), True, -d, False)) + interval(d, False, float("inf"), True) elif sign == "<": return intervals(interval(-d, True, d, True)) elif sign == "<=": return intervals(interval(-d, False, d, False)) elif sign == "==": return intervals(interval(d, False, d, False)) + interval(-d, False, -d, False) elif sign == "!=": return ( intervals(interval(float("-inf"), True, -d, True)) + interval(-d, True, d, True) + interval(d, True, float("inf"), True) ) else: raise Exception("unknown sign: " + sign) if c < 0: d = -math.pow(-c, 1 / p) else: d = math.pow(c, 1 / p) if sign == ">": return intervals(interval(d, True, float("inf"), True)) elif sign == ">=": return intervals(interval(d, False, float("inf"), True)) elif sign == "<": return intervals(interval(float("-inf"), True, d, True)) elif sign == "<=": return intervals(interval(float("-inf"), True, d, False)) elif sign == "==": return intervals(interval(d, False, d, False)) elif sign == "!=": return intervals(interval(float("-inf"), True, d, True)) + interval(d, True, float("inf"), True) else: raise Exception("unknown sign: " + sign) return None
one = one.get_mult_intervals(intervals(interval(float('-inf'), True, float('inf'), True))) ret = ret.get_add_intervals(one) return ret def test_linear_assumption(sym_lims, a): a_interval = get_linear_data_intervals(sym_lims, a.exp) if a.sign == '>=': need = intervals(interval(0, False, float('inf'), True)) elif a.sign == '>': need = intervals(interval(0, True, float('inf'), True)) elif a.sign == '<': need = intervals(interval(float('-inf'), True, 0, True)) elif a.sign == '<=': need = intervals(interval(float('-inf'), True, 0, False)) elif a.sign == '==': need = intervals(interval(0, False, 0, False)) elif a.sign == '!=': need = intervals(interval(float('-inf'), True, 0, True)) + interval(0, True, float('inf'), True) else: raise Exception('unknown sign: ', a.sign) result = a_interval * need return not result.is_zero() def get_ration_data_intervals(sym_lims, exp): num, denom = exp.as_numer_denom() denom_intervals = get_linear_data_intervals(sym_lims, denom) num_intervals = get_linear_data_intervals(sym_lims, num) denom_intervals = denom_intervals.get_dived_intervals() return num_intervals.get_mult_intervals(denom_intervals) if __name__ == "__main__": from sympy import Symbol from sympy.parsing.sympy_parser import parse_expr print(get_linear_data_intervals(dict(), parse_expr('4'))) print(get_linear_data_intervals({Symbol('a'): intervals(interval(float(1), True, float('+inf'), True)) }, parse_expr('4*a'))) print(get_linear_data_intervals({Symbol('a'): intervals(interval(float(1), False, float('+inf'), True)) }, parse_expr('4*a')))