Ticket #4539: trac4539_pickling.patch

File trac4539_pickling.patch, 11.4 KB (added by SimonKing, 3 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.