Ticket #4539: trac4539_pickling.patch

File trac4539_pickling.patch, 11.4 KB (added by SimonKing, 5 years ago)

Pickling of nc rings and polynomials

  • sage/algebras/free_algebra.py

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1317299148 -7200
    # Node ID 32b14dc59c37f3fc41a7e347369a18bf23b564be
    # Parent  0e1053cf125248cb2022db53fec32f59853f3c28
    #4539: Pickling for g-algebras and their elements
    
    diff --git a/sage/algebras/free_algebra.py b/sage/algebras/free_algebra.py
    a b  
    472472        """
    473473        return self.__monoid
    474474   
    475     def g_algebra(self, relations, order='degrevlex', check = True):
     475    def g_algebra(self, relations, names=None, order='degrevlex', check = True):
    476476        """
    477477        The G-Algebra derived from this algebra by relations.
    478478        By default is assumed, that two variables commute.
     
    507507            -x*y + z
    508508        """
    509509        from sage.matrix.constructor  import Matrix
    510         from sage.rings.polynomial.plural import NCPolynomialRing_plural
    511510       
    512511        base_ring=self.base_ring()
    513512        n=self.ngens()
     
    538537            cmat[v2_ind,v1_ind]=c_coef
    539538            if d_poly:
    540539                dmat[v2_ind,v1_ind]=d_poly
    541        
    542         return NCPolynomialRing_plural(base_ring, n, ",".join([str(g) for g in self.gens()]), c=cmat, d=dmat, order=order, check=check)
     540        from sage.rings.polynomial.plural import g_Algebra
     541        return g_Algebra(base_ring, cmat, dmat, names = names or self.variable_names(),
     542                         order=order, check=check)
    543543           
    544544           
    545545from sage.misc.cache import Cache
  • sage/rings/polynomial/plural.pyx

    diff --git a/sage/rings/polynomial/plural.pyx b/sage/rings/polynomial/plural.pyx
    a b  
    135135
    136136from sage.structure.parent cimport Parent
    137137from sage.structure.element cimport CommutativeRingElement
     138from sage.structure.factory import UniqueFactory
    138139from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
    139140from sage.rings.integer_ring import is_IntegerRing, ZZ
    140141from sage.categories.algebras import Algebras
    141142from sage.rings.ring import check_default_category
    142143
     144class G_AlgFactory(UniqueFactory):
     145    """
     146    A factory for the creation of g-algebras as unique parents.
     147
     148    TESTS::
     149
     150        sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     151        sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     152        sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest
     153        True
     154
     155    """
     156    def create_object(self, version, key, **extra_args):
     157        """
     158        Create a g-algebra to a given unique key.
     159
     160        INPUT:
     161
     162        - key - a 6-tuple, formed by a base ring, a tuple of names, two
     163          matrices over a polynomial ring over the base ring with the given
     164          variable names, a term order, and a category
     165        - extra_args - a dictionary, whose only relevant key is 'check'.
     166
     167        TEST::
     168
     169            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     170            sage: A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest
     171            Noncommutative Multivariate Polynomial Ring in x, y, z over Rational
     172            Field, nc-relations: {y*x: x*y - z, z*y: y*z - 2*y, z*x: x*z + 2*x}
     173
     174        """
     175        # key = (base_ring,names, c,d, order, category)
     176        # extra args: check
     177        base_ring,names,c,d,order,category = key
     178        check = extra_args.get('check')
     179        return NCPolynomialRing_plural(base_ring, names, c,d, order, category, check)
     180    def create_key_and_extra_args(self, base_ring, c,d, names=None, order=None,
     181                                 category=None,check=None):
     182        """
     183        Create a unique key for g-algebras.
     184
     185        INPUT:
     186
     187        - ``base_ring`` - a ring
     188        - ``c,d`` - two matrices
     189        - ``names`` - a tuple or list of names
     190        - ``order`` - (optional) term order
     191        - ``category`` - (optional) category
     192        - ``check`` - optional bool
     193
     194        TEST::
     195
     196            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     197            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     198            sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest
     199
     200        """
     201        if names is None:
     202            raise ValueError, "The generator names must be provided"
     203
     204        # Get the number of names:
     205        names = tuple(names)
     206        n = len(names)
     207        order = TermOrder(order or 'degrevlex', n)
     208
     209        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     210        P = PolynomialRing(base_ring, n, names, order=order)
     211        # The names may have been normalised in P:
     212        names = P.variable_names()
     213        c = c.change_ring(P)
     214        c.set_immutable()
     215        d = d.change_ring(P)
     216        d.set_immutable()
     217
     218        # Get the correct category
     219        category=check_default_category(Algebras(base_ring),category)
     220       
     221        # Extra arg
     222        if check is None:
     223            return (base_ring,names,c,d,order,category),{}
     224        return (base_ring,names,c,d,order,category),{'check':check}
     225
     226g_Algebra = G_AlgFactory('sage.rings.polynomial.plural.g_Algebra')
     227
    143228cdef class NCPolynomialRing_plural(Ring):
    144229    """
    145230    A non-commutative polynomial ring.
     
    150235        sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
    151236        sage: H._is_category_initialized()
    152237        True
    153         sage: H.catego
    154         H.categories  H.category
    155238        sage: H.category()
    156239        Category of algebras over Rational Field
     240        sage: TestSuite(H).run()
    157241
    158242    """
    159     def __init__(self, base_ring, n, names, c, d, order='degrevlex',
    160                  check = True, category=None):
     243    def __init__(self, base_ring, names, c, d, order, category, check = True):
    161244        """
    162245        Construct a noncommutative polynomial G-algebra subject to the following conditions:
    163246
     
    165248
    166249        - ``base_ring`` - base ring (must be either GF(q), ZZ, ZZ/nZZ,
    167250                          QQ or absolute number field)
    168         - ``n`` - number of variables (must be at least 1)
    169         - ``names`` - names of ring variables, may be string of list/tupl
     251        - ``names`` - a tuple of names of ring variables
    170252        - ``c``, ``d``- upper triangular matrices of coefficients,
    171253          resp. commutative polynomials, satisfying the nondegeneracy
    172254          conditions, which are to be tested if check == True. These
     
    175257            ``self.gen(j)*self.gen(i) == c[i, j] * self.gen(i)*self.gen(j) + d[i, j],``
    176258
    177259          where ``0 <= i < j < self.ngens()``.
    178         - ``order`` - term order (default: ``degrevlex``)
     260        - ``order`` - term order
    179261        - ``check`` - check the noncommutative conditions (default: ``True``)
    180         - ``category`` - optional category. The resulting ring
    181           will belong to that category and to the category of
    182           algebras over the base ring.
    183262
    184263        EXAMPLES::
    185264
     
    193272            sage: d[0, 1] = 17
    194273
    195274            sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural
    196             sage: P.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex')
     275            sage: P.<x,y,z> = NCPolynomialRing_plural(QQ, c = c, d = d, order='lex')
    197276
    198277            sage: P # indirect doctest
    199278            Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y + 17}
     
    223302            Degree reverse lexicographic term order
    224303
    225304        """
    226 
     305        n = len(names)
    227306        self._relations = None
    228         n = int(n)
    229         if n < 0:
    230             raise ValueError, "Multivariate Polynomial Rings must " + \
    231                   "have more than 0 variables."
    232 
    233         from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    234 
    235         order = TermOrder(order,n)
    236         P = PolynomialRing(base_ring, n, names, order=order)
    237        
    238         self._c = c.change_ring(P)
    239         self._d = d.change_ring(P)
     307
     308        P = c.base_ring()
     309        self._c = c
     310        self._d = d
    240311
    241312        from sage.libs.singular.function import singular_function
    242313        ncalgebra = singular_function('nc_algebra')
     
    250321        self.__ngens = n
    251322        self.__term_order = order
    252323
    253         Ring.__init__(self, base_ring, names,
    254                       category=check_default_category(Algebras(base_ring),category))
     324        Ring.__init__(self, base_ring, names, category)
    255325        self._populate_coercion_lists_()
    256326       
    257327        #MPolynomialRing_generic.__init__(self, base_ring, n, names, order)
     
    268338            if (len(test) != 1) or (test[0] != 0):
    269339                raise ValueError, "NDC check failed!"
    270340
     341    def __reduce__(self):
     342        """
     343        TESTS::
     344
     345            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     346            sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     347            sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     348            True
     349            sage: H is loads(dumps(H))  # indirect doctest
     350            True
     351
     352        """
     353        return g_Algebra, (self.base_ring(),self._c,self._d,
     354                            self.variable_names(),
     355                            self.term_order().name(),
     356                            self.category())
     357
    271358    def __dealloc__(self):
    272359        r"""
    273360        Carefully deallocate the ring, without changing "currRing"
     
    437524                _p = p_NSet(_n, _ring)
    438525
    439526        else:
    440             raise NotImplementedError("not able to constructor "+repr(element) +
    441                                       " of type "+ repr(type(element))) #### ??????
    442 
    443 
     527            raise NotImplementedError("not able to interprete "+repr(element) +
     528                                      " of type "+ repr(type(element)) +
     529                                      " as noncommutative polynomial")  ### ??????
    444530        return new_NCP(self,_p)
    445531
    446532
     
    12241310          M.append(new_NCP(self, p_Copy(tempvector,_ring)))
    12251311        return M
    12261312
     1313def unpickle_NCPolynomial_plural(NCPolynomialRing_plural R, d):
     1314    cdef ring *r = R._ring
     1315    cdef poly *m, *p
     1316    cdef int _i, _e
     1317    p = p_ISet(0,r)
     1318    rChangeCurrRing(r)
     1319    for mon,c in d.iteritems():
     1320        m = p_Init(r)
     1321        for i,e in mon.sparse_iter():
     1322            _i = i
     1323            if _i >= r.N:
     1324                p_Delete(&p,r)
     1325                p_Delete(&m,r)
     1326                raise TypeError, "variable index too big"
     1327            _e = e
     1328            if _e <= 0:
     1329                p_Delete(&p,r)
     1330                p_Delete(&m,r)
     1331                raise TypeError, "exponent too small"
     1332            overflow_check(_e, r)
     1333            p_SetExp(m, _i+1,_e, r)
     1334        p_SetCoeff(m, sa2si(c, r), r)
     1335        p_Setm(m,r)
     1336        p = p_Add_q(p,m,r)
     1337    return new_NCP(R,p)
    12271338
    12281339
    12291340cdef class NCPolynomial_plural(RingElement):
     
    12531364
    12541365#    def __call__(self, *x, **kwds): # ?
    12551366
     1367    def __reduce__(self):
     1368        """
     1369        TEST::
     1370
     1371            sage: A.<x,y,z> = FreeAlgebra(QQ, 3)
     1372            sage: H.<x,y,z> = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y})
     1373            sage: loads(dumps(x*y+2*z+4*x*y*z*x))
     1374            4*x^2*y*z + 8*x^2*y - 4*x*z^2 + x*y - 8*x*z + 2*z
     1375
     1376        """
     1377        return unpickle_NCPolynomial_plural, (self._parent, self.dict())
     1378
    12561379    # you may have to replicate this boilerplate code in derived classes if you override
    12571380    # __richcmp__.  The python documentation at  http://docs.python.org/api/type-structs.html
    12581381    # explains how __richcmp__, __hash__, and __cmp__ are tied together.