Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /sympy /concrete /delta.py
| """ | |
| This module implements sums and products containing the Kronecker Delta function. | |
| References | |
| ========== | |
| .. [1] https://mathworld.wolfram.com/KroneckerDelta.html | |
| """ | |
| from .products import product | |
| from .summations import Sum, summation | |
| from sympy.core import Add, Mul, S, Dummy | |
| from sympy.core.cache import cacheit | |
| from sympy.core.sorting import default_sort_key | |
| from sympy.functions import KroneckerDelta, Piecewise, piecewise_fold | |
| from sympy.polys.polytools import factor | |
| from sympy.sets.sets import Interval | |
| from sympy.solvers.solvers import solve | |
| def _expand_delta(expr, index): | |
| """ | |
| Expand the first Add containing a simple KroneckerDelta. | |
| """ | |
| if not expr.is_Mul: | |
| return expr | |
| delta = None | |
| func = Add | |
| terms = [S.One] | |
| for h in expr.args: | |
| if delta is None and h.is_Add and _has_simple_delta(h, index): | |
| delta = True | |
| func = h.func | |
| terms = [terms[0]*t for t in h.args] | |
| else: | |
| terms = [t*h for t in terms] | |
| return func(*terms) | |
| def _extract_delta(expr, index): | |
| """ | |
| Extract a simple KroneckerDelta from the expression. | |
| Explanation | |
| =========== | |
| Returns the tuple ``(delta, newexpr)`` where: | |
| - ``delta`` is a simple KroneckerDelta expression if one was found, | |
| or ``None`` if no simple KroneckerDelta expression was found. | |
| - ``newexpr`` is a Mul containing the remaining terms; ``expr`` is | |
| returned unchanged if no simple KroneckerDelta expression was found. | |
| Examples | |
| ======== | |
| >>> from sympy import KroneckerDelta | |
| >>> from sympy.concrete.delta import _extract_delta | |
| >>> from sympy.abc import x, y, i, j, k | |
| >>> _extract_delta(4*x*y*KroneckerDelta(i, j), i) | |
| (KroneckerDelta(i, j), 4*x*y) | |
| >>> _extract_delta(4*x*y*KroneckerDelta(i, j), k) | |
| (None, 4*x*y*KroneckerDelta(i, j)) | |
| See Also | |
| ======== | |
| sympy.functions.special.tensor_functions.KroneckerDelta | |
| deltaproduct | |
| deltasummation | |
| """ | |
| if not _has_simple_delta(expr, index): | |
| return (None, expr) | |
| if isinstance(expr, KroneckerDelta): | |
| return (expr, S.One) | |
| if not expr.is_Mul: | |
| raise ValueError("Incorrect expr") | |
| delta = None | |
| terms = [] | |
| for arg in expr.args: | |
| if delta is None and _is_simple_delta(arg, index): | |
| delta = arg | |
| else: | |
| terms.append(arg) | |
| return (delta, expr.func(*terms)) | |
| def _has_simple_delta(expr, index): | |
| """ | |
| Returns True if ``expr`` is an expression that contains a KroneckerDelta | |
| that is simple in the index ``index``, meaning that this KroneckerDelta | |
| is nonzero for a single value of the index ``index``. | |
| """ | |
| if expr.has(KroneckerDelta): | |
| if _is_simple_delta(expr, index): | |
| return True | |
| if expr.is_Add or expr.is_Mul: | |
| return any(_has_simple_delta(arg, index) for arg in expr.args) | |
| return False | |
| def _is_simple_delta(delta, index): | |
| """ | |
| Returns True if ``delta`` is a KroneckerDelta and is nonzero for a single | |
| value of the index ``index``. | |
| """ | |
| if isinstance(delta, KroneckerDelta) and delta.has(index): | |
| p = (delta.args[0] - delta.args[1]).as_poly(index) | |
| if p: | |
| return p.degree() == 1 | |
| return False | |
| def _remove_multiple_delta(expr): | |
| """ | |
| Evaluate products of KroneckerDelta's. | |
| """ | |
| if expr.is_Add: | |
| return expr.func(*list(map(_remove_multiple_delta, expr.args))) | |
| if not expr.is_Mul: | |
| return expr | |
| eqs = [] | |
| newargs = [] | |
| for arg in expr.args: | |
| if isinstance(arg, KroneckerDelta): | |
| eqs.append(arg.args[0] - arg.args[1]) | |
| else: | |
| newargs.append(arg) | |
| if not eqs: | |
| return expr | |
| solns = solve(eqs, dict=True) | |
| if len(solns) == 0: | |
| return S.Zero | |
| elif len(solns) == 1: | |
| newargs += [KroneckerDelta(k, v) for k, v in solns[0].items()] | |
| expr2 = expr.func(*newargs) | |
| if expr != expr2: | |
| return _remove_multiple_delta(expr2) | |
| return expr | |
| def _simplify_delta(expr): | |
| """ | |
| Rewrite a KroneckerDelta's indices in its simplest form. | |
| """ | |
| if isinstance(expr, KroneckerDelta): | |
| try: | |
| slns = solve(expr.args[0] - expr.args[1], dict=True) | |
| if slns and len(slns) == 1: | |
| return Mul(*[KroneckerDelta(*(key, value)) | |
| for key, value in slns[0].items()]) | |
| except NotImplementedError: | |
| pass | |
| return expr | |
| def deltaproduct(f, limit): | |
| """ | |
| Handle products containing a KroneckerDelta. | |
| See Also | |
| ======== | |
| deltasummation | |
| sympy.functions.special.tensor_functions.KroneckerDelta | |
| sympy.concrete.products.product | |
| """ | |
| if ((limit[2] - limit[1]) < 0) == True: | |
| return S.One | |
| if not f.has(KroneckerDelta): | |
| return product(f, limit) | |
| if f.is_Add: | |
| # Identify the term in the Add that has a simple KroneckerDelta | |
| delta = None | |
| terms = [] | |
| for arg in sorted(f.args, key=default_sort_key): | |
| if delta is None and _has_simple_delta(arg, limit[0]): | |
| delta = arg | |
| else: | |
| terms.append(arg) | |
| newexpr = f.func(*terms) | |
| k = Dummy("kprime", integer=True) | |
| if isinstance(limit[1], int) and isinstance(limit[2], int): | |
| result = deltaproduct(newexpr, limit) + sum(deltaproduct(newexpr, (limit[0], limit[1], ik - 1)) * | |
| delta.subs(limit[0], ik) * | |
| deltaproduct(newexpr, (limit[0], ik + 1, limit[2])) for ik in range(int(limit[1]), int(limit[2] + 1)) | |
| ) | |
| else: | |
| result = deltaproduct(newexpr, limit) + deltasummation( | |
| deltaproduct(newexpr, (limit[0], limit[1], k - 1)) * | |
| delta.subs(limit[0], k) * | |
| deltaproduct(newexpr, (limit[0], k + 1, limit[2])), | |
| (k, limit[1], limit[2]), | |
| no_piecewise=_has_simple_delta(newexpr, limit[0]) | |
| ) | |
| return _remove_multiple_delta(result) | |
| delta, _ = _extract_delta(f, limit[0]) | |
| if not delta: | |
| g = _expand_delta(f, limit[0]) | |
| if f != g: | |
| try: | |
| return factor(deltaproduct(g, limit)) | |
| except AssertionError: | |
| return deltaproduct(g, limit) | |
| return product(f, limit) | |
| return _remove_multiple_delta(f.subs(limit[0], limit[1])*KroneckerDelta(limit[2], limit[1])) + \ | |
| S.One*_simplify_delta(KroneckerDelta(limit[2], limit[1] - 1)) | |
| def deltasummation(f, limit, no_piecewise=False): | |
| """ | |
| Handle summations containing a KroneckerDelta. | |
| Explanation | |
| =========== | |
| The idea for summation is the following: | |
| - If we are dealing with a KroneckerDelta expression, i.e. KroneckerDelta(g(x), j), | |
| we try to simplify it. | |
| If we could simplify it, then we sum the resulting expression. | |
| We already know we can sum a simplified expression, because only | |
| simple KroneckerDelta expressions are involved. | |
| If we could not simplify it, there are two cases: | |
| 1) The expression is a simple expression: we return the summation, | |
| taking care if we are dealing with a Derivative or with a proper | |
| KroneckerDelta. | |
| 2) The expression is not simple (i.e. KroneckerDelta(cos(x))): we can do | |
| nothing at all. | |
| - If the expr is a multiplication expr having a KroneckerDelta term: | |
| First we expand it. | |
| If the expansion did work, then we try to sum the expansion. | |
| If not, we try to extract a simple KroneckerDelta term, then we have two | |
| cases: | |
| 1) We have a simple KroneckerDelta term, so we return the summation. | |
| 2) We did not have a simple term, but we do have an expression with | |
| simplified KroneckerDelta terms, so we sum this expression. | |
| Examples | |
| ======== | |
| >>> from sympy import oo, symbols | |
| >>> from sympy.abc import k | |
| >>> i, j = symbols('i, j', integer=True, finite=True) | |
| >>> from sympy.concrete.delta import deltasummation | |
| >>> from sympy import KroneckerDelta | |
| >>> deltasummation(KroneckerDelta(i, k), (k, -oo, oo)) | |
| 1 | |
| >>> deltasummation(KroneckerDelta(i, k), (k, 0, oo)) | |
| Piecewise((1, i >= 0), (0, True)) | |
| >>> deltasummation(KroneckerDelta(i, k), (k, 1, 3)) | |
| Piecewise((1, (i >= 1) & (i <= 3)), (0, True)) | |
| >>> deltasummation(k*KroneckerDelta(i, j)*KroneckerDelta(j, k), (k, -oo, oo)) | |
| j*KroneckerDelta(i, j) | |
| >>> deltasummation(j*KroneckerDelta(i, j), (j, -oo, oo)) | |
| i | |
| >>> deltasummation(i*KroneckerDelta(i, j), (i, -oo, oo)) | |
| j | |
| See Also | |
| ======== | |
| deltaproduct | |
| sympy.functions.special.tensor_functions.KroneckerDelta | |
| sympy.concrete.sums.summation | |
| """ | |
| if ((limit[2] - limit[1]) < 0) == True: | |
| return S.Zero | |
| if not f.has(KroneckerDelta): | |
| return summation(f, limit) | |
| x = limit[0] | |
| g = _expand_delta(f, x) | |
| if g.is_Add: | |
| return piecewise_fold( | |
| g.func(*[deltasummation(h, limit, no_piecewise) for h in g.args])) | |
| # try to extract a simple KroneckerDelta term | |
| delta, expr = _extract_delta(g, x) | |
| if (delta is not None) and (delta.delta_range is not None): | |
| dinf, dsup = delta.delta_range | |
| if (limit[1] - dinf <= 0) == True and (limit[2] - dsup >= 0) == True: | |
| no_piecewise = True | |
| if not delta: | |
| return summation(f, limit) | |
| solns = solve(delta.args[0] - delta.args[1], x) | |
| if len(solns) == 0: | |
| return S.Zero | |
| elif len(solns) != 1: | |
| return Sum(f, limit) | |
| value = solns[0] | |
| if no_piecewise: | |
| return expr.subs(x, value) | |
| return Piecewise( | |
| (expr.subs(x, value), Interval(*limit[1:3]).as_relational(value)), | |
| (S.Zero, True) | |
| ) | |
Xet Storage Details
- Size:
- 9.87 kB
- Xet hash:
- 13ced9841140b958a4fc77fb2b39a9430b88774e7936f5ec6579999e08e24387
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.