예제 #1
0
    def __new__(cls, sym, condition, base_set=S.UniversalSet):
        # nonlinsolve uses ConditionSet to return an unsolved system
        # of equations (see _return_conditionset in solveset) so until
        # that is changed we do minimal checking of the args
        sym = _sympify(sym)
        base_set = _sympify(base_set)
        condition = _sympify(condition)

        if isinstance(condition, FiniteSet):
            condition_orig = condition
            temp = (Eq(lhs, 0) for lhs in condition)
            condition = And(*temp)
            SymPyDeprecationWarning(
                feature="Using {} for condition".format(condition_orig),
                issue=17651,
                deprecated_since_version="1.5",
                useinstead="{} for condition".format(condition),
            ).warn()

        condition = as_Boolean(condition)

        if isinstance(sym, Tuple):  # unsolved eqns syntax
            return Basic.__new__(cls, sym, condition, base_set)

        if not isinstance(base_set, Set):
            raise TypeError("expecting set for base_set")

        if condition is S.false:
            return S.EmptySet
        elif condition is S.true:
            return base_set
        if isinstance(base_set, EmptySet):
            return base_set

        know = None
        if isinstance(base_set, FiniteSet):
            sifted = sift(base_set,
                          lambda _: fuzzy_bool(condition.subs(sym, _)))
            if sifted[None]:
                know = FiniteSet(*sifted[True])
                base_set = FiniteSet(*sifted[None])
            else:
                return FiniteSet(*sifted[True])

        if isinstance(base_set, cls):
            s, c, base_set = base_set.args
            if sym == s:
                condition = And(condition, c)
            elif sym not in c.free_symbols:
                condition = And(condition, c.xreplace({s: sym}))
            elif s not in condition.free_symbols:
                condition = And(condition.xreplace({sym: s}), c)
                sym = s
            else:
                # user will have to use cls.sym to get symbol
                dum = Symbol("lambda")
                if dum in condition.free_symbols or dum in c.free_symbols:
                    dum = Dummy(str(dum))
                condition = And(condition.xreplace({sym: dum}),
                                c.xreplace({s: dum}))
                sym = dum

        if not isinstance(sym, Symbol):
            s = Dummy("lambda")
            if s not in condition.xreplace({sym: s}).free_symbols:
                raise ValueError(
                    "non-symbol dummy not recognized in condition")

        rv = Basic.__new__(cls, sym, condition, base_set)
        return rv if know is None else Union(know, rv)
예제 #2
0
    def __new__(cls, sym, condition, base_set=S.UniversalSet):
        from sympy.core.function import BadSignatureError
        from sympy.utilities.iterables import flatten, has_dups
        sym = _sympify(sym)
        flat = flatten([sym])
        if has_dups(flat):
            raise BadSignatureError("Duplicate symbols detected")
        base_set = _sympify(base_set)
        if not isinstance(base_set, Set):
            raise TypeError('base set should be a Set object, not %s' %
                            base_set)
        condition = _sympify(condition)

        if isinstance(condition, FiniteSet):
            condition_orig = condition
            temp = (Eq(lhs, 0) for lhs in condition)
            condition = And(*temp)
            SymPyDeprecationWarning(
                feature="Using {} for condition".format(condition_orig),
                issue=17651,
                deprecated_since_version='1.5',
                useinstead="{} for condition".format(condition)).warn()

        condition = as_Boolean(condition)

        if condition is S.true:
            return base_set

        if condition is S.false:
            return S.EmptySet

        if isinstance(base_set, EmptySet):
            return base_set

        # no simple answers, so now check syms
        for i in flat:
            if not getattr(i, '_diff_wrt', False):
                raise ValueError('`%s` is not symbol-like' % i)

        if base_set.contains(sym) is S.false:
            raise TypeError('sym `%s` is not in base_set `%s`' %
                            (sym, base_set))

        know = None
        if isinstance(base_set, FiniteSet):
            sifted = sift(base_set,
                          lambda _: fuzzy_bool(condition.subs(sym, _)))
            if sifted[None]:
                know = FiniteSet(*sifted[True])
                base_set = FiniteSet(*sifted[None])
            else:
                return FiniteSet(*sifted[True])

        if isinstance(base_set, cls):
            s, c, b = base_set.args

            def sig(s):
                return cls(s, Eq(adummy, 0)).as_dummy().sym

            sa, sb = map(sig, (sym, s))
            if sa != sb:
                raise BadSignatureError('sym does not match sym of base set')
            reps = dict(zip(flatten([sym]), flatten([s])))
            if s == sym:
                condition = And(condition, c)
                base_set = b
            elif not c.free_symbols & sym.free_symbols:
                reps = {v: k for k, v in reps.items()}
                condition = And(condition, c.xreplace(reps))
                base_set = b
            elif not condition.free_symbols & s.free_symbols:
                sym = sym.xreplace(reps)
                condition = And(condition.xreplace(reps), c)
                base_set = b

        # flatten ConditionSet(Contains(ConditionSet())) expressions
        if isinstance(condition, Contains) and (sym == condition.args[0]):
            if isinstance(condition.args[1], Set):
                return condition.args[1].intersect(base_set)

        rv = Basic.__new__(cls, sym, condition, base_set)
        return rv if know is None else Union(know, rv)