r"""
Some base rings in which our invariants take values
EXAMPLES::
sage: from msinvar.rings import RF
sage: R=RF('u,v')
sage: R.inject_variables(verbose=False)
sage: (u-v).adams(2)/(u+v)
u - v
"""
# *****************************************************************************
# Copyright (C) 2021 Sergey Mozgovoy <mozhov@gmail.com>
#
# Distributed under the terms of the GNU General Public License (GPL)
# http://www.gnu.org/licenses/
# *****************************************************************************
from sage.symbolic.ring import SymbolicRing, SR
from sage.rings.fraction_field import FractionField_generic
from sage.rings.fraction_field_element import FractionFieldElement
from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
from sage.rings.rational_field import QQ
from sage.categories.quotient_fields import QuotientFields
from msinvar.lambda_rings import LambdaRings
[docs]class RationalFunctionField(FractionField_generic):
"""
Field of rational functions in several variables, meaning fractions P/Q, where P, Q
are polynomials in several variables.
EXAMPLES::
sage: from msinvar.rings import RF
sage: R=RF(); R
Field of Rational Functions in y
sage: y=R.gen()
sage: f=(1-y)**3/(1+y)**2; f
(-y^3 + 3*y^2 - 3*y + 1)/(y^2 + 2*y + 1)
sage: factor(f)
(-1) * (y + 1)^-2 * (y - 1)^3
sage: f.adams(2)
(-y^6 + 3*y^4 - 3*y^2 + 1)/(y^4 + 2*y^2 + 1)
sage: R=RF('x,y'); R
Field of Rational Functions in x, y
sage: R.inject_variables(verbose=False)
sage: f=(1-y**2)**5/(1-y)**5*(x-y)
sage: f.factor()
(-1) * (-x + y) * (y + 1)^5
"""
def __init__(self, vars='y', base=QQ):
vars = vars.split(',')
R = MPolynomialRing_libsingular(base, n=len(vars), names=vars)
# cat=Category.join([QuotientFields(),LambdaRings()])
super().__init__(R, element_class=RationalFunction) # , category=cat)
LambdaRings.add_ring(self)
[docs] def symbolic(self, f):
"""
Symbolic expression of a given rational function f.
"""
d = {v: SR.var(n) for n, v in zip(self.variable_names(), self.gens())}
return f.subs(d)
def _repr_(self):
vars = ', '.join(self.variable_names())
return 'Field of Rational Functions in '+vars
RF = RationalFunctionField
[docs]class RationalFunction(FractionFieldElement):
"""Element class for the parent class :class:`RationalFunctionField`."""
[docs] def root_vars(self, k=2):
"""See :meth:`root_vars`."""
return root_vars(self, k)
[docs] def simp(self):
if self == 0:
return self
return self.parent(self.factor().expand())
[docs]def root_vars(f, k=2):
"""
Substitute every variable x in a fraction f by x^(1/k).
"""
R = f.parent()
if R in QuotientFields:
return R(root_vars(f.numerator(), k)/root_vars(f.denominator(), k))
def root(e): return tuple(i//k for i in e)
dct = {root(e): c for e, c in f.dict().items()}
return R(dct)
[docs]class SR1(SymbolicRing):
def __init__(self, vars):
super().__init__()
self.var(vars)
LambdaRings.add_ring(self)
# Parent.__init__(self, category=LambdaRings()) # wee add category explicitly now
# self.inject_variables() #does not work globally; need to invoke it later
[docs] def ngens(self):
"""Return the number of variables."""
return len(self.symbols)
[docs] def gen(self, i=0): # needed for gens, inject_variables to work
"""Return the i-th variable."""
return list(self.symbols.values())[i]
[docs] def variable_names(self): # needed for inject_variables to work
"""Return the tuple of all names of variables."""
return tuple(self.symbols.keys())
def _repr_(self):
return 'Symbolic ring with lambda-ring structure'