def test_real_is_integer(self): self.assertTrue(Real.is_integer(-1.0)) self.assertTrue(Real.is_integer(0.0)) self.assertTrue(Real.is_integer(1.0)) self.assertTrue(Real.is_integer(42.0)) self.assertFalse(Real.is_integer(-0.5)) self.assertFalse(Real.is_integer(4.2))
def add_datapoint(self, value: Real, weighting: Real = 1.0): """Record a batch-level measurement of the metric. Parameters ---------- value : Real The recorded value. weighting : Real The weight with which this recorded value will contribute to the epoch-level mean.""" if isinstance(value, np.ndarray): value = value.item() self._batch_data_list.append(value) self._running_weighted_sum += weighting * value self._total_weighting += weighting self._cnt_since_epoch += 1
def sympify(a, locals=None, convert_xor=True): """Converts an arbitrary expression to a type that can be used inside sympy. For example, it will convert python int's into instance of sympy.Rational, floats into intances of sympy.Real, etc. It is also able to coerce symbolic expressions which does inherit after Basic. This can be useful in cooperation with SAGE. It currently accepts as arguments: - any object defined in sympy (except maybe matrices [TODO]) - standard numeric python types: int, long, float, Decimal - strings (like "0.09" or "2e-19") - booleans (will leave them unchanged) If the argument is already a type that sympy understands, it will do nothing but return that value. This can be used at the begining of a function to ensure you are working with the correct type. >>> from sympy import * >>> sympify(2).is_integer True >>> sympify(2).is_real True >>> sympify(2.0).is_real True >>> sympify("2.0").is_real True >>> sympify("2e-45").is_real True """ # XXX instead of duplicating _sympify it would be better to call _sympify # directly from here, but a lot of SymPy still calls sympify (no '_') and # this will add unneccesary overhead. # # When everything settles, let's refactor this. # -- kirr if locals is None: locals = {} if isinstance(a, Basic): return a if isinstance(a, BasicType): return a elif isinstance(a, bool): return a elif isinstance(a, (int, long)): return Integer(a) elif isinstance(a, (float, decimal.Decimal)): return Real(a) elif isinstance(a, complex): real, imag = map(sympify, (a.real, a.imag)) ireal, iimag = int(real), int(imag) if ireal + iimag * 1j == a: return ireal + iimag * S.ImaginaryUnit return real + S.ImaginaryUnit * imag elif isinstance(a, (list, tuple, set)): return type(a)([sympify(x) for x in a]) # let's see if 'a' implements conversion methods such as '_sympy_' or # '__int__', that returns a SymPy (by definition) or SymPy compatible # expression, so we just use it for methname, conv in [ ('_sympy_', None), ('__float__', Real), ('__int__', Integer), ]: meth = getattr(a, methname, None) if meth is None: continue # we have to be careful -- calling Class.__int__() almost always is not # a good idea try: v = meth() except TypeError: continue if conv is not None: v = conv(v) return v else: # XXX this is here because of cyclic-import issues from sympy.matrices import Matrix if isinstance(a, Matrix): raise NotImplementedError('matrix support') if not isinstance(a, str): # At this point we were given an arbitrary expression # which does not inherit from Basic and doesn't implement # _sympy_ (which is a canonical and robust way to convert # anything to SymPy expression). # # As a last chance, we try to take "a"'s normal form via str() # and try to parse it. If it fails, then we have no luck and # return an exception a = str(a) if convert_xor: a = a.replace('^', '**') import ast_parser return ast_parser.parse_expr(a, locals) raise SympifyError("%r is NOT a valid SymPy expression" % a)
def _sympify(a): """short version of sympify for internal usage When adding and comparing symbolic expressions, it is unwise to allow e.g. strings to mixin. On the other hand Python integers and floats are allowed. So we don't use full-featured sympify in __add__ and __eq__ methods, but instead use this small-crafted function there instead. >>> Integer(1) == 1 True >>> Integer(1) == '1' False >>> from sympy import Symbol >>> x = Symbol('x') >>> x + 1 1 + x >>> x + '1' Traceback (most recent call last): ... TypeError: unsupported operand type(s) for +: 'Symbol' and 'str' see: sympify """ if isinstance(a, Basic): return a if isinstance(a, BasicType): return a elif isinstance(a, (int, long)): return Integer(a) elif isinstance(a, (float, decimal.Decimal)): return Real(a) elif isinstance(a, complex): real, imag = map(sympify, (a.real, a.imag)) ireal, iimag = int(real), int(imag) if ireal + iimag * 1j == a: return ireal + iimag * S.ImaginaryUnit return real + S.ImaginaryUnit * imag # let's see if 'a' implements conversion methods such as '_sympy_' or # '__int__', that returns a SymPy (by definition) or SymPy compatible # expression, so we just use it for methname, conv in [ ('_sympy_', None), ('__float__', Real), ('__int__', Integer), ]: meth = getattr(a, methname, None) if meth is None: continue # we have to be careful -- calling Class.__int__() almost always is not # a good idea try: v = meth() except TypeError: continue if conv is not None: v = conv(v) return v raise SympifyError("%r is NOT a valid SymPy expression" % (a, ))
def flatten(cls, seq): # apply associativity, separate commutative part of seq c_part = [] # out: commutative factors nc_part = [] # out: non-commutative factors nc_seq = [] coeff = S.One # standalone term # e.g. 3 * ... c_powers = [] # (base,exp) n # e.g. (x,n) for x num_exp = [] # (num-base, exp) y # e.g. (3, y) for ... * 3 * ... order_symbols = None # --- PART 1 --- # # "collect powers and coeff": # # o coeff # o c_powers # o num_exp # # NOTE: this is optimized for all-objects-are-commutative case for o in seq: # O(x) if o.is_Order: o, order_symbols = o.as_expr_variables(order_symbols) # Mul([...]) if o.is_Mul: if o.is_commutative: seq.extend(o.args) # XXX zerocopy? else: # NCMul can have commutative parts as well for q in o.args: if q.is_commutative: seq.append(q) else: nc_seq.append(q) # append non-commutative marker, so we don't forget to # process scheduled non-commutative objects seq.append(NC_Marker) continue # 3 elif o.is_Number: if o is S.NaN or coeff is S.ComplexInfinity and o is S.Zero: # we know for sure the result will be nan return [S.NaN], [], None elif coeff.is_Number: # it could be zoo coeff *= o if coeff is S.NaN: # we know for sure the result will be nan return [S.NaN], [], None continue elif o is S.ComplexInfinity: if not coeff or coeff is S.ComplexInfinity: # we know for sure the result will be nan return [S.NaN], [], None coeff = S.ComplexInfinity continue elif o.is_commutative: # e # o = b b, e = o.as_base_exp() # y # 3 if o.is_Pow and b.is_Number: # get all the factors with numeric base so they can be # combined below, but don't combine negatives unless # the exponent is an integer if b.is_positive or e.is_integer: num_exp.append((b, e)) continue # n n n # (-3 + y) -> (-1) * (3 - y) # # Give powers a chance to become a Mul if that's the # behavior obtained from Add._eval_power() if not Basic.keep_sign and b.is_Add and e.is_Number: cb = b._eval_power(e, terms=True) if cb: c, b = cb coeff *= c c_powers.append((b, e)) # NON-COMMUTATIVE # TODO: Make non-commutative exponents not combine automatically else: if o is not NC_Marker: nc_seq.append(o) # process nc_seq (if any) while nc_seq: o = nc_seq.pop(0) if not nc_part: nc_part.append(o) continue # b c b+c # try to combine last terms: a * a -> a o1 = nc_part.pop() b1, e1 = o1.as_base_exp() b2, e2 = o.as_base_exp() new_exp = e1 + e2 # Only allow powers to combine if the new exponent is # not an Add. This allow things like a**2*b**3 == a**5 # if a.is_commutative == False, but prohibits # a**x*a**y and x**a*x**b from combining (x,y commute). if b1 == b2 and (not new_exp.is_Add): o12 = b1**new_exp # now o12 could be a commutative object if o12.is_commutative: seq.append(o12) continue else: nc_seq.insert(0, o12) else: nc_part.append(o1) nc_part.append(o) # We do want a combined exponent if it would not be an Add, such as # y 2y 3y # x * x -> x # We determine this if two exponents have the same term in as_coeff_mul # # Unfortunately, this isn't smart enough to consider combining into # exponents that might already be adds, so things like: # z - y y # x * x will be left alone. This is because checking every possible # combination can slow things down. # gather exponents of common bases... # in c_powers new_c_powers = [] common_b = {} # b:e for b, e in c_powers: co = e.as_coeff_mul() common_b.setdefault(b, {}).setdefault(co[1], []).append(co[0]) for b, d in common_b.items(): for di, li in d.items(): d[di] = Add(*li) for b, e in common_b.items(): for t, c in e.items(): new_c_powers.append((b, c * Mul(*t))) c_powers = new_c_powers # and in num_exp new_num_exp = [] common_b = {} # b:e for b, e in num_exp: co = e.as_coeff_mul() common_b.setdefault(b, {}).setdefault(co[1], []).append(co[0]) for b, d in common_b.items(): for di, li in d.items(): d[di] = Add(*li) for b, e in common_b.items(): for t, c in e.items(): new_num_exp.append((b, c * Mul(*t))) num_exp = new_num_exp # --- PART 2 --- # # o process collected powers (x**0 -> 1; x**1 -> x; otherwise Pow) # o combine collected powers (2**x * 3**x -> 6**x) # with numeric base # ................................ # now we have: # - coeff: # - c_powers: (b, e) # - num_exp: (2, e) # 0 1 # x -> 1 x -> x for b, e in c_powers: if e is S.Zero: continue if e is S.One: if b.is_Number: coeff *= b else: c_part.append(b) elif e.is_Integer and b.is_Number: coeff *= Pow(b, e) else: c_part.append(Pow(b, e)) # x x x # 2 * 3 -> 6 inv_exp_dict = {} # exp:Mul(num-bases) x x # e.g. x:6 for ... * 2 * 3 * ... for b, e in num_exp: inv_exp_dict.setdefault(e, []).append(b) for e, b in inv_exp_dict.items(): inv_exp_dict[e] = Mul(*b) reeval = False for e, b in inv_exp_dict.items(): if e is S.Zero: continue if e is S.One: if b.is_Number: coeff *= b else: c_part.append(b) elif e.is_Integer and b.is_Number: coeff *= Pow(b, e) else: obj = b**e if obj.is_Mul: # We may have split out a number that needs to go in coeff # e.g., sqrt(6)*sqrt(2) == 2*sqrt(3). See issue 415. reeval = True if obj.is_Number: coeff *= obj else: c_part.append(obj) # oo, -oo if (coeff is S.Infinity) or (coeff is S.NegativeInfinity): new_c_part = [] coeff_sign = 1 for t in c_part: if t.is_positive: continue if t.is_negative: coeff_sign *= -1 continue new_c_part.append(t) c_part = new_c_part new_nc_part = [] for t in nc_part: if t.is_positive: continue if t.is_negative: coeff_sign *= -1 continue new_nc_part.append(t) nc_part = new_nc_part coeff *= coeff_sign # zoo if coeff is S.ComplexInfinity: # zoo might be # unbounded_real + bounded_im # bounded_real + unbounded_im # unbounded_real + unbounded_im # and non-zero real or imaginary will not change that status. c_part = [ c for c in c_part if not (c.is_nonzero and c.is_real is not None) ] nc_part = [ c for c in nc_part if not (c.is_nonzero and c.is_real is not None) ] # 0 elif coeff is S.Zero: # we know for sure the result will be 0 return [coeff], [], order_symbols elif coeff.is_Real: if coeff == Real(0): c_part, nc_part = [coeff], [] elif coeff == Real(1): # change it to One, so it doesn't get inserted to slot0 coeff = S.One # order commutative part canonically c_part.sort(Basic.compare) # current code expects coeff to be always in slot-0 if coeff is not S.One: c_part.insert(0, coeff) # we are done if len(c_part) == 2 and c_part[0].is_Number and c_part[1].is_Add: # 2*(1+a) -> 2 + 2 * a coeff = c_part[0] c_part = [Add(*[coeff * f for f in c_part[1].args])] if reeval: c_part, _, _ = Mul.flatten(c_part) return c_part, nc_part, order_symbols
def flatten(cls, seq): # apply associativity, separate commutative part of seq c_part = [] # out: commutative factors nc_part = [] # out: non-commutative factors nc_seq = [] coeff = S.One # standalone term # e.g. 3 * ... c_powers = [] # (base,exp) n # e.g. (x,n) for x num_exp = [] # (num-base, exp) y # e.g. (3, y) for ... * 3 * ... order_symbols = None # --- PART 1 --- # # "collect powers and coeff": # # o coeff # o c_powers # o num_exp # # NOTE: this is optimized for all-objects-are-commutative case for o in seq: # O(x) if o.is_Order: o, order_symbols = o.as_expr_symbols(order_symbols) # Mul([...]) if o.is_Mul: if o.is_commutative: seq.extend(o.args) # XXX zerocopy? else: # NCMul can have commutative parts as well for q in o.args: if q.is_commutative: seq.append(q) else: nc_seq.append(q) # append non-commutative marker, so we don't forget to # process scheduled non-commutative objects seq.append(NC_Marker) continue # 3 elif o.is_Number: coeff *= o continue elif o.is_commutative: # e # o = b b, e = o.as_base_exp() # y # 3 if o.is_Pow and b.is_Number: # get all the factors with numeric base so they can be # combined below num_exp.append((b, e)) continue # n n n # (-3 + y) -> (-1) * (3 - y) if b.is_Add and e.is_Number: #found factor (x+y)**number; split off initial coefficient c, t = b.as_coeff_terms() #last time I checked, Add.as_coeff_terms returns One or NegativeOne #but this might change if c.is_negative and not e.is_integer: # extracting root from negative number: ignore sign if c is not S.NegativeOne: # make c positive (probably never occurs) coeff *= (-c)**e assert len(t) == 1, ` t ` b = -t[0] #else: ignoring sign from NegativeOne: nothing to do! elif c is not S.One: coeff *= c**e assert len(t) == 1, ` t ` b = t[0] #else: c is One, so pass c_powers.append((b, e)) # NON-COMMUTATIVE # TODO: Make non-commutative exponents not combine automatically else: if o is not NC_Marker: nc_seq.append(o) # process nc_seq (if any) while nc_seq: o = nc_seq.pop(0) if not nc_part: nc_part.append(o) continue # b c b+c # try to combine last terms: a * a -> a o1 = nc_part.pop() b1, e1 = o1.as_base_exp() b2, e2 = o.as_base_exp() if b1 == b2: o12 = b1**(e1 + e2) # now o12 could be a commutative object if o12.is_commutative: seq.append(o12) continue else: nc_seq.insert(0, o12) else: nc_part.append(o1) nc_part.append(o) # We do want a combined exponent if it would not be an Add, such as # y 2y 3y # x * x -> x # We determine this if two exponents have the same term in as_coeff_terms # # Unfortunately, this isn't smart enough to consider combining into # exponents that might already be adds, so thing like: # z - y y # x * x will be left alone. This is because checking every possible # combination can slow things down. new_c_powers = [] common_b = {} # b:e # First gather exponents of common bases for b, e in c_powers: co = e.as_coeff_terms() if b in common_b: if co[1] in common_b[b]: common_b[b][co[1]] += co[0] else: common_b[b][co[1]] = co[0] else: common_b[b] = {co[1]: co[0]} for b, e, in common_b.items(): for t, c in e.items(): new_c_powers.append((b, c * Mul(*t))) c_powers = new_c_powers # And the same for numeric bases new_num_exp = [] common_b = {} # b:e for b, e in num_exp: co = e.as_coeff_terms() if b in common_b: if co[1] in common_b[b]: common_b[b][co[1]] += co[0] else: common_b[b][co[1]] = co[0] else: common_b[b] = {co[1]: co[0]} for b, e, in common_b.items(): for t, c in e.items(): new_num_exp.append((b, c * Mul(*t))) num_exp = new_num_exp # --- PART 2 --- # # o process collected powers (x**0 -> 1; x**1 -> x; otherwise Pow) # o combine collected powers (2**x * 3**x -> 6**x) # with numeric base # ................................ # now we have: # - coeff: # - c_powers: (b, e) # - num_exp: (2, e) # 0 1 # x -> 1 x -> x for b, e in c_powers: if e is S.Zero: continue if e is S.One: if b.is_Number: coeff *= b else: c_part.append(b) elif e.is_Integer and b.is_Number: coeff *= b**e else: c_part.append(Pow(b, e)) # x x x # 2 * 3 -> 6 inv_exp_dict = {} # exp:Mul(num-bases) x x # e.g. x:6 for ... * 2 * 3 * ... for b, e in num_exp: if e in inv_exp_dict: inv_exp_dict[e] *= b else: inv_exp_dict[e] = b for e, b in inv_exp_dict.items(): if e is S.Zero: continue if e is S.One: if b.is_Number: coeff *= b else: c_part.append(b) elif e.is_Integer and b.is_Number: coeff *= b**e else: obj = b**e if obj.is_Number: coeff *= obj else: c_part.append(obj) # oo, -oo if (coeff is S.Infinity) or (coeff is S.NegativeInfinity): new_c_part = [] for t in c_part: if t.is_positive: continue if t.is_negative: coeff = -coeff continue new_c_part.append(t) c_part = new_c_part new_nc_part = [] for t in nc_part: if t.is_positive: continue if t.is_negative: coeff = -coeff continue new_nc_part.append(t) nc_part = new_nc_part # 0, nan elif (coeff is S.Zero) or (coeff is S.NaN): # we know for sure the result will be the same as coeff (0 or nan) return [coeff], [], order_symbols elif coeff.is_Real: if coeff == Real(0): c_part, nc_part = [coeff], [] elif coeff == Real(1): # change it to One, so it doesn't get inserted to slot0 coeff = S.One # order commutative part canonically c_part.sort(Basic.compare) # current code expects coeff to be always in slot-0 if coeff is not S.One: c_part.insert(0, coeff) # we are done if len(c_part) == 2 and c_part[0].is_Number and c_part[1].is_Add: # 2*(1+a) -> 2 + 2 * a coeff = c_part[0] c_part = [Add(*[coeff * f for f in c_part[1].args])] return c_part, nc_part, order_symbols
def is_right_unbounded(self): """Return ``True`` if the right endpoint is positive infinity. """ return self.right is S.Infinity or self.right == Real("+inf")
def is_left_unbounded(self): """Return ``True`` if the left endpoint is negative infinity. """ return self.left is S.NegativeInfinity or self.left == Real("-inf")
from numbers import Real from z3 import * x = Real('x') y = Real('y') s = Solver() s.add(x + y > 5, x > 1, y > 1) print(s.check()) print(s.model())