示例#1
0
 def _handle_irel(self, x, handler):
     """Return either None (if the conditions of self depend only on x) else
     a Piecewise expression whose expressions (handled by the handler that
     was passed) are paired with the governing x-independent relationals,
     e.g. Piecewise((A, a(x) & b(y)), (B, c(x) | c(y)) ->
     Piecewise(
         (handler(Piecewise((A, a(x) & True), (B, c(x) | True)), b(y) & c(y)),
         (handler(Piecewise((A, a(x) & True), (B, c(x) | False)), b(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | True)), c(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | False)), True))
     """
     # identify governing relationals
     rel = self.atoms(Relational)
     irel = list(
         ordered([
             r for r in rel
             if x not in r.free_symbols and r not in (S.true, S.false)
         ]))
     if irel:
         args = {}
         exprinorder = []
         for truth in product((1, 0), repeat=len(irel)):
             reps = dict(zip(irel, truth))
             # only store the true conditions since the false are implied
             # when they appear lower in the Piecewise args
             if 1 not in truth:
                 cond = None  # flag this one so it doesn't get combined
             else:
                 andargs = Tuple(*[i for i in reps if reps[i]])
                 free = list(andargs.free_symbols)
                 if len(free) == 1:
                     from sympy.solvers.inequalities import (
                         reduce_inequalities, _solve_inequality)
                     try:
                         t = reduce_inequalities(andargs, free[0])
                         # ValueError when there are potentially
                         # nonvanishing imaginary parts
                     except (ValueError, NotImplementedError):
                         # at least isolate free symbol on left
                         t = And(*[
                             _solve_inequality(a, free[0], linear=True)
                             for a in andargs
                         ])
                 else:
                     t = And(*andargs)
                 if t is S.false:
                     continue  # an impossible combination
                 cond = t
             expr = handler(self.xreplace(reps))
             if isinstance(expr, self.func) and len(expr.args) == 1:
                 expr, econd = expr.args[0]
                 cond = And(econd, True if cond is None else cond)
             # the ec pairs are being collected since all possibilities
             # are being enumerated, but don't put the last one in since
             # its expr might match a previous expression and it
             # must appear last in the args
             if cond is not None:
                 args.setdefault(expr, []).append(cond)
                 # but since we only store the true conditions we must maintain
                 # the order so that the expression with the most true values
                 # comes first
                 exprinorder.append(expr)
         # convert collected conditions as args of Or
         for k in args:
             args[k] = Or(*args[k])
         # take them in the order obtained
         args = [(e, args[e]) for e in uniq(exprinorder)]
         # add in the last arg
         args.append((expr, True))
         # if any condition reduced to True, it needs to go last
         # and there should only be one of them or else the exprs
         # should agree
         trues = [i for i in range(len(args)) if args[i][1] is S.true]
         if not trues:
             # make the last one True since all cases were enumerated
             e, c = args[-1]
             args[-1] = (e, S.true)
         else:
             assert len(set([e for e, c in [args[i] for i in trues]])) == 1
             args.append(args.pop(trues.pop()))
             while trues:
                 args.pop(trues.pop())
         return Piecewise(*args)
示例#2
0
文件: piecewise.py 项目: Lenqth/sympy
 def _handle_irel(self, x, handler):
     """Return either None (if the conditions of self depend only on x) else
     a Piecewise expression whose expressions (handled by the handler that
     was passed) are paired with the governing x-independent relationals,
     e.g. Piecewise((A, a(x) & b(y)), (B, c(x) | c(y)) ->
     Piecewise(
         (handler(Piecewise((A, a(x) & True), (B, c(x) | True)), b(y) & c(y)),
         (handler(Piecewise((A, a(x) & True), (B, c(x) | False)), b(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | True)), c(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | False)), True))
     """
     # identify governing relationals
     rel = self.atoms(Relational)
     irel = list(ordered([r for r in rel if x not in r.free_symbols
         and r not in (S.true, S.false)]))
     if irel:
         args = {}
         exprinorder = []
         for truth in product((1, 0), repeat=len(irel)):
             reps = dict(zip(irel, truth))
             # only store the true conditions since the false are implied
             # when they appear lower in the Piecewise args
             if 1 not in truth:
                 cond = None  # flag this one so it doesn't get combined
             else:
                 andargs = Tuple(*[i for i in reps if reps[i]])
                 free = list(andargs.free_symbols)
                 if len(free) == 1:
                     from sympy.solvers.inequalities import (
                         reduce_inequalities, _solve_inequality)
                     try:
                         t = reduce_inequalities(andargs, free[0])
                         # ValueError when there are potentially
                         # nonvanishing imaginary parts
                     except (ValueError, NotImplementedError):
                         # at least isolate free symbol on left
                         t = And(*[_solve_inequality(
                             a, free[0], linear=True)
                             for a in andargs])
                 else:
                     t = And(*andargs)
                 if t is S.false:
                     continue  # an impossible combination
                 cond = t
             expr = handler(self.xreplace(reps))
             if isinstance(expr, self.func) and len(expr.args) == 1:
                 expr, econd = expr.args[0]
                 cond = And(econd, True if cond is None else cond)
             # the ec pairs are being collected since all possibilities
             # are being enumerated, but don't put the last one in since
             # its expr might match a previous expression and it
             # must appear last in the args
             if cond is not None:
                 args.setdefault(expr, []).append(cond)
                 # but since we only store the true conditions we must maintain
                 # the order so that the expression with the most true values
                 # comes first
                 exprinorder.append(expr)
         # convert collected conditions as args of Or
         for k in args:
             args[k] = Or(*args[k])
         # take them in the order obtained
         args = [(e, args[e]) for e in uniq(exprinorder)]
         # add in the last arg
         args.append((expr, True))
         # if any condition reduced to True, it needs to go last
         # and there should only be one of them or else the exprs
         # should agree
         trues = [i for i in range(len(args)) if args[i][1] is S.true]
         if not trues:
             # make the last one True since all cases were enumerated
             e, c = args[-1]
             args[-1] = (e, S.true)
         else:
             assert len(set([e for e, c in [args[i] for i in trues]])) == 1
             args.append(args.pop(trues.pop()))
             while trues:
                 args.pop(trues.pop())
         return Piecewise(*args)