# Ticket #21100: flatten.py

File flatten.py, 2.7 KB (added by , 3 years ago) |
---|

Line | |
---|---|

1 | r""" |

2 | sage: R = QQ['x']['y']['s','t']['X'] |

3 | sage: f = FlatteningMorphism(R) |

4 | sage: g = f.section() |

5 | sage: %timeit f(p) |

6 | 100 loops, best of 3: 3.69 ms per loop |

7 | sage: %timeit g(f(p)) |

8 | 10 loops, best of 3: 63.3 ms per loop |

9 | """ |

10 | from sage.categories.morphism import Morphism |

11 | |

12 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing |

13 | from sage.rings.polynomial.polynomial_ring import is_PolynomialRing |

14 | from sage.rings.polynomial.multi_polynomial_ring_generic import is_MPolynomialRing |

15 | |

16 | class 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 | |

67 | class 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)) |