Ticket #4539: trac4539_pickling.patch
File trac4539_pickling.patch, 11.4 KB (added by SimonKing, 4 years ago) 


sage/algebras/free_algebra.py
# HG changeset patch # User Simon King <simon.king@unijena.de> # Date 1317299148 7200 # Node ID 32b14dc59c37f3fc41a7e347369a18bf23b564be # Parent 0e1053cf125248cb2022db53fec32f59853f3c28 #4539: Pickling for galgebras and their elements diff git a/sage/algebras/free_algebra.py b/sage/algebras/free_algebra.py
a b 472 472 """ 473 473 return self.__monoid 474 474 475 def g_algebra(self, relations, order='degrevlex', check = True):475 def g_algebra(self, relations, names=None, order='degrevlex', check = True): 476 476 """ 477 477 The GAlgebra derived from this algebra by relations. 478 478 By default is assumed, that two variables commute. … … 507 507 x*y + z 508 508 """ 509 509 from sage.matrix.constructor import Matrix 510 from sage.rings.polynomial.plural import NCPolynomialRing_plural511 510 512 511 base_ring=self.base_ring() 513 512 n=self.ngens() … … 538 537 cmat[v2_ind,v1_ind]=c_coef 539 538 if d_poly: 540 539 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) 543 543 544 544 545 545 from 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 135 135 136 136 from sage.structure.parent cimport Parent 137 137 from sage.structure.element cimport CommutativeRingElement 138 from sage.structure.factory import UniqueFactory 138 139 from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn 139 140 from sage.rings.integer_ring import is_IntegerRing, ZZ 140 141 from sage.categories.algebras import Algebras 141 142 from sage.rings.ring import check_default_category 142 143 144 class G_AlgFactory(UniqueFactory): 145 """ 146 A factory for the creation of galgebras 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*yz, z*x:x*z+2*x, z*y:y*z2*y}) 152 sage: H is A.g_algebra({y*x:x*yz, z*x:x*z+2*x, z*y:y*z2*y}) # indirect doctest 153 True 154 155 """ 156 def create_object(self, version, key, **extra_args): 157 """ 158 Create a galgebra to a given unique key. 159 160 INPUT: 161 162  key  a 6tuple, 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*yz, z*x:x*z+2*x, z*y:y*z2*y}) # indirect doctest 171 Noncommutative Multivariate Polynomial Ring in x, y, z over Rational 172 Field, ncrelations: {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 galgebras. 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*yz, z*x:x*z+2*x, z*y:y*z2*y}) 198 sage: H is A.g_algebra({y*x:x*yz, z*x:x*z+2*x, z*y:y*z2*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 226 g_Algebra = G_AlgFactory('sage.rings.polynomial.plural.g_Algebra') 227 143 228 cdef class NCPolynomialRing_plural(Ring): 144 229 """ 145 230 A noncommutative polynomial ring. … … 150 235 sage: H = A.g_algebra({y*x:x*yz, z*x:x*z+2*x, z*y:y*z2*y}) 151 236 sage: H._is_category_initialized() 152 237 True 153 sage: H.catego154 H.categories H.category155 238 sage: H.category() 156 239 Category of algebras over Rational Field 240 sage: TestSuite(H).run() 157 241 158 242 """ 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): 161 244 """ 162 245 Construct a noncommutative polynomial Galgebra subject to the following conditions: 163 246 … … 165 248 166 249  ``base_ring``  base ring (must be either GF(q), ZZ, ZZ/nZZ, 167 250 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 170 252  ``c``, ``d`` upper triangular matrices of coefficients, 171 253 resp. commutative polynomials, satisfying the nondegeneracy 172 254 conditions, which are to be tested if check == True. These … … 175 257 ``self.gen(j)*self.gen(i) == c[i, j] * self.gen(i)*self.gen(j) + d[i, j],`` 176 258 177 259 where ``0 <= i < j < self.ngens()``. 178  ``order``  term order (default: ``degrevlex``)260  ``order``  term order 179 261  ``check``  check the noncommutative conditions (default: ``True``) 180  ``category``  optional category. The resulting ring181 will belong to that category and to the category of182 algebras over the base ring.183 262 184 263 EXAMPLES:: 185 264 … … 193 272 sage: d[0, 1] = 17 194 273 195 274 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') 197 276 198 277 sage: P # indirect doctest 199 278 Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, ncrelations: {y*x: x*y + 17} … … 223 302 Degree reverse lexicographic term order 224 303 225 304 """ 226 305 n = len(names) 227 306 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 240 311 241 312 from sage.libs.singular.function import singular_function 242 313 ncalgebra = singular_function('nc_algebra') … … 250 321 self.__ngens = n 251 322 self.__term_order = order 252 323 253 Ring.__init__(self, base_ring, names, 254 category=check_default_category(Algebras(base_ring),category)) 324 Ring.__init__(self, base_ring, names, category) 255 325 self._populate_coercion_lists_() 256 326 257 327 #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) … … 268 338 if (len(test) != 1) or (test[0] != 0): 269 339 raise ValueError, "NDC check failed!" 270 340 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*yz, z*x:x*z+2*x, z*y:y*z2*y}) 347 sage: H is A.g_algebra({y*x:x*yz, z*x:x*z+2*x, z*y:y*z2*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 271 358 def __dealloc__(self): 272 359 r""" 273 360 Carefully deallocate the ring, without changing "currRing" … … 437 524 _p = p_NSet(_n, _ring) 438 525 439 526 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") ### ?????? 444 530 return new_NCP(self,_p) 445 531 446 532 … … 1224 1310 M.append(new_NCP(self, p_Copy(tempvector,_ring))) 1225 1311 return M 1226 1312 1313 def 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) 1227 1338 1228 1339 1229 1340 cdef class NCPolynomial_plural(RingElement): … … 1253 1364 1254 1365 # def __call__(self, *x, **kwds): # ? 1255 1366 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*yz, z*x:x*z+2*x, z*y:y*z2*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 1256 1379 # you may have to replicate this boilerplate code in derived classes if you override 1257 1380 # __richcmp__. The python documentation at http://docs.python.org/api/typestructs.html 1258 1381 # explains how __richcmp__, __hash__, and __cmp__ are tied together.