# Ticket #21100: flatten.py

File flatten.py, 2.7 KB (added by vdelecroix, 3 years ago)
Line
1r"""
2sage: R = QQ['x']['y']['s','t']['X']
3sage: f = FlatteningMorphism(R)
4sage: g = f.section()
5sage: %timeit f(p)
6100 loops, best of 3: 3.69 ms per loop
7sage: %timeit g(f(p))
810 loops, best of 3: 63.3 ms per loop
9"""
10from sage.categories.morphism import Morphism
11
12from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
13from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
14from sage.rings.polynomial.multi_polynomial_ring_generic import is_MPolynomialRing
15
16class FlatteningMorphism(Morphism):
17    r"""
18    EXAMPLES::
19
20        sage: R = QQ['a','b']['x','y','z']['t1','t2']
21        sage: f = FlatteningMorphism(R)
22        sage: f.codomain()
23        Multivariate Polynomial Ring in a, b, x, y, z, t1, t2 over Rational Field
24        sage: p = R('(a+b)*x + (a^2-b)*t2*(z+y)')
25        sage: p
26        ((a^2 - b)*y + (a^2 - b)*z)*t2 + (a + b)*x
27        sage: f(p)
28        a^2*y*t2 + a^2*z*t2 - b*y*t2 - b*z*t2 + a*x + b*x
29
30    Also work when univariate polynomial ring are involved::
31
32        sage: R = QQ['x']['y']['s','t']['X']
33        sage: f = FlatteningMorphism(R)
34        sage: f.codomain()
35        Multivariate Polynomial Ring in x, y, s, t, X over Rational Field
36        sage: p = R('((x^2 + 1) + (x+2)*y + x*y^3)*(s+t) + x*y*X')
37        sage: p
38        x*y*X + (x*y^3 + (x + 2)*y + x^2 + 1)*s + (x*y^3 + (x + 2)*y + x^2 + 1)*t
39        sage: f(p)
40        x*y^3*s + x*y^3*t + x^2*s + x*y*s + x^2*t + x*y*t + x*y*X + 2*y*s + 2*y*t + s + t
41    """
42    def __init__(self, domain, codomain=None):
43        if not is_PolynomialRing(domain) and not is_MPolynomialRing(domain):
44            raise ValueError("domain should be a polynomial ring")
45
46        if codomain is None:
47            ring = domain
48            variables = []
49            while is_PolynomialRing(ring) or is_MPolynomialRing(ring):
50                v = ring.variable_names()
51                if any(vv in variables for vv in v):
52                    raise ValueError("clash in variable names")
53                variables.extend(reversed(v))
54                ring = ring.base_ring()
55            variables.reverse()
56            codomain = PolynomialRing(ring.base_ring(), variables)
57
58        Morphism.__init__(self, domain, codomain)
59
60    def _call_(self, p):
61        # this is slow... but seems to work!
62        return self.codomain()(str(p))
63
64    def section(self):
65        return UnflatteningMorphism(self.codomain(), self.domain())
66
67class UnflatteningMorphism(Morphism):
68    r"""
69    EXAMPLES::
70
71        sage: R = QQ['x']['y']['s','t']['X']
72        sage: p = R.random_element()
73        sage: f = FlatteningMorphism(R)
74        sage: g = f.section()
75        sage: g(f(p)) == p
76        True
77    """
78    def _call_(self, p):
79        # this is slow... but seems to work!
80        return self.codomain()(str(p))