Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/functions/generalized.py
4045 views
1
r"""
2
Generalized Functions
3
4
Sage implements several generalized functions (also known as
5
distributions) such as Dirac delta, Heaviside step functions. These
6
generalized functions can be manipulated within Sage like any other
7
symbolic functions.
8
9
10
AUTHORS:
11
12
- Golam Mortuza Hossain (2009-06-26): initial version
13
14
15
EXAMPLES:
16
17
Dirac delta function::
18
19
sage: dirac_delta(x)
20
dirac_delta(x)
21
22
Heaviside step function::
23
24
sage: heaviside(x)
25
heaviside(x)
26
27
Unit step function::
28
29
sage: unit_step(x)
30
unit_step(x)
31
32
Signum (sgn) function::
33
34
sage: sgn(x)
35
sgn(x)
36
37
Kronecker delta function::
38
39
sage: m,n=var('m,n')
40
sage: kronecker_delta(m,n)
41
kronecker_delta(m, n)
42
43
"""
44
45
##############################################################################
46
#
47
# Copyright (C) 2009 Golam Mortuza Hossain <[email protected]>
48
#
49
# Distributed under the terms of the GNU General Public License (GPL v2+)
50
# http://www.gnu.org/licenses/
51
#
52
##############################################################################
53
54
from sage.symbolic.function import BuiltinFunction
55
from sage.rings.all import ComplexIntervalField, ZZ
56
57
class FunctionDiracDelta(BuiltinFunction):
58
r"""
59
The Dirac delta (generalized) function, `\delta(x)` (``dirac_delta(x)``).
60
61
INPUT:
62
63
- ``x`` - a real number or a symbolic expression
64
65
DEFINITION:
66
67
Dirac delta function `\delta(x)`, is defined in Sage as:
68
69
`\delta(x) = 0` for real `x \ne 0` and
70
`\int_{-\infty}^{\infty} \delta(x) dx = 1`
71
72
Its alternate definition with respect to an arbitrary test
73
function `f(x)` is
74
75
`\int_{-\infty}^{\infty} f(x) \delta(x-a) dx = f(a)`
76
77
EXAMPLES::
78
79
sage: dirac_delta(1)
80
0
81
sage: dirac_delta(0)
82
dirac_delta(0)
83
sage: dirac_delta(x)
84
dirac_delta(x)
85
86
REFERENCES:
87
88
- http://en.wikipedia.org/wiki/Dirac_delta_function
89
90
"""
91
def __init__(self):
92
r"""
93
The Dirac delta (generalized) function, ``dirac_delta(x)``.
94
95
INPUT:
96
97
- ``x`` - a real number or a symbolic expression
98
99
EXAMPLES::
100
101
sage: dirac_delta(1)
102
0
103
sage: dirac_delta(0)
104
dirac_delta(0)
105
sage: dirac_delta(x)
106
dirac_delta(x)
107
sage: latex(dirac_delta(x))
108
\delta\left(x\right)
109
110
sage: loads(dumps(dirac_delta(x)))
111
dirac_delta(x)
112
"""
113
BuiltinFunction.__init__(self, "dirac_delta", latex_name=r"\delta",
114
conversions=dict(maxima='delta',
115
mathematica='DiracDelta'))
116
117
def _eval_(self, x):
118
"""
119
INPUT:
120
121
- ``x`` - a real number or a symbolic expression
122
123
EXAMPLES::
124
125
sage: dirac_delta(1)
126
0
127
sage: dirac_delta(0)
128
dirac_delta(0)
129
sage: dirac_delta(x)
130
dirac_delta(x)
131
sage: dirac_delta(exp(-10000000000000000000))
132
0
133
134
Evaluation test::
135
136
sage: dirac_delta(x).subs(x=1)
137
0
138
"""
139
try:
140
approx_x = ComplexIntervalField()(x)
141
if bool(approx_x.imag() == 0): # x is real
142
if bool(approx_x.real() == 0): # x is zero
143
return None
144
else:
145
return 0
146
except: # x is symbolic
147
pass
148
return None
149
150
dirac_delta = FunctionDiracDelta()
151
152
class FunctionHeaviside(BuiltinFunction):
153
r"""
154
The Heaviside step function, `H(x)` (``heaviside(x)``).
155
156
INPUT:
157
158
- ``x`` - a real number or a symbolic expression
159
160
DEFINITION:
161
162
The Heaviside step function, `H(x)` is defined in Sage as:
163
164
`H(x) = 0` for `x < 0` and `H(x) = 1` for `x > 0`
165
166
EXAMPLES::
167
168
sage: heaviside(-1)
169
0
170
sage: heaviside(1)
171
1
172
sage: heaviside(0)
173
heaviside(0)
174
sage: heaviside(x)
175
heaviside(x)
176
177
REFERENCES:
178
179
- http://en.wikipedia.org/wiki/Heaviside_function
180
181
"""
182
def __init__(self):
183
r"""
184
The Heaviside step function, ``heaviside(x)``.
185
186
INPUT:
187
188
- ``x`` - a real number or a symbolic expression
189
190
EXAMPLES::
191
192
sage: heaviside(-1)
193
0
194
sage: heaviside(1)
195
1
196
sage: heaviside(0)
197
heaviside(0)
198
sage: heaviside(x)
199
heaviside(x)
200
sage: latex(heaviside(x))
201
H\left(x\right)
202
"""
203
BuiltinFunction.__init__(self, "heaviside", latex_name="H",
204
conversions=dict(mathematica='HeavisideTheta'))
205
206
def _eval_(self, x):
207
"""
208
INPUT:
209
210
- ``x`` - a real number or a symbolic expression
211
212
EXAMPLES::
213
214
sage: heaviside(-1/2)
215
0
216
sage: heaviside(1)
217
1
218
sage: heaviside(0)
219
heaviside(0)
220
sage: heaviside(x)
221
heaviside(x)
222
sage: heaviside(exp(-1000000000000000000000))
223
1
224
225
Evaluation test::
226
227
sage: heaviside(x).subs(x=1)
228
1
229
sage: heaviside(x).subs(x=-1)
230
0
231
232
::
233
234
sage: ex = heaviside(x)+1
235
sage: t = loads(dumps(ex)); t
236
heaviside(x) + 1
237
sage: bool(t == ex)
238
True
239
sage: t.subs(x=1)
240
2
241
"""
242
try:
243
approx_x = ComplexIntervalField()(x)
244
if bool(approx_x.imag() == 0): # x is real
245
if bool(approx_x.real() == 0): # x is zero
246
return None
247
# Now we have a non-zero real
248
if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
249
return 1
250
else:
251
return 0
252
except: # x is symbolic
253
pass
254
return None
255
256
def _derivative_(self, x, diff_param=None):
257
"""
258
Derivative of Heaviside step function
259
260
EXAMPLES::
261
262
sage: heaviside(x).diff(x)
263
dirac_delta(x)
264
"""
265
return dirac_delta(x)
266
267
heaviside = FunctionHeaviside()
268
269
class FunctionUnitStep(BuiltinFunction):
270
r"""
271
The unit step function, `\mathrm{u}(x)` (``unit_step(x)``).
272
273
INPUT:
274
275
- ``x`` - a real number or a symbolic expression
276
277
DEFINITION:
278
279
The unit step function, `\mathrm{u}(x)` is defined in Sage as:
280
281
`\mathrm{u}(x) = 0` for `x < 0` and `\mathrm{u}(x) = 1` for `x \geq 0`
282
283
EXAMPLES::
284
285
sage: unit_step(-1)
286
0
287
sage: unit_step(1)
288
1
289
sage: unit_step(0)
290
1
291
sage: unit_step(x)
292
unit_step(x)
293
"""
294
def __init__(self):
295
r"""
296
The unit step function, ``unit_step(x)``.
297
298
INPUT:
299
300
- ``x`` - a real number or a symbolic expression
301
302
EXAMPLES:
303
304
sage: unit_step(-1)
305
0
306
sage: unit_step(1)
307
1
308
sage: unit_step(0)
309
1
310
sage: unit_step(x)
311
unit_step(x)
312
sage: latex(unit_step(x))
313
\mathrm{u}\left(x\right)
314
315
TESTS::
316
317
sage: t = loads(dumps(unit_step(x)+1)); t
318
unit_step(x) + 1
319
sage: t.subs(x=0)
320
2
321
"""
322
BuiltinFunction.__init__(self, "unit_step", latex_name=r"\mathrm{u}",
323
conversions=dict(mathematica='UnitStep'))
324
325
def _eval_(self, x):
326
"""
327
INPUT:
328
329
- ``x`` - a real number or a symbolic expression
330
331
EXAMPLES::
332
333
sage: unit_step(-1)
334
0
335
sage: unit_step(1)
336
1
337
sage: unit_step(0)
338
1
339
sage: unit_step(x)
340
unit_step(x)
341
sage: unit_step(-exp(-10000000000000000000))
342
0
343
344
Evaluation test::
345
346
sage: unit_step(x).subs(x=1)
347
1
348
sage: unit_step(x).subs(x=0)
349
1
350
"""
351
try:
352
approx_x = ComplexIntervalField()(x)
353
if bool(approx_x.imag() == 0): # x is real
354
if bool(approx_x.real() == 0): # x is zero
355
return 1
356
# Now we have a non-zero real
357
if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
358
return 1
359
else:
360
return 0
361
except: # x is symbolic
362
pass
363
return None
364
365
def _derivative_(self, x, diff_param=None):
366
"""
367
Derivative of unit step function
368
369
EXAMPLES::
370
371
sage: unit_step(x).diff(x)
372
dirac_delta(x)
373
"""
374
return dirac_delta(x)
375
376
unit_step = FunctionUnitStep()
377
378
class FunctionSignum(BuiltinFunction):
379
r"""
380
The signum or sgn function `\mathrm{sgn}(x)` (``sgn(x)``).
381
382
INPUT:
383
384
- ``x`` - a real number or a symbolic expression
385
386
DEFINITION:
387
388
The sgn function, `\mathrm{sgn}(x)` is defined as:
389
390
`\mathrm{sgn}(x) = 1` for `x > 0`,
391
`\mathrm{sgn}(x) = 0` for `x = 0` and
392
`\mathrm{sgn}(x) = -1` for `x < 0`
393
394
EXAMPLES::
395
396
sage: sgn(-1)
397
-1
398
sage: sgn(1)
399
1
400
sage: sgn(0)
401
0
402
sage: sgn(x)
403
sgn(x)
404
405
We can also use ``sign``::
406
407
sage: sign(1)
408
1
409
sage: sign(0)
410
0
411
sage: a = AA(-5).nth_root(7)
412
sage: sign(a)
413
-1
414
415
TESTS:
416
417
Check if conversion to sympy works #11921::
418
419
sage: sgn(x)._sympy_()
420
sign(x)
421
422
423
REFERENCES:
424
425
- http://en.wikipedia.org/wiki/Sign_function
426
427
"""
428
def __init__(self):
429
r"""
430
The sgn function, ``sgn(x)``.
431
432
EXAMPLES:
433
434
sage: sgn(-1)
435
-1
436
sage: sgn(1)
437
1
438
sage: sgn(0)
439
0
440
sage: sgn(x)
441
sgn(x)
442
"""
443
BuiltinFunction.__init__(self, "sgn", latex_name=r"\mathrm{sgn}",
444
conversions=dict(maxima='signum',mathematica='Sign',sympy='sign'))
445
446
def _eval_(self, x):
447
"""
448
449
EXAMPLES::
450
451
sage: sgn(-1)
452
-1
453
sage: sgn(1)
454
1
455
sage: sgn(0)
456
0
457
sage: sgn(x)
458
sgn(x)
459
sage: sgn(-exp(-10000000000000000000))
460
-1
461
462
Evaluation test::
463
464
sage: sgn(x).subs(x=1)
465
1
466
sage: sgn(x).subs(x=0)
467
0
468
sage: sgn(x).subs(x=-1)
469
-1
470
471
More tests::
472
473
sage: sign(RR(2))
474
1
475
sage: sign(RDF(2))
476
1
477
sage: sign(AA(-2))
478
-1
479
sage: sign(AA(0))
480
0
481
"""
482
if hasattr(x,'sign'): # First check if x has a sign method
483
return x.sign()
484
if hasattr(x,'sgn'): # or a sgn method
485
return x.sgn()
486
try:
487
approx_x = ComplexIntervalField()(x)
488
if bool(approx_x.imag() == 0): # x is real
489
if bool(approx_x.real() == 0): # x is zero
490
return ZZ(0)
491
# Now we have a non-zero real
492
if bool((approx_x**(0.5)).imag() == 0): # Check: x > 0
493
return ZZ(1)
494
else:
495
return ZZ(-1)
496
except: # x is symbolic
497
pass
498
return None
499
500
def _derivative_(self, x, diff_param=None):
501
"""
502
Derivative of sgn function
503
504
EXAMPLES::
505
506
sage: sgn(x).diff(x)
507
2*dirac_delta(x)
508
"""
509
assert diff_param == 0
510
return 2*dirac_delta(x)
511
512
sgn = FunctionSignum()
513
sign = sgn
514
515
class FunctionKroneckerDelta(BuiltinFunction):
516
r"""
517
The Kronecker delta function `\delta_{m,n}` (``kronecker_delta(m, n)``).
518
519
INPUT:
520
521
- ``m`` - a number or a symbolic expression
522
- ``n`` - a number or a symbolic expression
523
524
DEFINITION:
525
526
Kronecker delta function `\delta_{m,n}` is defined as:
527
528
`\delta_{m,n} = 0` for `m \ne n` and
529
`\delta_{m,n} = 1` for `m = n`
530
531
EXAMPLES::
532
533
sage: kronecker_delta(1,2)
534
0
535
sage: kronecker_delta(1,1)
536
1
537
sage: m,n=var('m,n')
538
sage: kronecker_delta(m,n)
539
kronecker_delta(m, n)
540
541
REFERENCES:
542
543
- http://en.wikipedia.org/wiki/Kronecker_delta
544
545
"""
546
def __init__(self):
547
r"""
548
The Kronecker delta function.
549
550
EXAMPLES::
551
552
sage: kronecker_delta(1,2)
553
0
554
sage: kronecker_delta(1,1)
555
1
556
"""
557
BuiltinFunction.__init__(self, "kronecker_delta", nargs=2,
558
conversions=dict(maxima='kron_delta',
559
mathematica='KroneckerDelta'))
560
561
def _eval_(self, m, n):
562
"""
563
The Kronecker delta function.
564
565
EXAMPLES::
566
567
sage: kronecker_delta(1,2)
568
0
569
sage: kronecker_delta(1,1)
570
1
571
572
Kronecker delta is a symmetric function. We keep arguments sorted to
573
ensure that (k_d(m, n) - k_d(n, m) cancels automatically::
574
575
sage: x,y=var('x,y')
576
sage: kronecker_delta(x, y)
577
kronecker_delta(x, y)
578
sage: kronecker_delta(y, x)
579
kronecker_delta(x, y)
580
sage: kronecker_delta(x,2*x)
581
kronecker_delta(2*x, x)
582
583
Evaluation test::
584
585
sage: kronecker_delta(1,x).subs(x=1)
586
1
587
"""
588
if bool(repr(m) > repr(n)):
589
return kronecker_delta(n, m)
590
591
x = m - n
592
try:
593
approx_x = ComplexIntervalField()(x)
594
if bool(approx_x.imag() == 0): # x is real
595
if bool(approx_x.real() == 0): # x is zero
596
return 1
597
else:
598
return 0
599
else:
600
return 0 # x is complex
601
except: # x is symbolic
602
pass
603
return None
604
605
def _derivative_(self, *args, **kwds):
606
"""
607
Derivative of Kronecker delta
608
609
EXAMPLES::
610
611
sage: kronecker_delta(x,1).diff(x)
612
0
613
"""
614
# Kronecker delta is non-zero (but finite) only in the set of
615
# zero-measure unlike Dirac delta. Consequently, it is null
616
# for the purpose of integration/differentiation. For *discrete sum*
617
# Kronecker delta is however non-trivial.
618
return 0
619
620
def _print_latex_(self, m, n, **kwds):
621
"""
622
Return latex expression
623
624
EXAMPLES::
625
626
sage: from sage.misc.latex import latex
627
sage: m,n=var('m,n')
628
sage: latex(kronecker_delta(m,n))
629
\delta_{m,n}
630
631
"""
632
from sage.misc.latex import latex
633
return "\\delta_{%s,%s}"%(latex(m), latex(n))
634
635
kronecker_delta = FunctionKroneckerDelta()
636
637
638