def symmetrisation(self, N=None, tailreduce=False, report=None, use_full_group=False): """ Apply permutations to the generators of self and interreduce INPUT: - ``N`` -- (integer, default ``None``) Apply permutations in `Sym(N)`. If it is not given then it will be replaced by the maximal variable index occurring in the generators of ``self.interreduction().squeezed()``. - ``tailreduce`` -- (bool, default ``False``) If ``True``, perform tail reductions. - ``report`` -- (object, default ``None``) If not ``None``, report on the progress of computations. - ``use_full_group`` (optional) -- If True, apply *all* elements of `Sym(N)` to the generators of self (this is what [AB2008]_ originally suggests). The default is to apply all elementary transpositions to the generators of ``self.squeezed()``, interreduce, and repeat until the result stabilises, which is often much faster than applying all of `Sym(N)`, and we are convinced that both methods yield the same result. OUTPUT: A symmetrically interreduced symmetric ideal with respect to which any `Sym(N)`-translate of a generator of self is symmetrically reducible, where by default ``N`` is the maximal variable index that occurs in the generators of ``self.interreduction().squeezed()``. NOTE: If ``I`` is a symmetric ideal whose generators are monomials, then ``I.symmetrisation()`` is its reduced Groebner basis. It should be noted that without symmetrisation, monomial generators, in general, do not form a Groebner basis. EXAMPLES:: sage: X.<x> = InfinitePolynomialRing(QQ) sage: I = X*(x[1]+x[2], x[1]*x[2]) sage: I.symmetrisation() Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field sage: I.symmetrisation(N=3) Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field sage: I.symmetrisation(N=3, use_full_group=True) Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field """ newOUT = self.interreduction(tailreduce=tailreduce, report=report).squeezed() R = self.ring() OUT = R*() if N is None: N = max([Y.max_index() for Y in newOUT.gens()]+[1]) else: N = Integer(N) if hasattr(R,'_max') and R._max<N: R.gen()[N] if report is not None: print "Symmetrise %d polynomials at level %d"%(len(newOUT.gens()),N) if use_full_group: from sage.combinat.permutation import Permutations NewGens = [] Gens = self.gens() for P in Permutations(N): NewGens.extend([p**P for p in Gens]) return (NewGens * R).interreduction(tailreduce=tailreduce,report=report) from sage.combinat.permutation import Permutation from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy RStrat = SymmetricReductionStrategy(self.ring(),OUT.gens(),tailreduce=tailreduce) while (OUT!=newOUT): OUT = newOUT PermutedGens = list(OUT.gens()) if not (report is None): print "Apply permutations" for i in range(1,N): for j in range(i+1,N+1): P = Permutation(((i,j))) for X in OUT.gens(): p = RStrat.reduce(X**P,report=report) if p._p !=0: PermutedGens.append(p) RStrat.add_generator(p,good_input=True) newOUT = (PermutedGens * R).interreduction(tailreduce=tailreduce,report=report) return OUT
def interreduction(self, tailreduce=True, sorted=False, report=None, RStrat=None): """ Return symmetrically interreduced form of self INPUT: - ``tailreduce`` -- (bool, default ``True``) If True, the interreduction is also performed on the non-leading monomials. - ``sorted`` -- (bool, default ``False``) If True, it is assumed that the generators of self are already increasingly sorted. - ``report`` -- (object, default ``None``) If not None, some information on the progress of computation is printed - ``RStrat`` -- (:class:`~sage.rings.polynomial.symmetric_reduction.SymmetricReductionStrategy`, default ``None``) A reduction strategy to which the polynomials resulting from the interreduction will be added. If ``RStrat`` already contains some polynomials, they will be used in the interreduction. The effect is to compute in a quotient ring. OUTPUT: A Symmetric Ideal J (sorted list of generators) coinciding with self as an ideal, so that any generator is symmetrically reduced w.r.t. the other generators. Note that the leading coefficients of the result are not necessarily 1. EXAMPLES:: sage: X.<x> = InfinitePolynomialRing(QQ) sage: I=X*(x[1]+x[2],x[1]*x[2]) sage: I.interreduction() Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field Here, we show the ``report`` option:: sage: I.interreduction(report=True) Symmetric interreduction [1/2] > [2/2] :> [1/2] > [2/2] T[1]> > Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field ``[m/n]`` indicates that polynomial number ``m`` is considered and the total number of polynomials under consideration is ``n``. '-> 0' is printed if a zero reduction occurred. The rest of the report is as described in :meth:`sage.rings.polynomial.symmetric_reduction.SymmetricReductionStrategy.reduce`. Last, we demonstrate the use of the optional parameter ``RStrat``:: sage: from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy sage: R = SymmetricReductionStrategy(X) sage: R Symmetric Reduction Strategy in Infinite polynomial ring in x over Rational Field sage: I.interreduction(RStrat=R) Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field sage: R Symmetric Reduction Strategy in Infinite polynomial ring in x over Rational Field, modulo x_1^2, x_2 + x_1 sage: R = SymmetricReductionStrategy(X,[x[1]^2]) sage: I.interreduction(RStrat=R) Symmetric Ideal (x_2 + x_1) of Infinite polynomial ring in x over Rational Field """ DONE = [] j = 0 TODO = [] PARENT = self.ring() for P in self.gens(): if P._p!=0: if P.is_unit(): # self generates all of self.ring() if RStrat is not None: RStrat.add_generator(PARENT(1)) return SymmetricIdeal(self.ring(),[self.ring()(1)], coerce=False) TODO.append(P) if not sorted: TODO = list(set(TODO)) TODO.sort() if hasattr(PARENT,'_P'): CommonR = PARENT._P else: VarList = set([]) for P in TODO: if P._p!=0: if P.is_unit(): # self generates all of PARENT if RStrat is not None: RStrat.add_generator(PARENT(1)) return SymmetricIdeal(PARENT,[PARENT(1)], coerce=False) VarList = VarList.union(P._p.parent().variable_names()) VarList = list(VarList) if not VarList: return SymmetricIdeal(PARENT,[0]) VarList.sort(cmp=PARENT.varname_cmp, reverse=True) from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing CommonR = PolynomialRing(self.base_ring(), VarList, order=self.ring()._order) ## Now, the symmetric interreduction starts if not (report is None): print 'Symmetric interreduction' from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy if RStrat is None: RStrat = SymmetricReductionStrategy(self.ring(),tailreduce=tailreduce) GroundState = RStrat.gens() while (1): RStrat.setgens(GroundState) DONE = [] for i in range(len(TODO)): if (not (report is None)): print '[%d/%d] '%(i+1,len(TODO)), sys.stdout.flush() p = RStrat.reduce(TODO[i], report=report) if p._p != 0: if p.is_unit(): # self generates all of self.ring() return SymmetricIdeal(self.ring(),[self.ring()(1)], coerce=False) RStrat.add_generator(p, good_input=True) DONE.append(p) else: if not (report is None): print "-> 0" DONE.sort() if DONE == TODO: break else: if len(TODO)==len(DONE): import copy bla = copy.copy(TODO) bla.sort() if bla==DONE: break TODO = DONE return SymmetricIdeal(self.ring(),DONE, coerce=False)
def reduce(self, I, tailreduce=False): """ Symmetric reduction of self by another Symmetric Ideal or list of Infinite Polynomials, or symmetric reduction of a given Infinite Polynomial by self. INPUT: - ``I`` -- an Infinite Polynomial, or a Symmetric Ideal or a list of Infinite Polynomials. - ``tailreduce`` -- (bool, default ``False``) If ``True``, the non-leading terms will be reduced as well. OUTPUT: Symmetric reduction of ``self`` with respect to ``I``. THEORY: Reduction of an element `p` of an Infinite Polynomial Ring `X` by some other element `q` means the following: 1. Let `M` and `N` be the leading terms of `p` and `q`. 2. Test whether there is a permutation `P` that does not does not diminish the variable indices occurring in `N` and preserves their order, so that there is some term `T\in X` with `T N^P = M`. If there is no such permutation, return `p` 3. Replace `p` by `p-T q^P` and continue with step 1. EXAMPLES:: sage: X.<x,y> = InfinitePolynomialRing(QQ) sage: I = X*(y[1]^2*y[3]+y[1]*x[3]^2) sage: I.reduce([x[1]^2*y[2]]) Symmetric Ideal (x_3^2*y_1 + y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field The preceding is correct, since any permutation that turns ``x[1]^2*y[2]`` into a factor of ``x[3]^2*y[2]`` interchanges the variable indices 1 and 2 -- which is not allowed. However, reduction by ``x[2]^2*y[1]`` works, since one can change variable index 1 into 2 and 2 into 3:: sage: I.reduce([x[2]^2*y[1]]) Symmetric Ideal (y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field The next example shows that tail reduction is not done, unless it is explicitly advised. The input can also be a symmetric ideal:: sage: J = (y[2])*X sage: I.reduce(J) Symmetric Ideal (x_3^2*y_1 + y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field sage: I.reduce(J, tailreduce=True) Symmetric Ideal (x_3^2*y_1) of Infinite polynomial ring in x, y over Rational Field """ if I in self.ring(): # we want to reduce a polynomial by self return self.ring()(I).reduce(self) from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy if hasattr(I,'gens'): I = I.gens() if (not I): return self I = list(I) S = SymmetricReductionStrategy(self.ring(),I, tailreduce) return SymmetricIdeal(self.ring(),[S.reduce(X) for X in self.gens()], coerce=False)
def symmetrisation(self, N=None, tailreduce=False, report=None, use_full_group=False): """ Apply permutations to the generators of self and interreduce INPUT: - ``N`` -- (integer, default ``None``) Apply permutations in `Sym(N)`. If it is not given then it will be replaced by the maximal variable index occurring in the generators of ``self.interreduction().squeezed()``. - ``tailreduce`` -- (bool, default ``False``) If ``True``, perform tail reductions. - ``report`` -- (object, default ``None``) If not ``None``, report on the progress of computations. - ``use_full_group`` (optional) -- If True, apply *all* elements of `Sym(N)` to the generators of self (this is what [AB2008]_ originally suggests). The default is to apply all elementary transpositions to the generators of ``self.squeezed()``, interreduce, and repeat until the result stabilises, which is often much faster than applying all of `Sym(N)`, and we are convinced that both methods yield the same result. OUTPUT: A symmetrically interreduced symmetric ideal with respect to which any `Sym(N)`-translate of a generator of self is symmetrically reducible, where by default ``N`` is the maximal variable index that occurs in the generators of ``self.interreduction().squeezed()``. NOTE: If ``I`` is a symmetric ideal whose generators are monomials, then ``I.symmetrisation()`` is its reduced Groebner basis. It should be noted that without symmetrisation, monomial generators, in general, do not form a Groebner basis. EXAMPLES:: sage: X.<x> = InfinitePolynomialRing(QQ) sage: I = X*(x[1]+x[2], x[1]*x[2]) sage: I.symmetrisation() Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field sage: I.symmetrisation(N=3) Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field sage: I.symmetrisation(N=3, use_full_group=True) Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field """ newOUT = self.interreduction(tailreduce=tailreduce, report=report).squeezed() R = self.ring() OUT = R * () if N is None: N = max([Y.max_index() for Y in newOUT.gens()] + [1]) else: N = Integer(N) if hasattr(R, '_max') and R._max < N: R.gen()[N] if report is not None: print("Symmetrise %d polynomials at level %d" % (len(newOUT.gens()), N)) if use_full_group: from sage.combinat.permutation import Permutations NewGens = [] Gens = self.gens() for P in Permutations(N): NewGens.extend([p**P for p in Gens]) return (NewGens * R).interreduction(tailreduce=tailreduce, report=report) from sage.combinat.permutation import Permutation from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy RStrat = SymmetricReductionStrategy(self.ring(), OUT.gens(), tailreduce=tailreduce) while (OUT != newOUT): OUT = newOUT PermutedGens = list(OUT.gens()) if not (report is None): print("Apply permutations") for i in range(1, N): for j in range(i + 1, N + 1): P = Permutation(((i, j))) for X in OUT.gens(): p = RStrat.reduce(X**P, report=report) if p._p != 0: PermutedGens.append(p) RStrat.add_generator(p, good_input=True) newOUT = (PermutedGens * R).interreduction(tailreduce=tailreduce, report=report) return OUT
def interreduction(self, tailreduce=True, sorted=False, report=None, RStrat=None): """ Return symmetrically interreduced form of self INPUT: - ``tailreduce`` -- (bool, default ``True``) If True, the interreduction is also performed on the non-leading monomials. - ``sorted`` -- (bool, default ``False``) If True, it is assumed that the generators of self are already increasingly sorted. - ``report`` -- (object, default ``None``) If not None, some information on the progress of computation is printed - ``RStrat`` -- (:class:`~sage.rings.polynomial.symmetric_reduction.SymmetricReductionStrategy`, default ``None``) A reduction strategy to which the polynomials resulting from the interreduction will be added. If ``RStrat`` already contains some polynomials, they will be used in the interreduction. The effect is to compute in a quotient ring. OUTPUT: A Symmetric Ideal J (sorted list of generators) coinciding with self as an ideal, so that any generator is symmetrically reduced w.r.t. the other generators. Note that the leading coefficients of the result are not necessarily 1. EXAMPLES:: sage: X.<x> = InfinitePolynomialRing(QQ) sage: I=X*(x[1]+x[2],x[1]*x[2]) sage: I.interreduction() Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field Here, we show the ``report`` option:: sage: I.interreduction(report=True) Symmetric interreduction [1/2] > [2/2] :> [1/2] > [2/2] T[1]> > Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field ``[m/n]`` indicates that polynomial number ``m`` is considered and the total number of polynomials under consideration is ``n``. '-> 0' is printed if a zero reduction occurred. The rest of the report is as described in :meth:`sage.rings.polynomial.symmetric_reduction.SymmetricReductionStrategy.reduce`. Last, we demonstrate the use of the optional parameter ``RStrat``:: sage: from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy sage: R = SymmetricReductionStrategy(X) sage: R Symmetric Reduction Strategy in Infinite polynomial ring in x over Rational Field sage: I.interreduction(RStrat=R) Symmetric Ideal (-x_1^2, x_2 + x_1) of Infinite polynomial ring in x over Rational Field sage: R Symmetric Reduction Strategy in Infinite polynomial ring in x over Rational Field, modulo x_1^2, x_2 + x_1 sage: R = SymmetricReductionStrategy(X,[x[1]^2]) sage: I.interreduction(RStrat=R) Symmetric Ideal (x_2 + x_1) of Infinite polynomial ring in x over Rational Field """ DONE = [] j = 0 TODO = [] PARENT = self.ring() for P in self.gens(): if P._p != 0: if P.is_unit(): # self generates all of self.ring() if RStrat is not None: RStrat.add_generator(PARENT(1)) return SymmetricIdeal(self.ring(), [self.ring()(1)], coerce=False) TODO.append(P) if not sorted: TODO = list(set(TODO)) TODO.sort() if hasattr(PARENT, '_P'): CommonR = PARENT._P else: VarList = set([]) for P in TODO: if P._p != 0: if P.is_unit(): # self generates all of PARENT if RStrat is not None: RStrat.add_generator(PARENT(1)) return SymmetricIdeal(PARENT, [PARENT(1)], coerce=False) VarList = VarList.union(P._p.parent().variable_names()) VarList = list(VarList) if not VarList: return SymmetricIdeal(PARENT, [0]) VarList.sort(key=PARENT.varname_key, reverse=True) from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing CommonR = PolynomialRing(self.base_ring(), VarList, order=self.ring()._order) ## Now, the symmetric interreduction starts if not (report is None): print('Symmetric interreduction') from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy if RStrat is None: RStrat = SymmetricReductionStrategy(self.ring(), tailreduce=tailreduce) GroundState = RStrat.gens() while (1): RStrat.setgens(GroundState) DONE = [] for i in range(len(TODO)): if report is not None: print('[%d/%d] ' % (i + 1, len(TODO)), end="") sys.stdout.flush() p = RStrat.reduce(TODO[i], report=report) if p._p != 0: if p.is_unit(): # self generates all of self.ring() return SymmetricIdeal(self.ring(), [self.ring()(1)], coerce=False) RStrat.add_generator(p, good_input=True) DONE.append(p) else: if not (report is None): print("-> 0") DONE.sort() if DONE == TODO: break else: if len(TODO) == len(DONE): import copy bla = copy.copy(TODO) bla.sort() if bla == DONE: break TODO = DONE return SymmetricIdeal(self.ring(), DONE, coerce=False)
def reduce(self, I, tailreduce=False): """ Symmetric reduction of self by another Symmetric Ideal or list of Infinite Polynomials, or symmetric reduction of a given Infinite Polynomial by self. INPUT: - ``I`` -- an Infinite Polynomial, or a Symmetric Ideal or a list of Infinite Polynomials. - ``tailreduce`` -- (bool, default ``False``) If ``True``, the non-leading terms will be reduced as well. OUTPUT: Symmetric reduction of ``self`` with respect to ``I``. THEORY: Reduction of an element `p` of an Infinite Polynomial Ring `X` by some other element `q` means the following: 1. Let `M` and `N` be the leading terms of `p` and `q`. 2. Test whether there is a permutation `P` that does not does not diminish the variable indices occurring in `N` and preserves their order, so that there is some term `T\in X` with `T N^P = M`. If there is no such permutation, return `p` 3. Replace `p` by `p-T q^P` and continue with step 1. EXAMPLES:: sage: X.<x,y> = InfinitePolynomialRing(QQ) sage: I = X*(y[1]^2*y[3]+y[1]*x[3]^2) sage: I.reduce([x[1]^2*y[2]]) Symmetric Ideal (x_3^2*y_1 + y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field The preceding is correct, since any permutation that turns ``x[1]^2*y[2]`` into a factor of ``x[3]^2*y[2]`` interchanges the variable indices 1 and 2 -- which is not allowed. However, reduction by ``x[2]^2*y[1]`` works, since one can change variable index 1 into 2 and 2 into 3:: sage: I.reduce([x[2]^2*y[1]]) Symmetric Ideal (y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field The next example shows that tail reduction is not done, unless it is explicitly advised. The input can also be a symmetric ideal:: sage: J = (y[2])*X sage: I.reduce(J) Symmetric Ideal (x_3^2*y_1 + y_3*y_1^2) of Infinite polynomial ring in x, y over Rational Field sage: I.reduce(J, tailreduce=True) Symmetric Ideal (x_3^2*y_1) of Infinite polynomial ring in x, y over Rational Field """ if I in self.ring(): # we want to reduce a polynomial by self return self.ring()(I).reduce(self) from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy if hasattr(I, 'gens'): I = I.gens() if (not I): return self I = list(I) S = SymmetricReductionStrategy(self.ring(), I, tailreduce) return SymmetricIdeal(self.ring(), [S.reduce(X) for X in self.gens()], coerce=False)