Exemple #1
0
def _add_splines(c, b1, d, b2):
    """Construct c*b1 + d*b2."""
    if b1 == S.Zero or c == S.Zero:
        return expand(piecewise_fold(d * b2))
    if b2 == S.Zero or d == S.Zero:
        return expand(piecewise_fold(c * b1))
    new_args = []
    n_intervals = len(b1.args)
    assert n_intervals == len(b2.args)
    new_args.append((expand(c * b1.args[0].expr), b1.args[0].cond))
    for i in range(1, n_intervals - 1):
        new_args.append((expand(c * b1.args[i].expr + d * b2.args[i - 1].expr), b1.args[i].cond))
    new_args.append((expand(d * b2.args[-2].expr), b2.args[-2].cond))
    new_args.append(b2.args[-1])
    return Piecewise(*new_args)
Exemple #2
0
def test_reciprocal_frame_test():
    with GA_Printer():
        metric = '1 # #,' + \
                 '# 1 #,' + \
                 '# # 1,'

        (e1, e2, e3) = MV.setup('e1 e2 e3', metric)

        E = e1 ^ e2 ^ e3
        Esq = (E*E).scalar()
        assert str(E) == 'e1^e2^e3'
        assert str(Esq) == '(e1.e2)**2 - 2*(e1.e2)*(e1.e3)*(e2.e3) + (e1.e3)**2 + (e2.e3)**2 - 1'
        Esq_inv = 1/Esq

        E1 = (e2 ^ e3)*E
        E2 = (-1)*(e1 ^ e3)*E
        E3 = (e1 ^ e2)*E

        assert str(E1) == '((e2.e3)**2 - 1)*e1 + ((e1.e2) - (e1.e3)*(e2.e3))*e2 + (-(e1.e2)*(e2.e3) + (e1.e3))*e3'
        assert str(E2) == '((e1.e2) - (e1.e3)*(e2.e3))*e1 + ((e1.e3)**2 - 1)*e2 + (-(e1.e2)*(e1.e3) + (e2.e3))*e3'
        assert str(E3) == '(-(e1.e2)*(e2.e3) + (e1.e3))*e1 + (-(e1.e2)*(e1.e3) + (e2.e3))*e2 + ((e1.e2)**2 - 1)*e3'

        w = (E1 | e2)
        w = w.expand()
        assert str(w) == '0'

        w = (E1 | e3)
        w = w.expand()
        assert str(w) == '0'

        w = (E2 | e1)
        w = w.expand()
        assert str(w) == '0'

        w = (E2 | e3)
        w = w.expand()
        assert str(w) == '0'

        w = (E3 | e1)
        w = w.expand()
        assert str(w) == '0'

        w = (E3 | e2)
        w = w.expand()
        assert str(w) == '0'

        w = (E1 | e1)
        w = (w.expand()).scalar()
        Esq = expand(Esq)
        assert str(simplify(w/Esq)) == '1'

        w = (E2 | e2)
        w = (w.expand()).scalar()
        assert str(simplify(w/Esq)) == '1'

        w = (E3 | e3)
        w = (w.expand()).scalar()
        assert str(simplify(w/Esq)) == '1'

    return
Exemple #3
0
def test_reciprocal_frame():
    """
    Test of formula for general reciprocal frame of three vectors.
    Let three independent vectors be e1, e2, and e3. The reciprocal
    vectors E1, E2, and E3 obey the relations:

    e_i.E_j = delta_ij*(e1^e2^e3)**2
    """
    g = '1 # #,'+ \
        '# 1 #,'+ \
        '# # 1'

    g3dn = Ga('e1 e2 e3',g=g)

    (e1,e2,e3) = g3dn.mv()

    E = e1^e2^e3
    Esq = (E*E).scalar()
    Esq_inv = 1 / Esq

    E1 = (e2^e3)*E
    E2 = (-1)*(e1^e3)*E
    E3 = (e1^e2)*E

    w = (E1|e2)
    w = w.expand()
    assert w.scalar() == 0

    w = (E1|e3)
    w = w.expand()
    assert w.scalar() == 0

    w = (E2|e1)
    w = w.expand()
    assert w.scalar() == 0

    w = (E2|e3)
    w = w.expand()
    assert w.scalar() == 0

    w = (E3|e1)
    w = w.expand()
    assert w.scalar() == 0

    w = (E3|e2)
    w = w.expand()
    assert w.scalar() == 0

    w = (E1|e1)
    w = (w.expand()).scalar()
    Esq = expand(Esq)
    assert simplify(w/Esq) == 1

    w = (E2|e2)
    w = (w.expand()).scalar()
    assert simplify(w/Esq) == 1

    w = (E3|e3)
    w = (w.expand()).scalar()
    assert simplify(w/Esq) == 1
Exemple #4
0
def test_reciprocal_frame_test():
    with GA_Printer():
        metric = "1 # #," + "# 1 #," + "# # 1,"

        (e1, e2, e3) = MV.setup("e1 e2 e3", metric)

        E = e1 ^ e2 ^ e3
        Esq = (E * E).scalar()
        assert str(E) == "e1^e2^e3"
        assert str(Esq) == "(e1.e2)**2 - 2*(e1.e2)*(e1.e3)*(e2.e3) + (e1.e3)**2 + (e2.e3)**2 - 1"
        Esq_inv = 1 / Esq

        E1 = (e2 ^ e3) * E
        E2 = (-1) * (e1 ^ e3) * E
        E3 = (e1 ^ e2) * E

        assert str(E1) == "((e2.e3)**2 - 1)*e1 + ((e1.e2) - (e1.e3)*(e2.e3))*e2 + (-(e1.e2)*(e2.e3) + (e1.e3))*e3"
        assert str(E2) == "((e1.e2) - (e1.e3)*(e2.e3))*e1 + ((e1.e3)**2 - 1)*e2 + (-(e1.e2)*(e1.e3) + (e2.e3))*e3"
        assert str(E3) == "(-(e1.e2)*(e2.e3) + (e1.e3))*e1 + (-(e1.e2)*(e1.e3) + (e2.e3))*e2 + ((e1.e2)**2 - 1)*e3"

        w = E1 | e2
        w = w.expand()
        assert str(w) == "0"

        w = E1 | e3
        w = w.expand()
        assert str(w) == "0"

        w = E2 | e1
        w = w.expand()
        assert str(w) == "0"

        w = E2 | e3
        w = w.expand()
        assert str(w) == "0"

        w = E3 | e1
        w = w.expand()
        assert str(w) == "0"

        w = E3 | e2
        w = w.expand()
        assert str(w) == "0"

        w = E1 | e1
        w = (w.expand()).scalar()
        Esq = expand(Esq)
        assert str(simplify(w / Esq)) == "1"

        w = E2 | e2
        w = (w.expand()).scalar()
        assert str(simplify(w / Esq)) == "1"

        w = E3 | e3
        w = (w.expand()).scalar()
        assert str(simplify(w / Esq)) == "1"

    return
Exemple #5
0
def __trigsimp(expr, deep=False):
    """recursive helper for trigsimp"""
    from sympy.simplify.fu import TR10i

    if _trigpat is None:
        _trigpats()
    a, b, c, d, matchers_division, matchers_add, \
    matchers_identity, artifacts = _trigpat

    if expr.is_Mul:
        # do some simplifications like sin/cos -> tan:
        if not expr.is_commutative:
            com, nc = expr.args_cnc()
            expr = _trigsimp(Mul._from_args(com), deep)*Mul._from_args(nc)
        else:
            for i, (pattern, simp, ok1, ok2) in enumerate(matchers_division):
                if not _dotrig(expr, pattern):
                    continue

                newexpr = _match_div_rewrite(expr, i)
                if newexpr is not None:
                    if newexpr != expr:
                        expr = newexpr
                        break
                    else:
                        continue

                # use SymPy matching instead
                res = expr.match(pattern)
                if res and res.get(c, 0):
                    if not res[c].is_integer:
                        ok = ok1.subs(res)
                        if not ok.is_positive:
                            continue
                        ok = ok2.subs(res)
                        if not ok.is_positive:
                            continue
                    # if "a" contains any of trig or hyperbolic funcs with
                    # argument "b" then skip the simplification
                    if any(w.args[0] == res[b] for w in res[a].atoms(
                            TrigonometricFunction, HyperbolicFunction)):
                        continue
                    # simplify and finish:
                    expr = simp.subs(res)
                    break  # process below

    if expr.is_Add:
        args = []
        for term in expr.args:
            if not term.is_commutative:
                com, nc = term.args_cnc()
                nc = Mul._from_args(nc)
                term = Mul._from_args(com)
            else:
                nc = S.One
            term = _trigsimp(term, deep)
            for pattern, result in matchers_identity:
                res = term.match(pattern)
                if res is not None:
                    term = result.subs(res)
                    break
            args.append(term*nc)
        if args != expr.args:
            expr = Add(*args)
            expr = min(expr, expand(expr), key=count_ops)
        if expr.is_Add:
            for pattern, result in matchers_add:
                if not _dotrig(expr, pattern):
                    continue
                expr = TR10i(expr)
                if expr.has(HyperbolicFunction):
                    res = expr.match(pattern)
                    # if "d" contains any trig or hyperbolic funcs with
                    # argument "a" or "b" then skip the simplification;
                    # this isn't perfect -- see tests
                    if res is None or not (a in res and b in res) or any(
                        w.args[0] in (res[a], res[b]) for w in res[d].atoms(
                            TrigonometricFunction, HyperbolicFunction)):
                        continue
                    expr = result.subs(res)
                    break

        # Reduce any lingering artifacts, such as sin(x)**2 changing
        # to 1 - cos(x)**2 when sin(x)**2 was "simpler"
        for pattern, result, ex in artifacts:
            if not _dotrig(expr, pattern):
                continue
            # Substitute a new wild that excludes some function(s)
            # to help influence a better match. This is because
            # sometimes, for example, 'a' would match sec(x)**2
            a_t = Wild('a', exclude=[ex])
            pattern = pattern.subs(a, a_t)
            result = result.subs(a, a_t)

            m = expr.match(pattern)
            was = None
            while m and was != expr:
                was = expr
                if m[a_t] == 0 or \
                        -m[a_t] in m[c].args or m[a_t] + m[c] == 0:
                    break
                if d in m and m[a_t]*m[d] + m[c] == 0:
                    break
                expr = result.subs(m)
                m = expr.match(pattern)
                m.setdefault(c, S.Zero)

    elif expr.is_Mul or expr.is_Pow or deep and expr.args:
        expr = expr.func(*[_trigsimp(a, deep) for a in expr.args])

    try:
        if not expr.has(*_trigs):
            raise TypeError
        e = expr.atoms(exp)
        new = expr.rewrite(exp, deep=deep)
        if new == e:
            raise TypeError
        fnew = factor(new)
        if fnew != new:
            new = sorted([new, factor(new)], key=count_ops)[0]
        # if all exp that were introduced disappeared then accept it
        if not (new.atoms(exp) - e):
            expr = new
    except TypeError:
        pass

    return expr
Exemple #6
0
def test_noneuclidian_distance_calculation():
    from sympy import solve, sqrt
    with GA_Printer():
        metric = '0 # #,# 0 #,# # 1'
        (X, Y, e) = MV.setup('X Y e', metric)

        assert str((X ^ Y)*(X ^ Y)) == '(X.Y)**2'

        L = X ^ Y ^ e
        B = L*e
        assert str(B) == 'X^Y - (Y.e)*X^e + (X.e)*Y^e'
        Bsq = B*B
        assert str(Bsq) == '(X.Y)*((X.Y) - 2*(X.e)*(Y.e))'
        Bsq = Bsq.scalar()
        assert str(B) == 'X^Y - (Y.e)*X^e + (X.e)*Y^e'

        BeBr = B*e*B.rev()
        assert str(BeBr) == '((X.Y)*(-(X.Y) + 2*(X.e)*(Y.e)))*e'
        assert str(B*B) == '(X.Y)*((X.Y) - 2*(X.e)*(Y.e))'
        assert str(L*L) == '(X.Y)*((X.Y) - 2*(X.e)*(Y.e))'
        (s, c, Binv, M, BigS, BigC, alpha, XdotY, Xdote, Ydote) = symbols('s c (1/B) M S C alpha (X.Y) (X.e) (Y.e)')

        Bhat = Binv*B
        R = c + s*Bhat
        assert str(R) == 'c + (1/B)*s*X^Y - (1/B)*(Y.e)*s*X^e + (1/B)*(X.e)*s*Y^e'

        Z = R*X*R.rev()
        Z.obj = expand(Z.obj)
        Z.obj = Z.obj.collect([Binv, s, c, XdotY])
        assert str(Z) == '((1/B)**2*(X.Y)**2*s**2 - 2*(1/B)**2*(X.Y)*(X.e)*(Y.e)*s**2 + 2*(1/B)*(X.Y)*c*s - 2*(1/B)*(X.e)*(Y.e)*c*s + c**2)*X + 2*(1/B)*(X.e)**2*c*s*Y + (2*(1/B)*(X.Y)*(X.e)*s*(-(1/B)*(X.Y)*s + 2*(1/B)*(X.e)*(Y.e)*s - c))*e'
        W = Z | Y
        # From this point forward all calculations are with sympy scalars
        W = W.scalar()
        assert str(W) == '(1/B)**2*(X.Y)**3*s**2 - 4*(1/B)**2*(X.Y)**2*(X.e)*(Y.e)*s**2 + 4*(1/B)**2*(X.Y)*(X.e)**2*(Y.e)**2*s**2 + 2*(1/B)*(X.Y)**2*c*s - 4*(1/B)*(X.Y)*(X.e)*(Y.e)*c*s + (X.Y)*c**2'
        W = expand(W)
        W = simplify(W)
        W = W.collect([s*Binv])

        M = 1/Bsq
        W = W.subs(Binv**2, M)
        W = simplify(W)
        Bmag = sqrt(XdotY**2 - 2*XdotY*Xdote*Ydote)
        W = W.collect([Binv*c*s, XdotY])

        #Double angle substitutions

        W = W.subs(2*XdotY**2 - 4*XdotY*Xdote*Ydote, 2/(Binv**2))
        W = W.subs(2*c*s, BigS)
        W = W.subs(c**2, (BigC + 1)/2)
        W = W.subs(s**2, (BigC - 1)/2)
        W = simplify(W)
        W = expand(W)
        W = W.subs(1/Binv, Bmag)

        assert str(W) == '(X.Y)*C - (X.e)*(Y.e)*C + (X.e)*(Y.e) + S*sqrt((X.Y)**2 - 2*(X.Y)*(X.e)*(Y.e))'

        Wd = collect(W, [BigC, BigS], exact=True, evaluate=False)

        Wd_1 = Wd[S.One]
        Wd_C = Wd[BigC]
        Wd_S = Wd[BigS]

        assert str(Wd_1) == '(X.e)*(Y.e)'
        assert str(Wd_C) == '(X.Y) - (X.e)*(Y.e)'
        assert str(Wd_S) == 'sqrt((X.Y)**2 - 2*(X.Y)*(X.e)*(Y.e))'

        assert str(Bmag) == 'sqrt((X.Y)**2 - 2*(X.Y)*(X.e)*(Y.e))'
        Wd_1 = Wd_1.subs(Bmag, 1/Binv)
        Wd_C = Wd_C.subs(Bmag, 1/Binv)
        Wd_S = Wd_S.subs(Bmag, 1/Binv)

        lhs = Wd_1 + Wd_C*BigC
        rhs = -Wd_S*BigS
        lhs = lhs**2
        rhs = rhs**2
        W = expand(lhs - rhs)
        W = expand(W.subs(1/Binv**2, Bmag**2))
        W = expand(W.subs(BigS**2, BigC**2 - 1))
        W = W.collect([BigC, BigC**2], evaluate=False)

        a = simplify(W[BigC**2])
        b = simplify(W[BigC])
        c = simplify(W[S.One])

        assert str(a) == '(X.e)**2*(Y.e)**2'
        assert str(b) == '2*(X.e)*(Y.e)*((X.Y) - (X.e)*(Y.e))'
        assert str(c) == '(X.Y)**2 - 2*(X.Y)*(X.e)*(Y.e) + (X.e)**2*(Y.e)**2'

        x = Symbol('x')
        C = solve(a*x**2 + b*x + c, x)[0]
        assert str(expand(simplify(expand(C)))) == '-(X.Y)/((X.e)*(Y.e)) + 1'

    return
Exemple #7
0
def test_rs_series():
    x, a, b, c = symbols('x, a, b, c')

    assert rs_series(a, a, 5).as_expr() == a
    assert rs_series(sin(a), a, 5).as_expr() == (sin(a).series(a, 0,
        5)).removeO()
    assert rs_series(sin(a) + cos(a), a, 5).as_expr() == ((sin(a) +
        cos(a)).series(a, 0, 5)).removeO()
    assert rs_series(sin(a)*cos(a), a, 5).as_expr() == ((sin(a)*
        cos(a)).series(a, 0, 5)).removeO()

    p = (sin(a) - a)*(cos(a**2) + a**4/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a**2/2 + a/3) + cos(a/5)*sin(a/2)**3
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(x**2 + a)*(cos(x**3 - 1) - a - a**2)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(a**2 - a/3 + 2)**5*exp(a**3 - a/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a + b + c)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = tan(sin(a**2 + 4) + b + c)
    assert expand(rs_series(p, a, 6).as_expr()) == expand(p.series(a, 0,
        6).removeO())

    p = a**QQ(2,5) + a**QQ(2,3) + a

    r = rs_series(tan(p), a, 2)
    assert r.as_expr() == a**QQ(9,5) + a**QQ(26,15) + a**QQ(22,15) + a**QQ(6,5)/3 + \
        a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(exp(p), a, 1)
    assert r.as_expr() == a**QQ(4,5)/2 + a**QQ(2,3) + a**QQ(2,5) + 1

    r = rs_series(sin(p), a, 2)
    assert r.as_expr() == -a**QQ(9,5)/2 - a**QQ(26,15)/2 - a**QQ(22,15)/2 - \
        a**QQ(6,5)/6 + a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(cos(p), a, 2)
    assert r.as_expr() == a**QQ(28,15)/6 - a**QQ(5,3) + a**QQ(8,5)/24 - a**QQ(7,5) - \
        a**QQ(4,3)/2 - a**QQ(16,15) - a**QQ(4,5)/2 + 1

    assert rs_series(sin(a)/7, a, 5).as_expr() == (sin(a)/7).series(a, 0,
            5).removeO()

    assert rs_series(log(1 + x), x, 5).as_expr() == -x**4/4 + x**3/3 - \
                    x**2/2 + x
    assert rs_series(log(1 + 4*x), x, 5).as_expr() == -64*x**4 + 64*x**3/3 - \
                    8*x**2 + 4*x
    assert rs_series(log(1 + x + x**2), x, 10).as_expr() == -2*x**9/9 + \
                    x**8/8 + x**7/7 - x**6/3 + x**5/5 + x**4/4 - 2*x**3/3 + \
                    x**2/2 + x
    assert rs_series(log(1 + x*a**2), x, 7).as_expr() == -x**6*a**12/6 + \
                    x**5*a**10/5 - x**4*a**8/4 + x**3*a**6/3 - \
                    x**2*a**4/2 + x*a**2
Exemple #8
0
def test_rs_series():
    x, a, b, c = symbols('x, a, b, c')

    assert rs_series(a, a, 5).as_expr() == a
    assert rs_series(sin(1/a), a, 5).as_expr() == sin(1/a)
    assert rs_series(sin(a), a, 5).as_expr() == (sin(a).series(a, 0,
        5)).removeO()
    assert rs_series(sin(a) + cos(a), a, 5).as_expr() == ((sin(a) +
        cos(a)).series(a, 0, 5)).removeO()
    assert rs_series(sin(a)*cos(a), a, 5).as_expr() == ((sin(a)*
        cos(a)).series(a, 0, 5)).removeO()

    p = (sin(a) - a)*(cos(a**2) + a**4/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a**2/2 + a/3) + cos(a/5)*sin(a/2)**3
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(x**2 + a)*(cos(x**3 - 1) - a - a**2)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(a**2 - a/3 + 2)**5*exp(a**3 - a/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a + b + c)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = tan(sin(a**2 + 4) + b + c)
    assert expand(rs_series(p, a, 6).as_expr()) == expand(p.series(a, 0,
        6).removeO())
def test_rs_series():
    x, a, b, c = symbols('x, a, b, c')

    assert rs_series(a, a, 5).as_expr() == a
    assert rs_series(sin(a), a, 5).as_expr() == (sin(a).series(a, 0,
        5)).removeO()
    assert rs_series(sin(a) + cos(a), a, 5).as_expr() == ((sin(a) +
        cos(a)).series(a, 0, 5)).removeO()
    assert rs_series(sin(a)*cos(a), a, 5).as_expr() == ((sin(a)*
        cos(a)).series(a, 0, 5)).removeO()

    p = (sin(a) - a)*(cos(a**2) + a**4/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a**2/2 + a/3) + cos(a/5)*sin(a/2)**3
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(x**2 + a)*(cos(x**3 - 1) - a - a**2)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = sin(a**2 - a/3 + 2)**5*exp(a**3 - a/2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(p.series(a, 0,
        10).removeO())

    p = sin(a + b + c)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(p.series(a, 0,
        5).removeO())

    p = tan(sin(a**2 + 4) + b + c)
    assert expand(rs_series(p, a, 6).as_expr()) == expand(p.series(a, 0,
        6).removeO())

    p = a**QQ(2,5) + a**QQ(2,3) + a

    r = rs_series(tan(p), a, 2)
    assert r.as_expr() == a**QQ(9,5) + a**QQ(26,15) + a**QQ(22,15) + a**QQ(6,5)/3 + \
        a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(exp(p), a, 1)
    assert r.as_expr() == a**QQ(4,5)/2 + a**QQ(2,3) + a**QQ(2,5) + 1

    r = rs_series(sin(p), a, 2)
    assert r.as_expr() == -a**QQ(9,5)/2 - a**QQ(26,15)/2 - a**QQ(22,15)/2 - \
        a**QQ(6,5)/6 + a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(cos(p), a, 2)
    assert r.as_expr() == a**QQ(28,15)/6 - a**QQ(5,3) + a**QQ(8,5)/24 - a**QQ(7,5) - \
        a**QQ(4,3)/2 - a**QQ(16,15) - a**QQ(4,5)/2 + 1

    assert rs_series(sin(a)/7, a, 5).as_expr() == (sin(a)/7).series(a, 0,
            5).removeO()
Exemple #10
0
def fast_substitute(monomial, old_sub, new_sub):
    """Experimental fast substitution routine that considers only restricted
    cases of noncommutative algebras. In rare cases, it fails to find a
    substitution. Use it with proper testing.

    :param monomial: The monomial with parts need to be substituted.
    :param old_sub: The part to be replaced.
    :param new_sub: The replacement.
    """
    if is_number_type(monomial):
        return monomial
    if monomial.is_Add:
        return sum([fast_substitute(element, old_sub, new_sub) for element in
                    monomial.as_ordered_terms()])

    comm_factors, ncomm_factors = split_commutative_parts(monomial)
    old_comm_factors, old_ncomm_factors = split_commutative_parts(old_sub)
    # This is a temporary hack
    if not isinstance(new_sub, int) and not isinstance(new_sub, float):
        new_comm_factors, _ = split_commutative_parts(new_sub)
    comm_monomial = 1
    is_constant_term = False
    if len(comm_factors) == 1 and isinstance(comm_factors[0], Number):
        is_constant_term = True
        comm_monomial = comm_factors[0]
    if not is_constant_term and len(comm_factors) > 0:
        for comm_factor in comm_factors:
            comm_monomial *= comm_factor
        if len(old_comm_factors) > 0:
            comm_old_sub = 1
            for comm_factor in old_comm_factors:
                comm_old_sub *= comm_factor
            comm_new_sub = 1
            for comm_factor in new_comm_factors:
                comm_new_sub *= comm_factor
            comm_monomial = comm_monomial.subs(comm_old_sub, comm_new_sub)
    if len(ncomm_factors) == 0 or len(old_ncomm_factors) == 0:
        return comm_monomial
    # old_factors = old_sub.as_ordered_factors()
    # factors = monomial.as_ordered_factors()
    new_var_list = []
    new_monomial = 1
    match = False
    left_remainder = 1
    right_remainder = 1
    for i in range(len(ncomm_factors) - len(old_ncomm_factors) + 1):
        for j in range(len(old_ncomm_factors)):
            if isinstance(ncomm_factors[i + j], Number) and \
                ((not isinstance(old_ncomm_factors[j], Number) or
                  ncomm_factors[i + j] != old_ncomm_factors[j])):
                break
            if isinstance(ncomm_factors[i + j], Symbol) and \
                (not isinstance(old_ncomm_factors[j], Operator) or
                 (isinstance(old_ncomm_factors[j], Symbol) and
                  ncomm_factors[i + j] != old_ncomm_factors[j])):
                break
            if isinstance(ncomm_factors[i + j], Operator) and \
                isinstance(old_ncomm_factors[j], Operator) and \
                    ncomm_factors[i + j] != old_ncomm_factors[j]:
                break
            if isinstance(ncomm_factors[i + j], Dagger) and \
                (not isinstance(old_ncomm_factors[j], Dagger) or
                 ncomm_factors[i + j] != old_ncomm_factors[j]):
                break
            if not isinstance(ncomm_factors[i + j], Dagger) and \
                not isinstance(ncomm_factors[i + j], Pow) and \
                    isinstance(old_ncomm_factors[j], Dagger):
                break
            if isinstance(ncomm_factors[i + j], Pow):
                if isinstance(old_ncomm_factors[j], Pow):
                    old_base = old_ncomm_factors[j].base
                    old_degree = old_ncomm_factors[j].exp
                else:
                    old_base = old_ncomm_factors[j]
                    old_degree = 1
                if old_base != ncomm_factors[i + j].base:
                    break
                if old_degree > ncomm_factors[i + j].exp:
                    break
                if old_degree < ncomm_factors[i + j].exp:
                    if j != len(old_ncomm_factors) - 1:
                        if j != 0:
                            break
                        else:
                            left_remainder = old_base ** (
                                ncomm_factors[i + j].exp - old_degree)
                    else:
                        right_remainder = old_base ** (
                            ncomm_factors[i + j].exp - old_degree)
            if isinstance(ncomm_factors[i + j], Operator) and \
                    isinstance(old_ncomm_factors[j], Pow):
                break
        else:
            match = True
        if not match:
            new_var_list.append(ncomm_factors[i])
        else:
            new_monomial = 1
            for var in new_var_list:
                new_monomial *= var
            new_monomial *= left_remainder * new_sub * right_remainder
            for j in range(i + len(old_ncomm_factors), len(ncomm_factors)):
                new_monomial *= ncomm_factors[j]
            new_monomial *= comm_monomial
            break
    else:
        if not is_constant_term and len(comm_factors) > 0:
            new_monomial = comm_monomial
            for factor in ncomm_factors:
                new_monomial *= factor
        else:
            return monomial
    if not isinstance(new_sub, (float, int, complex)) and new_sub.is_Add:
        return expand(new_monomial)
    else:
        return new_monomial