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.Mon, 08 Jun 2020 17:15:17 +0200How to simplify dirac_delta?https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/Various manipulations are possible with `dirac_delta` and its derivatives. How can I teach sage to simplify these? For example, the following Green's function for a free particle in 1D could simplify to simply `dirac_delta(x)`:
sage: var('x,k')
sage: G = heaviside(x)*sin(k*x)/k
sage: simplify(k**2*G + diff(G, x, x))
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
How can I teach sage to perform the following simplifications
f(x)*dirac_delta(x)
-> f(0)*dirac_delta(x)
f(x)*diff(dirac_delta(x),x)
-> diff(f(x), x)*dirac_delta(x)
-> diff(f(x), x).subs(x=0)*dirac_delta(x)
which would bring the answer into the desired form `dirac_delta(x)`?Sat, 06 Jun 2020 08:16:37 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/Comment by ortollj for <p>Various manipulations are possible with <code>dirac_delta</code> and its derivatives. How can I teach sage to simplify these? For example, the following Green's function for a free particle in 1D could simplify to simply <code>dirac_delta(x)</code>:</p>
<pre><code>sage: var('x,k')
sage: G = heaviside(x)*sin(k*x)/k
sage: simplify(k**2*G + diff(G, x, x))
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
</code></pre>
<p>How can I teach sage to perform the following simplifications</p>
<pre><code>f(x)*dirac_delta(x)
-> f(0)*dirac_delta(x)
f(x)*diff(dirac_delta(x),x)
-> diff(f(x), x)*dirac_delta(x)
-> diff(f(x), x).subs(x=0)*dirac_delta(x)
</code></pre>
<p>which would bring the answer into the desired form <code>dirac_delta(x)</code>?</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51781#post-id-51781just out of curiosity: can someone tell me what it means to use this `%var x, k` syntax instead of
var('x,k') ?Sat, 06 Jun 2020 09:12:57 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51781#post-id-51781Comment by mforbes for <p>Various manipulations are possible with <code>dirac_delta</code> and its derivatives. How can I teach sage to simplify these? For example, the following Green's function for a free particle in 1D could simplify to simply <code>dirac_delta(x)</code>:</p>
<pre><code>sage: var('x,k')
sage: G = heaviside(x)*sin(k*x)/k
sage: simplify(k**2*G + diff(G, x, x))
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
</code></pre>
<p>How can I teach sage to perform the following simplifications</p>
<pre><code>f(x)*dirac_delta(x)
-> f(0)*dirac_delta(x)
f(x)*diff(dirac_delta(x),x)
-> diff(f(x), x)*dirac_delta(x)
-> diff(f(x), x).subs(x=0)*dirac_delta(x)
</code></pre>
<p>which would bring the answer into the desired form <code>dirac_delta(x)</code>?</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51783#post-id-51783Ah, sorry, that is a feature of [Sage worksheets](https://doc.cocalc.com/sagews.html) on CoCalc. It is the same thing. I will remove it.Sat, 06 Jun 2020 10:59:34 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51783#post-id-51783Answer by Juanjo for <p>Various manipulations are possible with <code>dirac_delta</code> and its derivatives. How can I teach sage to simplify these? For example, the following Green's function for a free particle in 1D could simplify to simply <code>dirac_delta(x)</code>:</p>
<pre><code>sage: var('x,k')
sage: G = heaviside(x)*sin(k*x)/k
sage: simplify(k**2*G + diff(G, x, x))
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
</code></pre>
<p>How can I teach sage to perform the following simplifications</p>
<pre><code>f(x)*dirac_delta(x)
-> f(0)*dirac_delta(x)
f(x)*diff(dirac_delta(x),x)
-> diff(f(x), x)*dirac_delta(x)
-> diff(f(x), x).subs(x=0)*dirac_delta(x)
</code></pre>
<p>which would bring the answer into the desired form <code>dirac_delta(x)</code>?</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?answer=51790#post-id-51790Consider the following code:
def simplify_dirac_delta(linear_combination, t):
r"""
Simplify a ``linear combination`` of the form
a_0(t) + a_1(t)*d_1(t) + a_2(t)*d_2(t) + ... + a_n(t)*d_n(t)
where each a_i(t) is a symbolic expression depending
on the symbolic variable ``t`` and each d_i(t) is
either dirac_delta(t) or diff(dirac_delta(t), t).
Simplification is done by applying the following
substitution rules:
(Rule 1) f(t) * diff(dirac_delta(t), t)
--> diff(f(t), t) * dirac_delta(t)
(Rule 2) f(t) * dirac_delta(t)
--> f(0) * dirac_delta(t)
"""
# Write the linear combination in the form
# c_0(t) + c_1(t) * diff(dirac_delta(t),t)
# and apply Rule 1
var("dd")
expression = linear_combination.collect(diff(dirac_delta(t),t))
expr = expression.subs({diff(dirac_delta(t),t): dd})
c_0 = expr.coefficient(dd,0)
c_1 = expr.coefficient(dd,1)
dc_1 = diff(c_1,t)
expression = c_0 + dc_1*dirac_delta(t)
# Write now the resulting linear combination in the form
# c_0(t) + c_1(t) * dirac_delta(t),t)
# and apply Rule 2
expression = expression.collect(dirac_delta(t))
expr = expression.subs({dirac_delta(t): dd})
c_0 = expr.coefficient(dd,0)
c_1 = expr.coefficient(dd,1)
return c_0 + c_1.subs({t:0})*dirac_delta(t)
The docstring and comments explain quite explicitly what `simplify_dirac_delta` does. Let us test this function. To this end, let us consider
$$
\cos(x)\, \delta(x)+e^{2x}\,\delta'(x)+3\sin(4x)\,\delta'(x)+9e^{3x}.
$$
The simplification rules transform this expression into
$$
\begin{aligned}
&\cos(x)\,\delta(x)+2e^{2x}\delta(x)+12\cos(4x)\,\delta(x)+9e^{3x} \\\\
&\qquad=(1+2+12)\delta(x)+9e^{3x}=15\delta(x)+9e^{3x}.
\end{aligned}
$$
Now we apply `simplify_dirac_delta`:
sage: DD = dirac_delta(x)
sage: dDD = diff(dirac_delta(x),x)
sage: expr = cos(x)*DD + exp(2*x)*dDD + 3*sin(4*x)*dDD + 9*exp(3*x)
sage: simplify_dirac_delta(expr,x)
15*dirac_delta(x) + 9*e^(3*x)
We get the expected result. Now, let us consider your example:
sage: var('x,k')
(x, k)
sage: G = heaviside(x)*sin(k*x)/k
sage: expr = simplify(k**2*G + diff(G, x, x)); expr
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
sage: simplify_dirac_delta(expr,x)
3*dirac_delta(x)
Once again we obtain the expected result.
The above code and the examples can be run in this [SageMath Cell](https://sagecell.sagemath.org/?z=eJytVMGO2jAQvfMVI_awTsimkO2lSO1pJe7toUcw8aRYBBvZZgFV--8d28kmQFBXanMAe_Lem5k3AwIrsHK3r2V1XgppeLkUWDvOaqmQm2Wpd2upuJNaZeCS-QjoMePxOBx-NEzgsFpFBvQYqxXoCtwGodJmFxjhgy-nzCUwocOMDqkIX-FexHsR73meh6iKUf_VqRw3aBCQlxtCSE-Qlgqx591a17IEPO0NWkt1gMA9KiHVr0CkgK_pHfjKjeTrGqkHRyVzJaKqaFUDCyWRDPQ9opfaR6qKXYa9VXlXaWOTLIMrvkyhFcKafNvv6zPV1ZhU1_rob4FlD2vrpDsEjjnUaOedJPtOAZgldKx8Hem9MiL8-nl6-hYJVQtLrzrrZSkustyAhrQrNr2DblfnAX4a6TA0frs5INXl3jy8y5ft8pRxa4Y7b7I9hGkGlyE6Fv2gkbOxEOOI6m3KV7hd_LykwWDp2HCiToPYnVTu58d-D3PmIMRbJFI_DY_yYEVbIlFRLpFNW8DsDmAWASIiQiY6tr1fdOWzTAIyHRhKOwylj8F24h1q5zfxn0fzoakUcFtxz8nO_77a33zvY_-r3wbdwajGUkI3Gd18-pZcuzt6eQmj6YKnZCSa4NVmnJKMXjYNldpSICXkxNfCipRuIlyfUysV-9wFvqQe8UyBkd3oIxv8Q_e6pE8lnTLYUgb_G3g8ZdvHZLSg6wb5q7RSoE_rE2xJ79O2rafVpHBapAu_TL7-RQYk52VDZg_-SBF_AIke9G4=&lang=sage&interacts=eJyLjgUAARUAuQ==)
Sat, 06 Jun 2020 15:59:32 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?answer=51790#post-id-51790Answer by Florentin Jaffredo for <p>Various manipulations are possible with <code>dirac_delta</code> and its derivatives. How can I teach sage to simplify these? For example, the following Green's function for a free particle in 1D could simplify to simply <code>dirac_delta(x)</code>:</p>
<pre><code>sage: var('x,k')
sage: G = heaviside(x)*sin(k*x)/k
sage: simplify(k**2*G + diff(G, x, x))
2*cos(k*x)*dirac_delta(x) + sin(k*x)*diff(dirac_delta(x), x)/k
</code></pre>
<p>How can I teach sage to perform the following simplifications</p>
<pre><code>f(x)*dirac_delta(x)
-> f(0)*dirac_delta(x)
f(x)*diff(dirac_delta(x),x)
-> diff(f(x), x)*dirac_delta(x)
-> diff(f(x), x).subs(x=0)*dirac_delta(x)
</code></pre>
<p>which would bring the answer into the desired form <code>dirac_delta(x)</code>?</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?answer=51825#post-id-51825Here is a more generic code, making use of wildcards. It should work in many more cases than just linear combinations. It also makes it easier to add new rules.
def simplify_dirac_delta(E, t):
"""
Apply some rules on expression E as long as it changes. The rules depend on a parameter t.
"""
w = SR.wild(0)
rules = {w*dirac_delta(t): lambda f: f.subs({t: 0})*dirac_delta(t),
w*diff(dirac_delta(t), t): lambda f: diff(f, t)*dirac_delta(t)}
def apply_rules():
nonlocal E
for r in rules:
for e in E.find(r):
f = e.match(r)[w]
E = E.substitute({e: rules[r](f)})
return E
while(E!=apply_rules()):
pass
return E
it can be used like this:
sage: simplify_dirac_delta(k**2*G + diff(G, x, x), x)
3*dirac_delta(x)
Simplifications rules are given as a dictionary. The function will try to apply these rules as long as the result changes, so you have to make sure that your rules can't loop back (alternatively you can delete the loop, and only apply the rules a fixed number of times).
Unfortunately, ``diff`` is not a symbolic function and does not accept wildcards, so I don't know how to match a derivative, and it is necessary to pass ``x`` as an argument.Mon, 08 Jun 2020 12:39:56 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?answer=51825#post-id-51825Comment by Juanjo for <p>Here is a more generic code, making use of wildcards. It should work in many more cases than just linear combinations. It also makes it easier to add new rules.</p>
<pre><code>def simplify_dirac_delta(E, t):
"""
Apply some rules on expression E as long as it changes. The rules depend on a parameter t.
"""
w = SR.wild(0)
rules = {w*dirac_delta(t): lambda f: f.subs({t: 0})*dirac_delta(t),
w*diff(dirac_delta(t), t): lambda f: diff(f, t)*dirac_delta(t)}
def apply_rules():
nonlocal E
for r in rules:
for e in E.find(r):
f = e.match(r)[w]
E = E.substitute({e: rules[r](f)})
return E
while(E!=apply_rules()):
pass
return E
</code></pre>
<p>it can be used like this:</p>
<pre><code>sage: simplify_dirac_delta(k**2*G + diff(G, x, x), x)
3*dirac_delta(x)
</code></pre>
<p>Simplifications rules are given as a dictionary. The function will try to apply these rules as long as the result changes, so you have to make sure that your rules can't loop back (alternatively you can delete the loop, and only apply the rules a fixed number of times).</p>
<p>Unfortunately, <code>diff</code> is not a symbolic function and does not accept wildcards, so I don't know how to match a derivative, and it is necessary to pass <code>x</code> as an argument.</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51831#post-id-51831Very interesting answer. I've learn a lot from it.Mon, 08 Jun 2020 16:33:19 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51831#post-id-51831Comment by Florentin Jaffredo for <p>Here is a more generic code, making use of wildcards. It should work in many more cases than just linear combinations. It also makes it easier to add new rules.</p>
<pre><code>def simplify_dirac_delta(E, t):
"""
Apply some rules on expression E as long as it changes. The rules depend on a parameter t.
"""
w = SR.wild(0)
rules = {w*dirac_delta(t): lambda f: f.subs({t: 0})*dirac_delta(t),
w*diff(dirac_delta(t), t): lambda f: diff(f, t)*dirac_delta(t)}
def apply_rules():
nonlocal E
for r in rules:
for e in E.find(r):
f = e.match(r)[w]
E = E.substitute({e: rules[r](f)})
return E
while(E!=apply_rules()):
pass
return E
</code></pre>
<p>it can be used like this:</p>
<pre><code>sage: simplify_dirac_delta(k**2*G + diff(G, x, x), x)
3*dirac_delta(x)
</code></pre>
<p>Simplifications rules are given as a dictionary. The function will try to apply these rules as long as the result changes, so you have to make sure that your rules can't loop back (alternatively you can delete the loop, and only apply the rules a fixed number of times).</p>
<p>Unfortunately, <code>diff</code> is not a symbolic function and does not accept wildcards, so I don't know how to match a derivative, and it is necessary to pass <code>x</code> as an argument.</p>
https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51833#post-id-51833I'm glad it was useful. I use this kind of custom simplification all the time. Perhaps there should be an option in ``simplify_full`` to add user-defined rules ?Mon, 08 Jun 2020 17:15:17 +0200https://ask.sagemath.org/question/51779/how-to-simplify-dirac_delta/?comment=51833#post-id-51833