ASKSAGE: Sage Q&A Forum - RSS feedhttps://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Wed, 28 Oct 2020 19:30:17 +0100Simplification Methods Surveyhttps://ask.sagemath.org/question/54047/simplification-methods-survey/I noted that SageMath has many ways to simplify expressions, including simplify_full(), full_simplify and canonicalize_radical.
Is there a survey nd usage guide available for these?
In particular, I am trying to simplify an expression as in
constants=var('a1,a2,b,c')
((a1*b)^c/(a2*b)^c).simplify_full()
such that I get `(a1/a2)^c`, but without success.Tue, 27 Oct 2020 19:32:18 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/Comment by ortollj for <p>I noted that SageMath has many ways to simplify expressions, including simplify_full(), full_simplify and canonicalize_radical.
Is there a survey nd usage guide available for these?
In particular, I am trying to simplify an expression as in</p>
<pre><code>constants=var('a1,a2,b,c')
((a1*b)^c/(a2*b)^c).simplify_full()
</code></pre>
<p>such that I get <code>(a1/a2)^c</code>, but without success.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54049#post-id-54049There may be a simplification in Sage Maths,
but it doesn't look easy to find anyway.
In any case, me too I was not able to found it!
constants=var('a1,a2,b,c')
f=((a1*b)^c/(a2*b)^c)
show(f.simplify())
show(f.simplify_full())
show(f.simplify_rational(algorithm='simple'))
show(f.simplify_rational())
show(f.simplify_rational(algorithm='simple',map=True))
show(f.simplify_rational(map=True))
show(f.simplify_rational(algorithm='noexpand'))
show(f.simplify_rational(algorithm='full'))
show(f.simplify_real())
show(f.simplify_rectform())
f.simplify_rational??Wed, 28 Oct 2020 08:10:18 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54049#post-id-54049Answer by Emmanuel Charpentier for <p>I noted that SageMath has many ways to simplify expressions, including simplify_full(), full_simplify and canonicalize_radical.
Is there a survey nd usage guide available for these?
In particular, I am trying to simplify an expression as in</p>
<pre><code>constants=var('a1,a2,b,c')
((a1*b)^c/(a2*b)^c).simplify_full()
</code></pre>
<p>such that I get <code>(a1/a2)^c</code>, but without success.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?answer=54052#post-id-54052Nope : without further hypotheses, neither Sage, Sympy nor Mathematica can do better than :
sage: constants=var('a1,a2,b,c')
sage: f=((a1*b)^c/(a2*b)^c)
sage: f.canonicalize_radical()
a1^c/a2^c
Powers and logs are simple to treat in the "usual" special cases and extremely tricky in general. Hiont : think of lomplex logarithm and its branch cut...Wed, 28 Oct 2020 14:21:25 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?answer=54052#post-id-54052Comment by Ingo for <p>Nope : without further hypotheses, neither Sage, Sympy nor Mathematica can do better than :</p>
<pre><code>sage: constants=var('a1,a2,b,c')
sage: f=((a1*b)^c/(a2*b)^c)
sage: f.canonicalize_radical()
a1^c/a2^c
</code></pre>
<p>Powers and logs are simple to treat in the "usual" special cases and extremely tricky in general. Hiont : think of lomplex logarithm and its branch cut...</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54058#post-id-54058I wouldn't mind if the system asks for assumptions to work (as desolve does).Wed, 28 Oct 2020 18:01:20 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54058#post-id-54058Answer by Florentin Jaffredo for <p>I noted that SageMath has many ways to simplify expressions, including simplify_full(), full_simplify and canonicalize_radical.
Is there a survey nd usage guide available for these?
In particular, I am trying to simplify an expression as in</p>
<pre><code>constants=var('a1,a2,b,c')
((a1*b)^c/(a2*b)^c).simplify_full()
</code></pre>
<p>such that I get <code>(a1/a2)^c</code>, but without success.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?answer=54053#post-id-54053When 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](https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825) other question).
Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). 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 returns a tuple, the second element being a condition that must hold for the substitution to be valid.Wed, 28 Oct 2020 14:24:11 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?answer=54053#post-id-54053Comment by Emmanuel Charpentier for <p>When Sage doesn't want to simplify my expressions, I do it myself.</p>
<p>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 <a href="https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825">this</a> other question).</p>
<p>Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). The function will try to apply this rule everywhere, then finish with one step of <code>log_simplify</code>.</p>
<pre><code>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
</code></pre>
<p>It works as expected:</p>
<pre><code>sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
</code></pre>
<p>Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now returns a tuple, the second element being a condition that must hold for the substitution to be valid.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54056#post-id-54056This transform is legitimate only for some cases. See for example the discussion in `Sympy`'s [documentation](https://docs.sympy.org/latest/tutorial/simplification.html#powers) of `powsimp`... The necessary checks could be integrated in `custom_simplify`...Wed, 28 Oct 2020 16:28:47 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54056#post-id-54056Comment by Florentin Jaffredo for <p>When Sage doesn't want to simplify my expressions, I do it myself.</p>
<p>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 <a href="https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825">this</a> other question).</p>
<p>Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). The function will try to apply this rule everywhere, then finish with one step of <code>log_simplify</code>.</p>
<pre><code>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
</code></pre>
<p>It works as expected:</p>
<pre><code>sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
</code></pre>
<p>Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now returns a tuple, the second element being a condition that must hold for the substitution to be valid.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54059#post-id-54059You are completely right. I edited the code. The rules now contain a condition describing when it is valid. This code is getting even uglier...
Well, it was supposed to be a dirty hack anyway.Wed, 28 Oct 2020 18:06:13 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54059#post-id-54059Comment by Ingo for <p>When Sage doesn't want to simplify my expressions, I do it myself.</p>
<p>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 <a href="https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825">this</a> other question).</p>
<p>Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). The function will try to apply this rule everywhere, then finish with one step of <code>log_simplify</code>.</p>
<pre><code>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
</code></pre>
<p>It works as expected:</p>
<pre><code>sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
</code></pre>
<p>Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now returns a tuple, the second element being a condition that must hold for the substitution to be valid.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54060#post-id-54060Thanks, that's indeed a helpful function. Experimenting with it I wonder why
from sage.symbolic.constants import Constant
constants=var('a1,a2,b,c,L')
custom_simplify((a1*b)^c/(L*a1*z+a1*b)^c)
does not work, but it is working if L is replaced by d.Wed, 28 Oct 2020 18:18:02 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54060#post-id-54060Comment by Ingo for <p>When Sage doesn't want to simplify my expressions, I do it myself.</p>
<p>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 <a href="https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825">this</a> other question).</p>
<p>Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). The function will try to apply this rule everywhere, then finish with one step of <code>log_simplify</code>.</p>
<pre><code>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
</code></pre>
<p>It works as expected:</p>
<pre><code>sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
</code></pre>
<p>Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now returns a tuple, the second element being a condition that must hold for the substitution to be valid.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54061#post-id-54061My initial problem was not whether there is a function that handles this specific term, but whether there is some guidance to find functions that may handle some given term, so I don't think this was overkill.
If there is no automatic selection of a simplification method, the approach to define a set of rewrite rules and apply them is helpful, preferably encapsulated in a single function which takes a term and a ruleset and applies it. https://wiki.sagemath.org/symbolics/rewrite is close to that, except that it has a fixed ruleset.
.
I confess that I am looking for an easy-to-use function as I am not a Sage expert.Wed, 28 Oct 2020 18:31:05 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54061#post-id-54061Comment by Florentin Jaffredo for <p>When Sage doesn't want to simplify my expressions, I do it myself.</p>
<p>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 <a href="https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/#51825">this</a> other question).</p>
<p>Here I use the rule $a^b\to e^{b \log a}$, defined on the third line (holding the result, otherwise it immediatly goes back to $a^b$). The function will try to apply this rule everywhere, then finish with one step of <code>log_simplify</code>.</p>
<pre><code>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
</code></pre>
<p>It works as expected:</p>
<pre><code>sage: assume(a1>0, a2>0, b>0)
sage: custom_simplify((a1*b)^c/(a2*b)^c)
(a1/a2)^c
</code></pre>
<p>Edit: Modified for use with assumptions for correctness, as suggested by Emmanuel Charpentier. The rules now returns a tuple, the second element being a condition that must hold for the substitution to be valid.</p>
https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54063#post-id-54063hmm, I don't really know. How do you define ``z``? What does the import do? Did you remember to use the assumptions ``assume(a1>0, b>0, L>0)`` ?
This works for me:
sage: constants=var('a1,a2,b,c,L')
sage: assume(a1>0, a2>0, L>0, b>0)
sage: custom_simplify((a1*b)^c/(L*a1*a2+a1*b)^c)
(b/(L*a2 + b))^cWed, 28 Oct 2020 19:30:17 +0100https://ask.sagemath.org/question/54047/simplification-methods-survey/?comment=54063#post-id-54063