def test_fuzzy_or(): assert fuzzy_or([T, T]) == T assert fuzzy_or([T, F]) == T assert fuzzy_or([T, U]) == T assert fuzzy_or([F, F]) == F assert fuzzy_or([F, U]) == U assert fuzzy_or([U, U]) == U assert [fuzzy_or([w]) for w in [U, T, F]] == [U, T, F] assert fuzzy_or([T, F, U]) == T assert fuzzy_or([]) == F raises(TypeError, lambda: fuzzy_or())
def is_monotonic(f, interval=S.Reals, symbol=None): """ Returns if a function is monotonic or not, in the given ``Interval``. Examples ======== >>> from sympy import is_monotonic >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_monotonic(-x**2, S.Reals) False >>> is_monotonic(x**2 + y + 1, Interval(1, 2), x) True """ from sympy.core.logic import fuzzy_or f = sympify(f) free_sym = f.free_symbols if symbol is None and len(free_sym) > 1: raise NotImplementedError('is_monotonic has not yet been ' 'for all multivariate expressions') inc = is_increasing(f, interval, symbol) dec = is_decreasing(f, interval, symbol) return fuzzy_or([inc, dec])
def is_monotonic(f, interval=S.Reals): """ Returns if a function is monotonic or not, in the given ``Interval``. Examples ======== >>> from sympy import is_monotonic >>> from sympy.abc import x >>> from sympy import S, Interval, oo >>> is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_monotonic(-x**2, S.Reals) False """ from sympy.core.logic import fuzzy_or if len(f.free_symbols) > 1: raise NotImplementedError('is_monotonic has not yet been ' 'implemented for multivariate expressions') inc = is_increasing(f, interval) dec = is_decreasing(f, interval) return fuzzy_or([inc, dec])
def Basic(expr, assumptions): if expr.is_number: # if there are no symbols just evalf i = expr.evalf(2) def nonz(i): if i._prec != 1: return i != 0 return fuzzy_or(nonz(i) for i in i.as_real_imag())
def Basic(expr, assumptions): if ask(Q.real(expr)) is False: return False if expr.is_number: # if there are no symbols just evalf i = expr.evalf(2) def nonz(i): if i._prec != 1: return i != 0 return fuzzy_or(nonz(i) for i in i.as_real_imag())
def _eval_is_positive(self): arg = self.args[0] if arg.is_real: return True re, im = arg.as_real_imag() im_mod = im % (2*pi) if im_mod == 0: return True if re == 0: if im_mod < pi/2 or im_mod > 3*pi/2: return True elif im_mod >= pi/2 or im_mod <= 3*pi/2: return False return fuzzy_or([fuzzy_and([fuzzy_bool(Eq(re, 0)), fuzzy_or([fuzzy_bool(im_mod < pi/2), fuzzy_bool(im_mod > 3*pi/2)])]), fuzzy_bool(Eq(im_mod, 0))])
def _contains(self, other): from sympy.functions import arg, Abs from sympy.core.containers import Tuple other = sympify(other) isTuple = isinstance(other, Tuple) if isTuple and len(other) != 2: raise ValueError("expecting Tuple of length 2") # If the other is not an Expression, and neither a Tuple if not isinstance(other, Expr) and not isinstance(other, Tuple): return S.false # self in rectangular form if not self.polar: re, im = other if isTuple else other.as_real_imag() return fuzzy_or( fuzzy_and( [pset.args[0]._contains(re), pset.args[1]._contains(im)]) for pset in self.psets) # self in polar form elif self.polar: if other.is_zero: # ignore undefined complex argument return fuzzy_or(pset.args[0]._contains(S.Zero) for pset in self.psets) if isTuple: r, theta = other else: r, theta = Abs(other), arg(other) if theta.is_real and theta.is_number: # angles in psets are normalized to [0, 2pi) theta %= 2 * S.Pi return fuzzy_or( fuzzy_and([ pset.args[0]._contains(r), pset.args[1]._contains( theta) ]) for pset in self.psets)
def is_subset_sets(a_interval, b_u): # noqa:F811 if all(isinstance(s, (Interval, FiniteSet)) for s in b_u.args): intervals = [s for s in b_u.args if isinstance(s, Interval)] if all(fuzzy_bool(a_interval.start < s.start) for s in intervals): return False if all(fuzzy_bool(a_interval.end > s.end) for s in intervals): return False if a_interval.measure.is_nonzero: no_overlap = lambda s1, s2: fuzzy_or([ fuzzy_bool(s1.end <= s2.start), fuzzy_bool(s1.start >= s2.end), ]) if all(no_overlap(s, a_interval) for s in intervals): return False
def _eval_is_nonnegative(self): z = self.args[0] x, y = z.as_real_imag() ymod = y % (2 * pi) yzero = ymod.is_zero # shortcut if ymod is zero if yzero: return True xzero = x.is_zero # shortcut x is not zero if xzero is False: return yzero return fuzzy_or([ # Case 1: yzero, # Case 2: fuzzy_and([xzero, fuzzy_or([ymod <= pi / 2, ymod >= 3 * pi / 2])]) ])
def arc_coplanar(self, other): """ Returns True if the transformation arcs represented by the input quaternions happen in the same plane. Explanation =========== Two quaternions are said to be coplanar (in this arc sense) when their axes are parallel. The plane of a quaternion is the one normal to its axis. Parameters ========== other : a Quaternion Returns ======= True : if the planes of the two quaternions are the same, apart from its orientation/sign. False : if the planes of the two quaternions are not the same, apart from its orientation/sign. None : if plane of either of the quaternion is unknown. Examples ======== >>> from sympy.algebras.quaternion import Quaternion >>> q1 = Quaternion(1, 4, 4, 4) >>> q2 = Quaternion(3, 8, 8, 8) >>> Quaternion.arc_coplanar(q1, q2) True >>> q1 = Quaternion(2, 8, 13, 12) >>> Quaternion.arc_coplanar(q1, q2) False See Also ======== vector_coplanar is_pure """ if (self.is_zero_quaternion()) or (other.is_zero_quaternion()): raise ValueError('Neither of the given quaternions can be 0') return fuzzy_or([(self.axis() - other.axis()).is_zero_quaternion(), (self.axis() + other.axis()).is_zero_quaternion()])
def __new__(cls, flambda, *sets): if not isinstance(flambda, Lambda): raise ValueError('first argument must be a Lambda') if flambda is S.IdentityFunction: if len(sets) != 1: raise ValueError('identify function requires a single set') return sets[0] if not set(flambda.variables) & flambda.expr.free_symbols: emptyprod = fuzzy_or(s.is_empty for s in sets) if emptyprod == True: return S.EmptySet elif emptyprod == False: return FiniteSet(flambda.expr) return Basic.__new__(cls, flambda, *sets)
def _old_assump_replacer(obj): # Things to be careful of: # - real means real or infinite in the old assumptions. # - nonzero does not imply real in the old assumptions. # - finite means finite and not zero in the old assumptions. if not isinstance(obj, AppliedPredicate): return obj e = obj.args[0] ret = None if obj.func == Q.positive: ret = fuzzy_and([e.is_finite, e.is_positive]) if obj.func == Q.zero: ret = e.is_zero if obj.func == Q.negative: ret = fuzzy_and([e.is_finite, e.is_negative]) if obj.func == Q.nonpositive: ret = fuzzy_and([e.is_finite, e.is_nonpositive]) if obj.func == Q.nonzero: ret = fuzzy_and([e.is_nonzero, e.is_finite]) if obj.func == Q.nonnegative: ret = fuzzy_and([fuzzy_or([e.is_zero, e.is_finite]), e.is_nonnegative]) if obj.func == Q.rational: ret = e.is_rational if obj.func == Q.irrational: ret = e.is_irrational if obj.func == Q.even: ret = e.is_even if obj.func == Q.odd: ret = e.is_odd if obj.func == Q.integer: ret = e.is_integer if obj.func == Q.imaginary: ret = e.is_imaginary if obj.func == Q.commutative: ret = e.is_commutative if ret is None: return obj return ret
def __new__(cls, flambda, *sets): if not isinstance(flambda, Lambda): raise ValueError('First argument must be a Lambda') sets = [_sympify(s) for s in sets] if flambda is S.IdentityFunction: if len(sets) != 1: raise ValueError('Identity function requires a single set') return sets[0] if not all(isinstance(s, Set) for s in sets): raise TypeError("Set arguments to ImageSet should of type Set") sets = [s.flatten() if s.is_ProductSet else s for s in sets] if not set(flambda.variables) & flambda.expr.free_symbols: emptyprod = fuzzy_or(s.is_empty for s in sets) if emptyprod == True: return S.EmptySet elif emptyprod == False: return FiniteSet(flambda.expr) return Basic.__new__(cls, flambda, *sets)
def _eval_is_complex(self): def complex_extended_negative(arg): yield arg.is_complex yield arg.is_extended_negative return fuzzy_or(complex_extended_negative(self.args[0]))
def _eval_is_extended_positive(self): return fuzzy_or(a.is_extended_positive for a in self.args)
def _eval_is_zero(self): # is_imaginary implies nonzero return fuzzy_or([self.args[0].is_imaginary, self.args[0].is_zero])
def _eval_is_zero(self): return fuzzy_or([self.args[0].is_zero, self.args[0].is_integer])
def Mul(expr, assumptions): # TODO: This should be deducible from the nonzero handler return fuzzy_or(ask(Q.zero(arg), assumptions) for arg in expr.args)
def _eval_is_negative(self): return fuzzy_or(a.is_negative for a in self.args)
def __getitem__(self, i): ooslice = "cannot slice from the end with an infinite value" zerostep = "slice step cannot be zero" infinite = "slicing not possible on range with infinite start" # if we had to take every other element in the following # oo, ..., 6, 4, 2, 0 # we might get oo, ..., 4, 0 or oo, ..., 6, 2 ambiguous = "cannot unambiguously re-stride from the end " + \ "with an infinite value" if isinstance(i, slice): if self.size.is_finite: # validates, too if self.start == self.stop: return Range(0) start, stop, step = i.indices(self.size) n = ceiling((stop - start) / step) if n <= 0: return Range(0) canonical_stop = start + n * step end = canonical_stop - step ss = step * self.step return Range(self[start], self[end] + ss, ss) else: # infinite Range start = i.start stop = i.stop if i.step == 0: raise ValueError(zerostep) step = i.step or 1 ss = step * self.step #--------------------- # handle infinite Range # i.e. Range(-oo, oo) or Range(oo, -oo, -1) # -------------------- if self.start.is_infinite and self.stop.is_infinite: raise ValueError(infinite) #--------------------- # handle infinite on right # e.g. Range(0, oo) or Range(0, -oo, -1) # -------------------- if self.stop.is_infinite: # start and stop are not interdependent -- # they only depend on step --so we use the # equivalent reversed values return self.reversed[ stop if stop is None else -stop + 1:start if start is None else -start:step].reversed #--------------------- # handle infinite on the left # e.g. Range(oo, 0, -1) or Range(-oo, 0) # -------------------- # consider combinations of # start/stop {== None, < 0, == 0, > 0} and # step {< 0, > 0} if start is None: if stop is None: if step < 0: return Range(self[-1], self.start, ss) elif step > 1: raise ValueError(ambiguous) else: # == 1 return self elif stop < 0: if step < 0: return Range(self[-1], self[stop], ss) else: # > 0 return Range(self.start, self[stop], ss) elif stop == 0: if step > 0: return Range(0) else: # < 0 raise ValueError(ooslice) elif stop == 1: if step > 0: raise ValueError(ooslice) # infinite singleton else: # < 0 raise ValueError(ooslice) else: # > 1 raise ValueError(ooslice) elif start < 0: if stop is None: if step < 0: return Range(self[start], self.start, ss) else: # > 0 return Range(self[start], self.stop, ss) elif stop < 0: return Range(self[start], self[stop], ss) elif stop == 0: if step < 0: raise ValueError(ooslice) else: # > 0 return Range(0) elif stop > 0: raise ValueError(ooslice) elif start == 0: if stop is None: if step < 0: raise ValueError(ooslice) # infinite singleton elif step > 1: raise ValueError(ambiguous) else: # == 1 return self elif stop < 0: if step > 1: raise ValueError(ambiguous) elif step == 1: return Range(self.start, self[stop], ss) else: # < 0 return Range(0) else: # >= 0 raise ValueError(ooslice) elif start > 0: raise ValueError(ooslice) else: if self.start == self.stop: raise IndexError('Range index out of range') if not (all(i.is_integer or i.is_infinite for i in self.args) and ( (self.stop - self.start) / self.step).is_extended_positive): raise ValueError('Invalid method for symbolic Range') if i == 0: if self.start.is_infinite: raise ValueError(ooslice) return self.start if i == -1: if self.stop.is_infinite: raise ValueError(ooslice) return self.stop - self.step n = self.size # must be known for any other index rv = (self.stop if i < 0 else self.start) + i * self.step if rv.is_infinite: raise ValueError(ooslice) val = (rv - self.start) / self.step rel = fuzzy_or([ val.is_infinite, fuzzy_and([val.is_nonnegative, (n - val).is_nonnegative]) ]) if rel: return rv if rel is None: raise ValueError('Invalid method for symbolic Range') raise IndexError("Range index out of range")
def _eval_is_random(self): return fuzzy_or(arg.is_random for arg in self.args)