Processing math: 100%

First time here? Check out the FAQ!

Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps"""

    w = [SR.wild(i) for i in (0, .., 10)]

    rules = {w[0]^w[1]: lambda f: (exp(f[w[1]]*log(f[w[0]]), hold=True))}
    final_steps = ['log_simplify']

    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                E = E.substitute({e: rules[r](f)})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
click to hide/show revision 2
No.2 Revision

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need to change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps"""

    w = [SR.wild(i) for i in (0, .., 10)]

    rules = {w[0]^w[1]: lambda f: (exp(f[w[1]]*log(f[w[0]]), hold=True))}
    final_steps = ['log_simplify']

    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                E = E.substitute({e: rules[r](f)})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
click to hide/show revision 3
No.3 Revision

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need to change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps"""

    w = [SR.wild(i) for i in (0, .., 10)]

    rules = {w[0]^w[1]: lambda f: (exp(f[w[1]]*log(f[w[0]]), hold=True))}
    final_steps = ['log_simplify']

    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                E = E.substitute({e: rules[r](f)})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c

Edit: It's extremely overkill here, since canonicalize_radical does the work fine.

click to hide/show revision 4
No.4 Revision

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need to change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps"""
steps."""

    w = [SR.wild(i) for i in (0, .., 10)]

     rules = {w[0]^w[1]: lambda f: (exp(f[w[1]]*log(f[w[0]]), hold=True))}
((exp(f[w[1]]*log(f[w[0]]), hold=True)), f[w[0]]>0),}
    final_steps = ['log_simplify']
 
    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                if rules[r](f)[1]:
                    E = E.substitute({e: rules[r](f)})
rules[r](f)[0]})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c

Edit: It's extremely overkill here, since canonicalize_radical does the work fine.

Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now contain a tuple, the second element being a condition that must hold for the substitution to be valid.

click to hide/show revision 5
No.5 Revision

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need to change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps."""

    w = [SR.wild(i) for i in (0, .., 10)]

     rules = {w[0]^w[1]: lambda f: ((exp(f[w[1]]*log(f[w[0]]), hold=True)), f[w[0]]>0),}
    final_steps = ['log_simplify']
 
    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                if rules[r](f)[1]:
                    E = E.substitute({e: rules[r](f)[0]})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c

Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now contain a tuple, the second element being a condition that must hold for the substitution to be valid.

click to hide/show revision 6
No.6 Revision

When Sage doesn't want to simplify my expressions, I do it myself.

I wrote a function to do that some time ago, and I just need to change the rules (I already used the same function to solve this other question).

Here I use the rule abebloga, defined on the third line (holding the result, otherwise it immediatly goes back to ab). The function will try to apply this rule everywhere, then finish with one step of log_simplify.

def custom_simplify(E):
    """Apply some rules on expression E as long as it changes, then apply some final steps."""

    w = [SR.wild(i) for i in (0, .., 10)]

    rules = {w[0]^w[1]: lambda f: ((exp(f[w[1]]*log(f[w[0]]), hold=True)), f[w[0]]>0),}
    final_steps = ['log_simplify']

    def apply_rules():
        nonlocal E
        for r in rules:
            for e in E.find(r):
                f = e.match(r)
                if rules[r](f)[1]:
                    E = E.substitute({e: rules[r](f)[0]})
        return E

    while(E!=apply_rules()):
        pass

    for step in final_steps:
        E = getattr(E, step)()

    return E

It works as expected:

sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c

Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now contain returns a tuple, the second element being a condition that must hold for the substitution to be valid.