Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /sympy /holonomic /recurrence.py
| """Recurrence Operators""" | |
| from sympy.core.singleton import S | |
| from sympy.core.symbol import (Symbol, symbols) | |
| from sympy.printing import sstr | |
| from sympy.core.sympify import sympify | |
| def RecurrenceOperators(base, generator): | |
| """ | |
| Returns an Algebra of Recurrence Operators and the operator for | |
| shifting i.e. the `Sn` operator. | |
| The first argument needs to be the base polynomial ring for the algebra | |
| and the second argument must be a generator which can be either a | |
| noncommutative Symbol or a string. | |
| Examples | |
| ======== | |
| >>> from sympy import ZZ | |
| >>> from sympy import symbols | |
| >>> from sympy.holonomic.recurrence import RecurrenceOperators | |
| >>> n = symbols('n', integer=True) | |
| >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn') | |
| """ | |
| ring = RecurrenceOperatorAlgebra(base, generator) | |
| return (ring, ring.shift_operator) | |
| class RecurrenceOperatorAlgebra: | |
| """ | |
| A Recurrence Operator Algebra is a set of noncommutative polynomials | |
| in intermediate `Sn` and coefficients in a base ring A. It follows the | |
| commutation rule: | |
| Sn * a(n) = a(n + 1) * Sn | |
| This class represents a Recurrence Operator Algebra and serves as the parent ring | |
| for Recurrence Operators. | |
| Examples | |
| ======== | |
| >>> from sympy import ZZ | |
| >>> from sympy import symbols | |
| >>> from sympy.holonomic.recurrence import RecurrenceOperators | |
| >>> n = symbols('n', integer=True) | |
| >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn') | |
| >>> R | |
| Univariate Recurrence Operator Algebra in intermediate Sn over the base ring | |
| ZZ[n] | |
| See Also | |
| ======== | |
| RecurrenceOperator | |
| """ | |
| def __init__(self, base, generator): | |
| # the base ring for the algebra | |
| self.base = base | |
| # the operator representing shift i.e. `Sn` | |
| self.shift_operator = RecurrenceOperator( | |
| [base.zero, base.one], self) | |
| if generator is None: | |
| self.gen_symbol = symbols('Sn', commutative=False) | |
| else: | |
| if isinstance(generator, str): | |
| self.gen_symbol = symbols(generator, commutative=False) | |
| elif isinstance(generator, Symbol): | |
| self.gen_symbol = generator | |
| def __str__(self): | |
| string = 'Univariate Recurrence Operator Algebra in intermediate '\ | |
| + sstr(self.gen_symbol) + ' over the base ring ' + \ | |
| (self.base).__str__() | |
| return string | |
| __repr__ = __str__ | |
| def __eq__(self, other): | |
| if self.base == other.base and self.gen_symbol == other.gen_symbol: | |
| return True | |
| else: | |
| return False | |
| def _add_lists(list1, list2): | |
| if len(list1) <= len(list2): | |
| sol = [a + b for a, b in zip(list1, list2)] + list2[len(list1):] | |
| else: | |
| sol = [a + b for a, b in zip(list1, list2)] + list1[len(list2):] | |
| return sol | |
| class RecurrenceOperator: | |
| """ | |
| The Recurrence Operators are defined by a list of polynomials | |
| in the base ring and the parent ring of the Operator. | |
| Explanation | |
| =========== | |
| Takes a list of polynomials for each power of Sn and the | |
| parent ring which must be an instance of RecurrenceOperatorAlgebra. | |
| A Recurrence Operator can be created easily using | |
| the operator `Sn`. See examples below. | |
| Examples | |
| ======== | |
| >>> from sympy.holonomic.recurrence import RecurrenceOperator, RecurrenceOperators | |
| >>> from sympy import ZZ | |
| >>> from sympy import symbols | |
| >>> n = symbols('n', integer=True) | |
| >>> R, Sn = RecurrenceOperators(ZZ.old_poly_ring(n),'Sn') | |
| >>> RecurrenceOperator([0, 1, n**2], R) | |
| (1)Sn + (n**2)Sn**2 | |
| >>> Sn*n | |
| (n + 1)Sn | |
| >>> n*Sn*n + 1 - Sn**2*n | |
| (1) + (n**2 + n)Sn + (-n - 2)Sn**2 | |
| See Also | |
| ======== | |
| DifferentialOperatorAlgebra | |
| """ | |
| _op_priority = 20 | |
| def __init__(self, list_of_poly, parent): | |
| # the parent ring for this operator | |
| # must be an RecurrenceOperatorAlgebra object | |
| self.parent = parent | |
| # sequence of polynomials in n for each power of Sn | |
| # represents the operator | |
| # convert the expressions into ring elements using from_sympy | |
| if isinstance(list_of_poly, list): | |
| for i, j in enumerate(list_of_poly): | |
| if isinstance(j, int): | |
| list_of_poly[i] = self.parent.base.from_sympy(S(j)) | |
| elif not isinstance(j, self.parent.base.dtype): | |
| list_of_poly[i] = self.parent.base.from_sympy(j) | |
| self.listofpoly = list_of_poly | |
| self.order = len(self.listofpoly) - 1 | |
| def __mul__(self, other): | |
| """ | |
| Multiplies two Operators and returns another | |
| RecurrenceOperator instance using the commutation rule | |
| Sn * a(n) = a(n + 1) * Sn | |
| """ | |
| listofself = self.listofpoly | |
| base = self.parent.base | |
| if not isinstance(other, RecurrenceOperator): | |
| if not isinstance(other, self.parent.base.dtype): | |
| listofother = [self.parent.base.from_sympy(sympify(other))] | |
| else: | |
| listofother = [other] | |
| else: | |
| listofother = other.listofpoly | |
| # multiply a polynomial `b` with a list of polynomials | |
| def _mul_dmp_diffop(b, listofother): | |
| if isinstance(listofother, list): | |
| return [i * b for i in listofother] | |
| return [b * listofother] | |
| sol = _mul_dmp_diffop(listofself[0], listofother) | |
| # compute Sn^i * b | |
| def _mul_Sni_b(b): | |
| sol = [base.zero] | |
| if isinstance(b, list): | |
| for i in b: | |
| j = base.to_sympy(i).subs(base.gens[0], base.gens[0] + S.One) | |
| sol.append(base.from_sympy(j)) | |
| else: | |
| j = b.subs(base.gens[0], base.gens[0] + S.One) | |
| sol.append(base.from_sympy(j)) | |
| return sol | |
| for i in range(1, len(listofself)): | |
| # find Sn^i * b in ith iteration | |
| listofother = _mul_Sni_b(listofother) | |
| # solution = solution + listofself[i] * (Sn^i * b) | |
| sol = _add_lists(sol, _mul_dmp_diffop(listofself[i], listofother)) | |
| return RecurrenceOperator(sol, self.parent) | |
| def __rmul__(self, other): | |
| if not isinstance(other, RecurrenceOperator): | |
| if isinstance(other, int): | |
| other = S(other) | |
| if not isinstance(other, self.parent.base.dtype): | |
| other = (self.parent.base).from_sympy(other) | |
| sol = [other * j for j in self.listofpoly] | |
| return RecurrenceOperator(sol, self.parent) | |
| def __add__(self, other): | |
| if isinstance(other, RecurrenceOperator): | |
| sol = _add_lists(self.listofpoly, other.listofpoly) | |
| return RecurrenceOperator(sol, self.parent) | |
| else: | |
| if isinstance(other, int): | |
| other = S(other) | |
| list_self = self.listofpoly | |
| if not isinstance(other, self.parent.base.dtype): | |
| list_other = [((self.parent).base).from_sympy(other)] | |
| else: | |
| list_other = [other] | |
| sol = [list_self[0] + list_other[0]] + list_self[1:] | |
| return RecurrenceOperator(sol, self.parent) | |
| __radd__ = __add__ | |
| def __sub__(self, other): | |
| return self + (-1) * other | |
| def __rsub__(self, other): | |
| return (-1) * self + other | |
| def __pow__(self, n): | |
| if n == 1: | |
| return self | |
| result = RecurrenceOperator([self.parent.base.one], self.parent) | |
| if n == 0: | |
| return result | |
| # if self is `Sn` | |
| if self.listofpoly == self.parent.shift_operator.listofpoly: | |
| sol = [self.parent.base.zero] * n + [self.parent.base.one] | |
| return RecurrenceOperator(sol, self.parent) | |
| x = self | |
| while True: | |
| if n % 2: | |
| result *= x | |
| n >>= 1 | |
| if not n: | |
| break | |
| x *= x | |
| return result | |
| def __str__(self): | |
| listofpoly = self.listofpoly | |
| print_str = '' | |
| for i, j in enumerate(listofpoly): | |
| if j == self.parent.base.zero: | |
| continue | |
| j = self.parent.base.to_sympy(j) | |
| if i == 0: | |
| print_str += '(' + sstr(j) + ')' | |
| continue | |
| if print_str: | |
| print_str += ' + ' | |
| if i == 1: | |
| print_str += '(' + sstr(j) + ')Sn' | |
| continue | |
| print_str += '(' + sstr(j) + ')' + 'Sn**' + sstr(i) | |
| return print_str | |
| __repr__ = __str__ | |
| def __eq__(self, other): | |
| if isinstance(other, RecurrenceOperator): | |
| if self.listofpoly == other.listofpoly and self.parent == other.parent: | |
| return True | |
| else: | |
| return False | |
| return self.listofpoly[0] == other and \ | |
| all(i is self.parent.base.zero for i in self.listofpoly[1:]) | |
| class HolonomicSequence: | |
| """ | |
| A Holonomic Sequence is a type of sequence satisfying a linear homogeneous | |
| recurrence relation with Polynomial coefficients. Alternatively, A sequence | |
| is Holonomic if and only if its generating function is a Holonomic Function. | |
| """ | |
| def __init__(self, recurrence, u0=[]): | |
| self.recurrence = recurrence | |
| if not isinstance(u0, list): | |
| self.u0 = [u0] | |
| else: | |
| self.u0 = u0 | |
| if len(self.u0) == 0: | |
| self._have_init_cond = False | |
| else: | |
| self._have_init_cond = True | |
| self.n = recurrence.parent.base.gens[0] | |
| def __repr__(self): | |
| str_sol = 'HolonomicSequence(%s, %s)' % ((self.recurrence).__repr__(), sstr(self.n)) | |
| if not self._have_init_cond: | |
| return str_sol | |
| else: | |
| cond_str = '' | |
| seq_str = 0 | |
| for i in self.u0: | |
| cond_str += ', u(%s) = %s' % (sstr(seq_str), sstr(i)) | |
| seq_str += 1 | |
| sol = str_sol + cond_str | |
| return sol | |
| __str__ = __repr__ | |
| def __eq__(self, other): | |
| if self.recurrence != other.recurrence or self.n != other.n: | |
| return False | |
| if self._have_init_cond and other._have_init_cond: | |
| return self.u0 == other.u0 | |
| return True | |
Xet Storage Details
- Size:
- 10.4 kB
- Xet hash:
- 8a7911bc8c6517d4d211387d7dfb5194771dfa7c9bdf268833574e56a6b0fa11
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.