def _separate_imaginary_from_complex(cls, complexes): from diofant.utilities.iterables import sift def is_imag(c): ''' return True if all roots are imaginary (ax**2 + b) return False if no roots are imaginary return None if 2 roots are imaginary (ax**N''' u, f, k = c deg = f.degree() if f.length() == 2: if deg == 2: return True # both imag elif _ispow2(deg): if f.LC() * f.TC() < 0: return # 2 are imag return False # none are imag # separate according to the function sifted = sift(complexes, lambda c: c[1]) del complexes imag = [] complexes = [] for f in sifted: isift = sift(sifted[f], lambda c: is_imag(c)) imag.extend(isift.pop(True, [])) complexes.extend(isift.pop(False, [])) mixed = isift.pop(None, []) assert not isift if not mixed: continue while True: # the non-imaginary ones will be on one side or the other # of the y-axis i = 0 while i < len(mixed): u, f, k = mixed[i] if u.ax * u.bx > 0: complexes.append(mixed.pop(i)) else: i += 1 if len(mixed) == 2: imag.extend(mixed) break # refine for i, (u, f, k) in enumerate(mixed): u = u._inner_refine() mixed[i] = u, f, k return imag, complexes
def conglomerate(expr): """ Conglomerate together identical args x + x -> 2x """ groups = sift(arguments(expr), key) counts = {k: sum(map(count, args)) for k, args in groups.items()} newargs = [combine(cnt, mat) for mat, cnt in counts.items()] if set(newargs) != set(arguments(expr)): return term(operator(expr), newargs) else: return expr
def _eval_factor(self, **hints): if 1 == len(self.limits): summand = self.function.factor(**hints) if summand.is_Mul: out = sift( summand.args, lambda w: w.is_commutative and not set( self.variables) & w.free_symbols) return Mul(*out[True]) * self.func(Mul(*out[False]), * self.limits) else: summand = self.func(self.function, self.limits[0:-1]).factor() if not summand.has(self.variables[-1]): return self.func(1, [self.limits[-1]]).doit() * summand return self
def cse_separate(r, e): """Move expressions that are in the form (symbol, expr) out of the expressions and sort them into the replacements using the reps_toposort. Examples ======== >>> from diofant.simplify.cse_main import cse_separate >>> from diofant.abc import x, y, z >>> from diofant import cos, exp, cse, Eq, symbols >>> x0, x1 = symbols('x:2') >>> eq = (x + 1 + exp((x + 1)/(y + 1)) + cos(y + 1)) >>> cse([eq, Eq(x, z + 1), z - 2], postprocess=cse_separate) in [ ... [[(x0, y + 1), (x, z + 1), (x1, x + 1)], ... [x1 + exp(x1/x0) + cos(x0), z - 2]], ... [[(x1, y + 1), (x, z + 1), (x0, x + 1)], ... [x0 + exp(x0/x1) + cos(x1), z - 2]]] ... True """ d = sift(e, lambda w: w.is_Equality and w.lhs.is_Symbol) r = r + [w.args for w in d[True]] e = d[False] return [reps_toposort(r), e]
def test_sift(): assert sift(list(range(5)), lambda _: _ % 2) == {1: [1, 3], 0: [0, 2, 4]} assert sift([x, y], lambda _: _.has(x)) == {False: [y], True: [x]} assert sift([S.One], lambda _: _.has(x)) == {False: [1]}
def test_sift(): assert sift(list(range(5)), lambda _: _ % 2) == {1: [1, 3], 0: [0, 2, 4]} assert sift([x, y], lambda _: _.has(x)) == {False: [y], True: [x]} assert sift([Integer(1)], lambda _: _.has(x)) == {False: [1]}