| | 1 | r""" |
| | 2 | Noncommutative Polynomials via libSINGULAR/Plural |
| | 3 | |
| | 4 | This module implements specialized and optimized implementations for |
| | 5 | noncommutative multivariate polynomials over many coefficient rings, via the |
| | 6 | shared library interface to SINGULAR. In particular, the following coefficient |
| | 7 | rings are supported by this implementation: |
| | 8 | |
| | 9 | - the rational numbers `\QQ`, and |
| | 10 | |
| | 11 | - finite fields `\GF{p}` for `p` prime |
| | 12 | |
| | 13 | AUTHORS: |
| | 14 | |
| | 15 | The PLURAL wrapper is due to |
| | 16 | |
| | 17 | - Burcin Erocal (2008-11 and 2010-07): initial implementation and concept |
| | 18 | |
| | 19 | - Michael Brickenstein (2008-11 and 2010-07): initial implementation and concept |
| | 20 | |
| | 21 | - Oleksandr Motsak (2010-07): complete overall fnoncommutative unctionality and first release |
| | 22 | |
| | 23 | - Alexander Dreyer (2010-07): noncommutative ring functionality and documentation |
| | 24 | |
| | 25 | The underlying libSINGULAR interface was implemented by |
| | 26 | |
| | 27 | - Martin Albrecht (2007-01): initial implementation |
| | 28 | |
| | 29 | - Joel Mohler (2008-01): misc improvements, polishing |
| | 30 | |
| | 31 | - Martin Albrecht (2008-08): added `\QQ(a)` and `\ZZ` support |
| | 32 | |
| | 33 | - Simon King (2009-04): improved coercion |
| | 34 | |
| | 35 | - Martin Albrecht (2009-05): added `\ZZ/n\ZZ` support, refactoring |
| | 36 | |
| | 37 | - Martin Albrecht (2009-06): refactored the code to allow better |
| | 38 | re-use |
| | 39 | |
| | 40 | TODO: |
| | 41 | |
| | 42 | - extend functionality towards those of libSINGULARs commutative part |
| | 43 | |
| | 44 | EXAMPLES: |
| | 45 | |
| | 46 | We show how to construct various noncommutative polynomial rings:: |
| | 47 | |
| | 48 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 49 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 50 | sage: P.inject_variables() |
| | 51 | Defining x, y, z |
| | 52 | |
| | 53 | sage: P |
| | 54 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 55 | |
| | 56 | sage: y*x + 1/2 |
| | 57 | -x*y + 1/2 |
| | 58 | |
| | 59 | sage: A.<x,y,z> = FreeAlgebra(GF(17), 3) |
| | 60 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 61 | sage: P.inject_variables() |
| | 62 | Defining x, y, z |
| | 63 | |
| | 64 | sage: P |
| | 65 | Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 17, nc-relations: {y*x: -x*y} |
| | 66 | |
| | 67 | sage: y*x + 7 |
| | 68 | -x*y + 7 |
| | 69 | |
| | 70 | |
| | 71 | Raw use of this class:: |
| | 72 | sage: from sage.matrix.constructor import Matrix |
| | 73 | sage: c = Matrix(3) |
| | 74 | sage: c[0,1] = -2 |
| | 75 | sage: c[0,2] = 1 |
| | 76 | sage: c[1,2] = 1 |
| | 77 | |
| | 78 | sage: d = Matrix(3) |
| | 79 | sage: d[0, 1] = 17 |
| | 80 | |
| | 81 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 82 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex') |
| | 83 | sage: R |
| | 84 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -2*x*y + 17} |
| | 85 | |
| | 86 | sage: R.term_order() |
| | 87 | Lexicographic term order |
| | 88 | |
| | 89 | sage: a,b,c = R.gens() |
| | 90 | sage: f = 57 * a^2*b + 43 * c + 1; f |
| | 91 | 57*x^2*y + 43*z + 1 |
| | 92 | |
| | 93 | sage: R.term_order() |
| | 94 | Lexicographic term order |
| | 95 | |
| | 96 | TESTS:: |
| | 97 | |
| | 98 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 99 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 100 | sage: P.inject_variables() |
| | 101 | Defining x, y, z |
| | 102 | |
| | 103 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural, NCPolynomial_plural |
| | 104 | sage: TestSuite(NCPolynomialRing_plural).run() |
| | 105 | sage: TestSuite(NCPolynomial_plural).run() |
| | 106 | """ |
| | 107 | include "sage/ext/stdsage.pxi" |
| | 108 | include "sage/ext/interrupt.pxi" |
| | 109 | |
| | 110 | |
| | 111 | from sage.libs.singular.function cimport RingWrap |
| | 112 | from sage.structure.parent_base cimport ParentWithBase |
| | 113 | from sage.structure.parent_gens cimport ParentWithGens |
| | 114 | |
| | 115 | # singular rings |
| | 116 | from sage.libs.singular.ring cimport singular_ring_new, singular_ring_delete |
| | 117 | |
| | 118 | from sage.rings.integer cimport Integer |
| | 119 | from sage.structure.element cimport Element, ModuleElement |
| | 120 | |
| | 121 | from sage.libs.singular.polynomial cimport singular_polynomial_call, singular_polynomial_cmp, singular_polynomial_add, singular_polynomial_sub, singular_polynomial_neg, singular_polynomial_pow, singular_polynomial_mul, singular_polynomial_rmul |
| | 122 | from sage.libs.singular.polynomial cimport singular_polynomial_deg, singular_polynomial_str_with_changed_varnames, singular_polynomial_latex, singular_polynomial_str, singular_polynomial_div_coeff |
| | 123 | |
| | 124 | from sage.rings.polynomial.polydict import ETuple |
| | 125 | |
| | 126 | from sage.libs.singular.singular cimport si2sa, sa2si, overflow_check |
| | 127 | from sage.rings.integer_ring import ZZ |
| | 128 | from term_order import TermOrder |
| | 129 | |
| | 130 | |
| | 131 | from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomialRing_libsingular |
| | 132 | #from sage.rings.polynomial.multi_polynomial_libsingular cimport addwithcarry |
| | 133 | from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic |
| | 134 | |
| | 135 | |
| | 136 | from sage.structure.parent cimport Parent |
| | 137 | from sage.structure.element cimport CommutativeRingElement |
| | 138 | from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn |
| | 139 | from sage.rings.integer_ring import is_IntegerRing, ZZ |
| | 140 | from sage.categories.algebras import Algebras |
| | 141 | from sage.rings.ring import check_default_category |
| | 142 | |
| | 143 | cdef class NCPolynomialRing_plural(Ring): |
| | 144 | """ |
| | 145 | A non-commutative polynomial ring. |
| | 146 | |
| | 147 | EXAMPLES:: |
| | 148 | |
| | 149 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 150 | sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) |
| | 151 | sage: H._is_category_initialized() |
| | 152 | True |
| | 153 | sage: H.catego |
| | 154 | H.categories H.category |
| | 155 | sage: H.category() |
| | 156 | Category of algebras over Rational Field |
| | 157 | |
| | 158 | """ |
| | 159 | def __init__(self, base_ring, n, names, c, d, order='degrevlex', |
| | 160 | check = True, category=None): |
| | 161 | """ |
| | 162 | Construct a noncommutative polynomial G-algebra subject to the following conditions: |
| | 163 | |
| | 164 | INPUT: |
| | 165 | |
| | 166 | - ``base_ring`` - base ring (must be either GF(q), ZZ, ZZ/nZZ, |
| | 167 | 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 |
| | 170 | - ``c``, ``d``- upper triangular matrices of coefficients, |
| | 171 | resp. commutative polynomials, satisfying the nondegeneracy |
| | 172 | conditions, which are to be tested if check == True. These |
| | 173 | matrices describe the noncommutative relations: |
| | 174 | |
| | 175 | ``self.gen(j)*self.gen(i) == c[i, j] * self.gen(i)*self.gen(j) + d[i, j],`` |
| | 176 | |
| | 177 | where ``0 <= i < j < self.ngens()``. |
| | 178 | - ``order`` - term order (default: ``degrevlex``) |
| | 179 | - ``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. |
| | 183 | |
| | 184 | EXAMPLES:: |
| | 185 | |
| | 186 | sage: from sage.matrix.constructor import Matrix |
| | 187 | sage: c = Matrix(3) |
| | 188 | sage: c[0,1] = -1 |
| | 189 | sage: c[0,2] = 1 |
| | 190 | sage: c[1,2] = 1 |
| | 191 | |
| | 192 | sage: d = Matrix(3) |
| | 193 | sage: d[0, 1] = 17 |
| | 194 | |
| | 195 | 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') |
| | 197 | |
| | 198 | sage: P # indirect doctest |
| | 199 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y + 17} |
| | 200 | |
| | 201 | sage: P(x*y) |
| | 202 | x*y |
| | 203 | |
| | 204 | sage: f = 27/113 * x^2 + y*z + 1/2; f |
| | 205 | 27/113*x^2 + y*z + 1/2 |
| | 206 | |
| | 207 | sage: P.term_order() |
| | 208 | Lexicographic term order |
| | 209 | |
| | 210 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 211 | sage: P.<x,y,z> = NCPolynomialRing_plural(GF(7), 3, c = c, d = d, order='degrevlex') |
| | 212 | |
| | 213 | sage: P # indirect doctest |
| | 214 | Noncommutative Multivariate Polynomial Ring in x, y, z over Finite Field of size 7, nc-relations: {y*x: -x*y + 3} |
| | 215 | |
| | 216 | sage: P(x*y) |
| | 217 | x*y |
| | 218 | |
| | 219 | sage: f = 3 * x^2 + y*z + 5; f |
| | 220 | 3*x^2 + y*z - 2 |
| | 221 | |
| | 222 | sage: P.term_order() |
| | 223 | Degree reverse lexicographic term order |
| | 224 | |
| | 225 | """ |
| | 226 | |
| | 227 | 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) |
| | 240 | |
| | 241 | from sage.libs.singular.function import singular_function |
| | 242 | ncalgebra = singular_function('nc_algebra') |
| | 243 | |
| | 244 | cdef RingWrap rw = ncalgebra(self._c, self._d, ring = P) |
| | 245 | |
| | 246 | # rw._output() |
| | 247 | self._ring = rw._ring |
| | 248 | self._ring.ShortOut = 0 |
| | 249 | |
| | 250 | self.__ngens = n |
| | 251 | self.__term_order = order |
| | 252 | |
| | 253 | Ring.__init__(self, base_ring, names, |
| | 254 | category=check_default_category(Algebras(base_ring),category)) |
| | 255 | self._populate_coercion_lists_() |
| | 256 | |
| | 257 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 258 | #self._has_singular = True |
| | 259 | assert(n == len(self._names)) |
| | 260 | |
| | 261 | self._one_element = new_NCP(self, p_ISet(1, self._ring)) |
| | 262 | self._zero_element = new_NCP(self, NULL) |
| | 263 | |
| | 264 | |
| | 265 | if check: |
| | 266 | import sage.libs.singular |
| | 267 | test = sage.libs.singular.ff.nctools__lib.ndcond(ring = self) |
| | 268 | if (len(test) != 1) or (test[0] != 0): |
| | 269 | raise ValueError, "NDC check failed!" |
| | 270 | |
| | 271 | def __dealloc__(self): |
| | 272 | r""" |
| | 273 | Carefully deallocate the ring, without changing "currRing" |
| | 274 | (since this method can be at unpredictable times due to garbage |
| | 275 | collection). |
| | 276 | |
| | 277 | TESTS: |
| | 278 | This example caused a segmentation fault with a previous version |
| | 279 | of this method: |
| | 280 | sage: import gc |
| | 281 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 282 | sage: from sage.algebras.free_algebra import FreeAlgebra |
| | 283 | sage: A1.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 284 | sage: R1 = A1.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 285 | sage: A2.<x,y,z> = FreeAlgebra(GF(5), 3) |
| | 286 | sage: R2 = A2.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 287 | sage: A3.<x,y,z> = FreeAlgebra(GF(11), 3) |
| | 288 | sage: R3 = A3.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 289 | sage: A4.<x,y,z> = FreeAlgebra(GF(13), 3) |
| | 290 | sage: R4 = A4.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}, order=TermOrder('degrevlex', 2)) |
| | 291 | sage: _ = gc.collect() |
| | 292 | sage: foo = R1.gen(0) |
| | 293 | sage: del foo |
| | 294 | sage: del R1 |
| | 295 | sage: _ = gc.collect() |
| | 296 | sage: del R2 |
| | 297 | sage: _ = gc.collect() |
| | 298 | sage: del R3 |
| | 299 | sage: _ = gc.collect() |
| | 300 | """ |
| | 301 | singular_ring_delete(self._ring) |
| | 302 | |
| | 303 | def _element_constructor_(self, element): |
| | 304 | """ |
| | 305 | Make sure element is a valid member of self, and return the constructed element. |
| | 306 | |
| | 307 | EXAMPLES:: |
| | 308 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 309 | |
| | 310 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 311 | |
| | 312 | We can construct elements from the base ring:: |
| | 313 | |
| | 314 | sage: P(1/2) |
| | 315 | 1/2 |
| | 316 | |
| | 317 | |
| | 318 | and all kinds of integers:: |
| | 319 | |
| | 320 | sage: P(17) |
| | 321 | 17 |
| | 322 | |
| | 323 | sage: P(int(19)) |
| | 324 | 19 |
| | 325 | |
| | 326 | sage: P(long(19)) |
| | 327 | 19 |
| | 328 | |
| | 329 | TESTS:: |
| | 330 | |
| | 331 | Check conversion from self:: |
| | 332 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 333 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 334 | sage: P.inject_variables() |
| | 335 | Defining x, y, z |
| | 336 | |
| | 337 | sage: P._element_constructor_(1/2) |
| | 338 | 1/2 |
| | 339 | |
| | 340 | sage: P._element_constructor_(x*y) |
| | 341 | x*y |
| | 342 | |
| | 343 | sage: P._element_constructor_(y*x) |
| | 344 | -x*y |
| | 345 | |
| | 346 | Raw use of this class:: |
| | 347 | sage: from sage.matrix.constructor import Matrix |
| | 348 | sage: c = Matrix(3) |
| | 349 | sage: c[0,1] = -2 |
| | 350 | sage: c[0,2] = 1 |
| | 351 | sage: c[1,2] = 1 |
| | 352 | |
| | 353 | sage: d = Matrix(3) |
| | 354 | sage: d[0, 1] = 17 |
| | 355 | |
| | 356 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 357 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = d, order='lex') |
| | 358 | sage: R._element_constructor_(x*y) |
| | 359 | x*y |
| | 360 | |
| | 361 | sage: P._element_constructor_(17) |
| | 362 | 17 |
| | 363 | |
| | 364 | sage: P._element_constructor_(int(19)) |
| | 365 | 19 |
| | 366 | |
| | 367 | Testing special cases:: |
| | 368 | sage: P._element_constructor_(1) |
| | 369 | 1 |
| | 370 | |
| | 371 | sage: P._element_constructor_(0) |
| | 372 | 0 |
| | 373 | """ |
| | 374 | |
| | 375 | if element == 0: |
| | 376 | return self._zero_element |
| | 377 | if element == 1: |
| | 378 | return self._one_element |
| | 379 | |
| | 380 | cdef poly *_p |
| | 381 | cdef ring *_ring, |
| | 382 | cdef number *_n |
| | 383 | |
| | 384 | _ring = self._ring |
| | 385 | |
| | 386 | base_ring = self.base_ring() |
| | 387 | |
| | 388 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 389 | |
| | 390 | |
| | 391 | if PY_TYPE_CHECK(element, NCPolynomial_plural): |
| | 392 | |
| | 393 | if element.parent() is <object>self: |
| | 394 | return element |
| | 395 | elif element.parent() == self: |
| | 396 | # is this safe? |
| | 397 | _p = p_Copy((<NCPolynomial_plural>element)._poly, _ring) |
| | 398 | |
| | 399 | elif PY_TYPE_CHECK(element, CommutativeRingElement): |
| | 400 | # base ring elements |
| | 401 | if <Parent>element.parent() is base_ring: |
| | 402 | # shortcut for GF(p) |
| | 403 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 404 | _p = p_ISet(int(element) % _ring.ch, _ring) |
| | 405 | else: |
| | 406 | _n = sa2si(element,_ring) |
| | 407 | _p = p_NSet(_n, _ring) |
| | 408 | |
| | 409 | # also accepting ZZ |
| | 410 | elif is_IntegerRing(element.parent()): |
| | 411 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 412 | _p = p_ISet(int(element),_ring) |
| | 413 | else: |
| | 414 | _n = sa2si(base_ring(element),_ring) |
| | 415 | _p = p_NSet(_n, _ring) |
| | 416 | else: |
| | 417 | # fall back to base ring |
| | 418 | element = base_ring._coerce_c(element) |
| | 419 | _n = sa2si(element,_ring) |
| | 420 | _p = p_NSet(_n, _ring) |
| | 421 | |
| | 422 | # Accepting int |
| | 423 | elif PY_TYPE_CHECK(element, int): |
| | 424 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 425 | _p = p_ISet(int(element) % _ring.ch,_ring) |
| | 426 | else: |
| | 427 | _n = sa2si(base_ring(element),_ring) |
| | 428 | _p = p_NSet(_n, _ring) |
| | 429 | |
| | 430 | # and longs |
| | 431 | elif PY_TYPE_CHECK(element, long): |
| | 432 | if isinstance(base_ring, FiniteField_prime_modn): |
| | 433 | element = element % self.base_ring().characteristic() |
| | 434 | _p = p_ISet(int(element),_ring) |
| | 435 | else: |
| | 436 | _n = sa2si(base_ring(element),_ring) |
| | 437 | _p = p_NSet(_n, _ring) |
| | 438 | |
| | 439 | else: |
| | 440 | raise NotImplementedError("not able to constructor "+repr(element) + |
| | 441 | " of type "+ repr(type(element))) #### ?????? |
| | 442 | |
| | 443 | |
| | 444 | return new_NCP(self,_p) |
| | 445 | |
| | 446 | |
| | 447 | |
| | 448 | cpdef _coerce_map_from_(self, S): |
| | 449 | """ |
| | 450 | The only things that coerce into this ring are: |
| | 451 | - the integer ring |
| | 452 | - other localizations away from fewer primes |
| | 453 | |
| | 454 | EXAMPLES:: |
| | 455 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 456 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 457 | |
| | 458 | sage: P._coerce_map_from_(ZZ) |
| | 459 | True |
| | 460 | """ |
| | 461 | |
| | 462 | if self.base_ring().has_coerce_map_from(S): |
| | 463 | return True |
| | 464 | |
| | 465 | |
| | 466 | |
| | 467 | def __hash__(self): |
| | 468 | """ |
| | 469 | Return a hash for this noncommutative ring, that is, a hash of the string |
| | 470 | representation of this polynomial ring. |
| | 471 | |
| | 472 | EXAMPLES:: |
| | 473 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 474 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 475 | sage: hash(P) # somewhat random output |
| | 476 | ... |
| | 477 | |
| | 478 | TESTS:: |
| | 479 | |
| | 480 | Check conversion from self:: |
| | 481 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 482 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 483 | sage: from sage.matrix.constructor import Matrix |
| | 484 | sage: c = Matrix(3) |
| | 485 | sage: c[0,1] = -1 |
| | 486 | sage: c[0,2] = 1 |
| | 487 | sage: c[1,2] = 1 |
| | 488 | |
| | 489 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 490 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 491 | sage: hash(R) == hash(P) |
| | 492 | True |
| | 493 | """ |
| | 494 | return hash(str(self.__repr__()) + str(self.term_order()) ) |
| | 495 | |
| | 496 | |
| | 497 | def __cmp__(self, right): |
| | 498 | r""" |
| | 499 | Non-commutative polynomial rings are said to be equal if: |
| | 500 | |
| | 501 | - their base rings match, |
| | 502 | - their generator names match, |
| | 503 | - their term orderings match, and |
| | 504 | - their relations match. |
| | 505 | |
| | 506 | EXAMPLES:: |
| | 507 | |
| | 508 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 509 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 510 | |
| | 511 | sage: P == P |
| | 512 | True |
| | 513 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 514 | sage: Q == P |
| | 515 | True |
| | 516 | |
| | 517 | sage: from sage.matrix.constructor import Matrix |
| | 518 | sage: c = Matrix(3) |
| | 519 | sage: c[0,1] = -1 |
| | 520 | sage: c[0,2] = 1 |
| | 521 | sage: c[1,2] = 1 |
| | 522 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 523 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 524 | sage: R == P |
| | 525 | True |
| | 526 | |
| | 527 | sage: c[0,1] = -2 |
| | 528 | sage: R.<x,y,z> = NCPolynomialRing_plural(QQ, 3, c = c, d = Matrix(3), order='lex') |
| | 529 | sage: P == R |
| | 530 | False |
| | 531 | """ |
| | 532 | |
| | 533 | if PY_TYPE_CHECK(right, NCPolynomialRing_plural): |
| | 534 | |
| | 535 | return cmp( (self.base_ring(), map(str, self.gens()), |
| | 536 | self.term_order(), self._c, self._d), |
| | 537 | (right.base_ring(), map(str, right.gens()), |
| | 538 | right.term_order(), |
| | 539 | (<NCPolynomialRing_plural>right)._c, |
| | 540 | (<NCPolynomialRing_plural>right)._d) |
| | 541 | ) |
| | 542 | else: |
| | 543 | return cmp(type(self),type(right)) |
| | 544 | |
| | 545 | def __pow__(self, n, _): |
| | 546 | """ |
| | 547 | Return the free module of rank `n` over this ring. |
| | 548 | |
| | 549 | EXAMPLES:: |
| | 550 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 551 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 552 | sage: P.inject_variables() |
| | 553 | Defining x, y, z |
| | 554 | |
| | 555 | sage: f = x^3 + y |
| | 556 | sage: f^2 |
| | 557 | x^6 + y^2 |
| | 558 | """ |
| | 559 | import sage.modules.all |
| | 560 | return sage.modules.all.FreeModule(self, n) |
| | 561 | |
| | 562 | def term_order(self): |
| | 563 | """ |
| | 564 | Return the term ordering of the noncommutative ring. |
| | 565 | |
| | 566 | EXAMPLES:: |
| | 567 | |
| | 568 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 569 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 570 | sage: P.term_order() |
| | 571 | Lexicographic term order |
| | 572 | |
| | 573 | sage: P = A.g_algebra(relations={y*x:-x*y}) |
| | 574 | sage: P.term_order() |
| | 575 | Degree reverse lexicographic term order |
| | 576 | """ |
| | 577 | return self.__term_order |
| | 578 | |
| | 579 | def is_commutative(self): |
| | 580 | """ |
| | 581 | Return False. |
| | 582 | |
| | 583 | EXAMPLES:: |
| | 584 | |
| | 585 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 586 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 587 | sage: P.is_commutative() |
| | 588 | False |
| | 589 | """ |
| | 590 | return False |
| | 591 | |
| | 592 | def is_field(self): |
| | 593 | """ |
| | 594 | Return False. |
| | 595 | |
| | 596 | EXAMPLES:: |
| | 597 | |
| | 598 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 599 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 600 | sage: P.is_field() |
| | 601 | False |
| | 602 | """ |
| | 603 | return False |
| | 604 | |
| | 605 | def _repr_(self): |
| | 606 | """ |
| | 607 | EXAMPLE: |
| | 608 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 609 | sage: from sage.matrix.constructor import Matrix |
| | 610 | sage: c=Matrix(2) |
| | 611 | sage: c[0,1]=-1 |
| | 612 | sage: P.<x,y> = NCPolynomialRing_plural(QQ, 2, c=c, d=Matrix(2)) |
| | 613 | sage: P # indirect doctest |
| | 614 | Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: {y*x: -x*y} |
| | 615 | sage: x*y |
| | 616 | x*y |
| | 617 | sage: y*x |
| | 618 | -x*y |
| | 619 | """ |
| | 620 | #TODO: print the relations |
| | 621 | varstr = ", ".join([ rRingVar(i,self._ring) for i in range(self.__ngens) ]) |
| | 622 | return "Noncommutative Multivariate Polynomial Ring in %s over %s, nc-relations: %s"%(varstr,self.base_ring(), self.relations()) |
| | 623 | |
| | 624 | |
| | 625 | def _ringlist(self): |
| | 626 | """ |
| | 627 | Return an internal list representation of the noncummutative ring. |
| | 628 | |
| | 629 | EXAMPLES:: |
| | 630 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 631 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 632 | sage: P._ringlist() |
| | 633 | [0, ['x', 'y', 'z'], [['lp', (1, 1, 1)], ['C', (0,)]], [0], [ 0 -1 1] |
| | 634 | [ 0 0 1] |
| | 635 | [ 0 0 0], [0 0 0] |
| | 636 | [0 0 0] |
| | 637 | [0 0 0]] |
| | 638 | """ |
| | 639 | cdef ring* _ring = self._ring |
| | 640 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 641 | from sage.libs.singular.function import singular_function |
| | 642 | ringlist = singular_function('ringlist') |
| | 643 | result = ringlist(self, ring=self) |
| | 644 | |
| | 645 | |
| | 646 | |
| | 647 | |
| | 648 | return result |
| | 649 | |
| | 650 | |
| | 651 | def relations(self, add_commutative = False): |
| | 652 | """ |
| | 653 | EXAMPLE:: |
| | 654 | |
| | 655 | sage: from sage.rings.polynomial.plural import NCPolynomialRing_plural |
| | 656 | sage: from sage.matrix.constructor import Matrix |
| | 657 | sage: c=Matrix(2) |
| | 658 | sage: c[0,1]=-1 |
| | 659 | sage: P = NCPolynomialRing_plural(QQ, 2, 'x,y', c=c, d=Matrix(2)) |
| | 660 | sage: P # indirect doctest |
| | 661 | Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: ... |
| | 662 | """ |
| | 663 | if self._relations is not None: |
| | 664 | return self._relations |
| | 665 | |
| | 666 | from sage.algebras.free_algebra import FreeAlgebra |
| | 667 | A = FreeAlgebra( self.base_ring(), self.ngens(), self.gens() ) |
| | 668 | |
| | 669 | res = {} |
| | 670 | n = self.ngens() |
| | 671 | for r in range(0, n-1, 1): |
| | 672 | for c in range(r+1, n, 1): |
| | 673 | if (self.gen(c) * self.gen(r) != self.gen(r) * self.gen(c)) or add_commutative: |
| | 674 | res[ A.gen(c) * A.gen(r) ] = self.gen(c) * self.gen(r) # C[r, c] * P.gen(r) * P.gen(c) + D[r, c] |
| | 675 | |
| | 676 | |
| | 677 | self._relations = res |
| | 678 | return self._relations |
| | 679 | |
| | 680 | def ngens(self): |
| | 681 | """ |
| | 682 | Returns the number of variables in this noncommutative polynomial ring. |
| | 683 | |
| | 684 | EXAMPLES:: |
| | 685 | |
| | 686 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 687 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 688 | sage: P.inject_variables() |
| | 689 | Defining x, y, z |
| | 690 | |
| | 691 | sage: P.ngens() |
| | 692 | 3 |
| | 693 | """ |
| | 694 | return int(self.__ngens) |
| | 695 | |
| | 696 | def gen(self, int n=0): |
| | 697 | """ |
| | 698 | Returns the ``n``-th generator of this noncommutative polynomial |
| | 699 | ring. |
| | 700 | |
| | 701 | INPUT: |
| | 702 | |
| | 703 | - ``n`` -- an integer ``>= 0`` |
| | 704 | |
| | 705 | EXAMPLES:: |
| | 706 | |
| | 707 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 708 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 709 | sage: P.gen(),P.gen(1) |
| | 710 | (x, y) |
| | 711 | |
| | 712 | sage: P.gen(1) |
| | 713 | y |
| | 714 | """ |
| | 715 | cdef poly *_p |
| | 716 | cdef ring *_ring = self._ring |
| | 717 | |
| | 718 | if n < 0 or n >= self.__ngens: |
| | 719 | raise ValueError, "Generator not defined." |
| | 720 | |
| | 721 | rChangeCurrRing(_ring) |
| | 722 | _p = p_ISet(1,_ring) |
| | 723 | p_SetExp(_p, n+1, 1, _ring) |
| | 724 | p_Setm(_p, _ring); |
| | 725 | |
| | 726 | return new_NCP(self,_p) |
| | 727 | |
| | 728 | def ideal(self, *gens, **kwds): |
| | 729 | """ |
| | 730 | Create an ideal in this polynomial ring. |
| | 731 | |
| | 732 | INPUT: |
| | 733 | |
| | 734 | - ``*gens`` - list or tuple of generators (or several input arguments) |
| | 735 | |
| | 736 | - ``coerce`` - bool (default: ``True``); this must be a |
| | 737 | keyword argument. Only set it to ``False`` if you are certain |
| | 738 | that each generator is already in the ring. |
| | 739 | |
| | 740 | EXAMPLES:: |
| | 741 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 742 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 743 | sage: P.inject_variables() |
| | 744 | Defining x, y, z |
| | 745 | |
| | 746 | sage: P.ideal([x + 2*y + 2*z-1, 2*x*y + 2*y*z-y, x^2 + 2*y^2 + 2*z^2-x]) |
| | 747 | Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 - x + 2*y^2 + 2*z^2) of Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 748 | """ |
| | 749 | from sage.rings.polynomial.multi_polynomial_ideal import \ |
| | 750 | NCPolynomialIdeal |
| | 751 | coerce = kwds.get('coerce', True) |
| | 752 | if len(gens) == 1: |
| | 753 | gens = gens[0] |
| | 754 | #if is_SingularElement(gens): |
| | 755 | # gens = list(gens) |
| | 756 | # coerce = True |
| | 757 | #elif is_Macaulay2Element(gens): |
| | 758 | # gens = list(gens) |
| | 759 | # coerce = True |
| | 760 | if not isinstance(gens, (list, tuple)): |
| | 761 | gens = [gens] |
| | 762 | if coerce: |
| | 763 | gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly! |
| | 764 | return NCPolynomialIdeal(self, gens, coerce=False, side=kwds.get('side','left')) |
| | 765 | |
| | 766 | def _list_to_ring(self, L): |
| | 767 | """ |
| | 768 | Convert internal list representation to noncommutative ring. |
| | 769 | |
| | 770 | EXAMPLES:: |
| | 771 | |
| | 772 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 773 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 774 | sage: rlist = P._ringlist(); |
| | 775 | sage: Q = P._list_to_ring(rlist) |
| | 776 | sage: Q # indirect doctest |
| | 777 | <noncommutative RingWrap> |
| | 778 | """ |
| | 779 | |
| | 780 | cdef ring* _ring = self._ring |
| | 781 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 782 | |
| | 783 | from sage.libs.singular.function import singular_function |
| | 784 | ring = singular_function('ring') |
| | 785 | return ring(L, ring=self) |
| | 786 | |
| | 787 | def quotient(self, I): |
| | 788 | """ |
| | 789 | Construct quotient ring of ``self`` and the two-sided Groebner basis of `ideal` |
| | 790 | |
| | 791 | EXAMPLE:: |
| | 792 | |
| | 793 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 794 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 795 | sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd() |
| | 796 | |
| | 797 | sage: Q = H.quotient(I); Q |
| | 798 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 799 | |
| | 800 | TESTS:: |
| | 801 | |
| | 802 | check coercion bug:: |
| | 803 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 804 | sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') |
| | 805 | sage: rlist = P._ringlist(); |
| | 806 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 807 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 808 | sage: I = H.ideal([H.gen(i) ^2 for i in [0, 1]]).twostd() |
| | 809 | sage: Q = H.quotient(I); Q |
| | 810 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 811 | sage: Q.gen(0)^2 |
| | 812 | 0 |
| | 813 | sage: Q.gen(1) * Q.gen(0) |
| | 814 | -x*y |
| | 815 | """ |
| | 816 | L = self._ringlist() |
| | 817 | L[3] = I.twostd() |
| | 818 | W = self._list_to_ring(L) |
| | 819 | return new_NRing(W, self.base_ring()) |
| | 820 | |
| | 821 | |
| | 822 | ### The following methods are handy for implementing Groebner |
| | 823 | ### basis algorithms. They do only superficial type/sanity checks |
| | 824 | ### and should be called carefully. |
| | 825 | |
| | 826 | def monomial_quotient(self, NCPolynomial_plural f, NCPolynomial_plural g, coeff=False): |
| | 827 | r""" |
| | 828 | Return ``f/g``, where both ``f`` and`` ``g`` are treated as |
| | 829 | monomials. |
| | 830 | |
| | 831 | Coefficients are ignored by default. |
| | 832 | |
| | 833 | INPUT: |
| | 834 | |
| | 835 | - ``f`` - monomial |
| | 836 | - ``g`` - monomial |
| | 837 | - ``coeff`` - divide coefficients as well (default: ``False``) |
| | 838 | |
| | 839 | EXAMPLES:: |
| | 840 | |
| | 841 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 842 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 843 | sage: P.inject_variables() |
| | 844 | Defining x, y, z |
| | 845 | |
| | 846 | sage: P.monomial_quotient(3/2*x*y,x,coeff=True) |
| | 847 | 3/2*y |
| | 848 | |
| | 849 | Note, that `\ZZ` behaves different if ``coeff=True``:: |
| | 850 | |
| | 851 | sage: P.monomial_quotient(2*x,3*x) |
| | 852 | 1 |
| | 853 | sage: P.monomial_quotient(2*x,3*x,coeff=True) |
| | 854 | 2/3 |
| | 855 | |
| | 856 | TESTS:: |
| | 857 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 858 | sage: R = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 859 | sage: R.inject_variables() |
| | 860 | Defining x, y, z |
| | 861 | |
| | 862 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 863 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 864 | sage: P.inject_variables() |
| | 865 | Defining x, y, z |
| | 866 | |
| | 867 | sage: P.monomial_quotient(x*y,x) |
| | 868 | y |
| | 869 | |
| | 870 | ## sage: P.monomial_quotient(x*y,R.gen()) |
| | 871 | ## y |
| | 872 | |
| | 873 | sage: P.monomial_quotient(P(0),P(1)) |
| | 874 | 0 |
| | 875 | |
| | 876 | sage: P.monomial_quotient(P(1),P(0)) |
| | 877 | Traceback (most recent call last): |
| | 878 | ... |
| | 879 | ZeroDivisionError |
| | 880 | |
| | 881 | sage: P.monomial_quotient(P(3/2),P(2/3), coeff=True) |
| | 882 | 9/4 |
| | 883 | |
| | 884 | sage: P.monomial_quotient(x,P(1)) |
| | 885 | x |
| | 886 | |
| | 887 | TESTS:: |
| | 888 | |
| | 889 | sage: P.monomial_quotient(x,y) # Note the wrong result |
| | 890 | x*y^... |
| | 891 | |
| | 892 | .. warning:: |
| | 893 | |
| | 894 | Assumes that the head term of f is a multiple of the head |
| | 895 | term of g and return the multiplicant m. If this rule is |
| | 896 | violated, funny things may happen. |
| | 897 | """ |
| | 898 | cdef poly *res |
| | 899 | cdef ring *r = self._ring |
| | 900 | cdef number *n, *denom |
| | 901 | |
| | 902 | if not <ParentWithBase>self is f._parent: |
| | 903 | f = self._coerce_c(f) |
| | 904 | if not <ParentWithBase>self is g._parent: |
| | 905 | g = self._coerce_c(g) |
| | 906 | |
| | 907 | if(r != currRing): rChangeCurrRing(r) |
| | 908 | |
| | 909 | if not f._poly: |
| | 910 | return self._zero_element |
| | 911 | if not g._poly: |
| | 912 | raise ZeroDivisionError |
| | 913 | |
| | 914 | res = pDivide(f._poly,g._poly) |
| | 915 | if coeff: |
| | 916 | if r.ringtype == 0 or r.cf.nDivBy(p_GetCoeff(f._poly, r), p_GetCoeff(g._poly, r)): |
| | 917 | n = r.cf.nDiv( p_GetCoeff(f._poly, r) , p_GetCoeff(g._poly, r)) |
| | 918 | p_SetCoeff0(res, n, r) |
| | 919 | else: |
| | 920 | raise ArithmeticError("Cannot divide these coefficients.") |
| | 921 | else: |
| | 922 | p_SetCoeff0(res, n_Init(1, r), r) |
| | 923 | return new_NCP(self, res) |
| | 924 | |
| | 925 | def monomial_divides(self, NCPolynomial_plural a, NCPolynomial_plural b): |
| | 926 | """ |
| | 927 | Return ``False`` if a does not divide b and ``True`` |
| | 928 | otherwise. |
| | 929 | |
| | 930 | Coefficients are ignored. |
| | 931 | |
| | 932 | INPUT: |
| | 933 | |
| | 934 | - ``a`` -- monomial |
| | 935 | |
| | 936 | - ``b`` -- monomial |
| | 937 | |
| | 938 | EXAMPLES:: |
| | 939 | |
| | 940 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 941 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 942 | sage: P.inject_variables() |
| | 943 | Defining x, y, z |
| | 944 | |
| | 945 | sage: P.monomial_divides(x*y*z, x^3*y^2*z^4) |
| | 946 | True |
| | 947 | sage: P.monomial_divides(x^3*y^2*z^4, x*y*z) |
| | 948 | False |
| | 949 | |
| | 950 | TESTS:: |
| | 951 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 952 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 953 | sage: Q.inject_variables() |
| | 954 | Defining x, y, z |
| | 955 | |
| | 956 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 957 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 958 | sage: P.inject_variables() |
| | 959 | Defining x, y, z |
| | 960 | |
| | 961 | sage: P.monomial_divides(P(1), P(0)) |
| | 962 | True |
| | 963 | sage: P.monomial_divides(P(1), x) |
| | 964 | True |
| | 965 | """ |
| | 966 | cdef poly *_a |
| | 967 | cdef poly *_b |
| | 968 | cdef ring *_r |
| | 969 | if a._parent is not b._parent: |
| | 970 | b = (<NCPolynomialRing_plural>a._parent)._coerce_c(b) |
| | 971 | |
| | 972 | _a = a._poly |
| | 973 | _b = b._poly |
| | 974 | _r = (<NCPolynomialRing_plural>a._parent)._ring |
| | 975 | |
| | 976 | if _a == NULL: |
| | 977 | raise ZeroDivisionError |
| | 978 | if _b == NULL: |
| | 979 | return True |
| | 980 | |
| | 981 | if not p_DivisibleBy(_a, _b, _r): |
| | 982 | return False |
| | 983 | else: |
| | 984 | return True |
| | 985 | |
| | 986 | |
| | 987 | def monomial_lcm(self, NCPolynomial_plural f, NCPolynomial_plural g): |
| | 988 | """ |
| | 989 | LCM for monomials. Coefficients are ignored. |
| | 990 | |
| | 991 | INPUT: |
| | 992 | |
| | 993 | - ``f`` - monomial |
| | 994 | |
| | 995 | - ``g`` - monomial |
| | 996 | |
| | 997 | EXAMPLES:: |
| | 998 | |
| | 999 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1000 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1001 | sage: P.inject_variables() |
| | 1002 | Defining x, y, z |
| | 1003 | |
| | 1004 | sage: P.monomial_lcm(3/2*x*y,x) |
| | 1005 | x*y |
| | 1006 | |
| | 1007 | TESTS:: |
| | 1008 | |
| | 1009 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1010 | sage: R = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1011 | sage: R.inject_variables() |
| | 1012 | Defining x, y, z |
| | 1013 | |
| | 1014 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1015 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1016 | sage: P.inject_variables() |
| | 1017 | Defining x, y, z |
| | 1018 | |
| | 1019 | ## sage: P.monomial_lcm(x*y,R.gen()) |
| | 1020 | ## x*y |
| | 1021 | |
| | 1022 | sage: P.monomial_lcm(P(3/2),P(2/3)) |
| | 1023 | 1 |
| | 1024 | |
| | 1025 | sage: P.monomial_lcm(x,P(1)) |
| | 1026 | x |
| | 1027 | """ |
| | 1028 | cdef poly *m = p_ISet(1,self._ring) |
| | 1029 | |
| | 1030 | if not <ParentWithBase>self is f._parent: |
| | 1031 | f = self._coerce_c(f) |
| | 1032 | if not <ParentWithBase>self is g._parent: |
| | 1033 | g = self._coerce_c(g) |
| | 1034 | |
| | 1035 | if f._poly == NULL: |
| | 1036 | if g._poly == NULL: |
| | 1037 | return self._zero_element |
| | 1038 | else: |
| | 1039 | raise ArithmeticError, "Cannot compute LCM of zero and nonzero element." |
| | 1040 | if g._poly == NULL: |
| | 1041 | raise ArithmeticError, "Cannot compute LCM of zero and nonzero element." |
| | 1042 | |
| | 1043 | if(self._ring != currRing): rChangeCurrRing(self._ring) |
| | 1044 | |
| | 1045 | pLcm(f._poly, g._poly, m) |
| | 1046 | p_Setm(m, self._ring) |
| | 1047 | return new_NCP(self,m) |
| | 1048 | |
| | 1049 | def monomial_reduce(self, NCPolynomial_plural f, G): |
| | 1050 | """ |
| | 1051 | Try to find a ``g`` in ``G`` where ``g.lm()`` divides |
| | 1052 | ``f``. If found ``(flt,g)`` is returned, ``(0,0)`` otherwise, |
| | 1053 | where ``flt`` is ``f/g.lm()``. |
| | 1054 | |
| | 1055 | It is assumed that ``G`` is iterable and contains *only* |
| | 1056 | elements in this polynomial ring. |
| | 1057 | |
| | 1058 | Coefficients are ignored. |
| | 1059 | |
| | 1060 | INPUT: |
| | 1061 | |
| | 1062 | - ``f`` - monomial |
| | 1063 | - ``G`` - list/set of mpolynomials |
| | 1064 | |
| | 1065 | EXAMPLES:: |
| | 1066 | |
| | 1067 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1068 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1069 | sage: P.inject_variables() |
| | 1070 | Defining x, y, z |
| | 1071 | |
| | 1072 | sage: f = x*y^2 |
| | 1073 | sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ] |
| | 1074 | sage: P.monomial_reduce(f,G) |
| | 1075 | (y, 1/4*x*y + 2/7) |
| | 1076 | |
| | 1077 | TESTS:: |
| | 1078 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1079 | sage: Q = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1080 | sage: Q.inject_variables() |
| | 1081 | Defining x, y, z |
| | 1082 | |
| | 1083 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1084 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1085 | sage: P.inject_variables() |
| | 1086 | Defining x, y, z |
| | 1087 | sage: f = x*y^2 |
| | 1088 | sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ] |
| | 1089 | |
| | 1090 | sage: P.monomial_reduce(P(0),G) |
| | 1091 | (0, 0) |
| | 1092 | |
| | 1093 | sage: P.monomial_reduce(f,[P(0)]) |
| | 1094 | (0, 0) |
| | 1095 | """ |
| | 1096 | cdef poly *m = f._poly |
| | 1097 | cdef ring *r = self._ring |
| | 1098 | cdef poly *flt |
| | 1099 | |
| | 1100 | if not m: |
| | 1101 | return f,f |
| | 1102 | |
| | 1103 | for g in G: |
| | 1104 | if PY_TYPE_CHECK(g, NCPolynomial_plural) \ |
| | 1105 | and (<NCPolynomial_plural>g) \ |
| | 1106 | and p_LmDivisibleBy((<NCPolynomial_plural>g)._poly, m, r): |
| | 1107 | flt = pDivide(f._poly, (<NCPolynomial_plural>g)._poly) |
| | 1108 | #p_SetCoeff(flt, n_Div( p_GetCoeff(f._poly, r) , p_GetCoeff((<NCPolynomial_plural>g)._poly, r), r), r) |
| | 1109 | p_SetCoeff(flt, n_Init(1, r), r) |
| | 1110 | return new_NCP(self,flt), g |
| | 1111 | return self._zero_element,self._zero_element |
| | 1112 | |
| | 1113 | def monomial_pairwise_prime(self, NCPolynomial_plural g, NCPolynomial_plural h): |
| | 1114 | """ |
| | 1115 | Return ``True`` if ``h`` and ``g`` are pairwise prime. Both |
| | 1116 | are treated as monomials. |
| | 1117 | |
| | 1118 | Coefficients are ignored. |
| | 1119 | |
| | 1120 | INPUT: |
| | 1121 | |
| | 1122 | - ``h`` - monomial |
| | 1123 | - ``g`` - monomial |
| | 1124 | |
| | 1125 | EXAMPLES:: |
| | 1126 | |
| | 1127 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1128 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1129 | sage: P.inject_variables() |
| | 1130 | Defining x, y, z |
| | 1131 | |
| | 1132 | sage: P.monomial_pairwise_prime(x^2*z^3, y^4) |
| | 1133 | True |
| | 1134 | |
| | 1135 | sage: P.monomial_pairwise_prime(1/2*x^3*y^2, 3/4*y^3) |
| | 1136 | False |
| | 1137 | |
| | 1138 | TESTS:: |
| | 1139 | |
| | 1140 | sage: A.<x1,y1,z1> = FreeAlgebra(QQ, 3) |
| | 1141 | sage: Q = A.g_algebra(relations={y1*x1:-x1*y1}, order='lex') |
| | 1142 | sage: Q.inject_variables() |
| | 1143 | Defining x1, y1, z1 |
| | 1144 | |
| | 1145 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1146 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1147 | sage: P.inject_variables() |
| | 1148 | Defining x, y, z |
| | 1149 | |
| | 1150 | ## sage: P.monomial_pairwise_prime(x^2*z^3, x1^4) |
| | 1151 | ## True |
| | 1152 | |
| | 1153 | ## sage: P.monomial_pairwise_prime((2)*x^3*y^2, Q.zero_element()) |
| | 1154 | ## True |
| | 1155 | |
| | 1156 | sage: P.monomial_pairwise_prime(2*P.one_element(),x) |
| | 1157 | False |
| | 1158 | """ |
| | 1159 | cdef int i |
| | 1160 | cdef ring *r |
| | 1161 | cdef poly *p, *q |
| | 1162 | |
| | 1163 | if h._parent is not g._parent: |
| | 1164 | g = (<NCPolynomialRing_plural>h._parent)._coerce_c(g) |
| | 1165 | |
| | 1166 | r = (<NCPolynomialRing_plural>h._parent)._ring |
| | 1167 | p = g._poly |
| | 1168 | q = h._poly |
| | 1169 | |
| | 1170 | if p == NULL: |
| | 1171 | if q == NULL: |
| | 1172 | return False #GCD(0,0) = 0 |
| | 1173 | else: |
| | 1174 | return True #GCD(x,0) = 1 |
| | 1175 | |
| | 1176 | elif q == NULL: |
| | 1177 | return True # GCD(0,x) = 1 |
| | 1178 | |
| | 1179 | elif p_IsConstant(p,r) or p_IsConstant(q,r): # assuming a base field |
| | 1180 | return False |
| | 1181 | |
| | 1182 | for i from 1 <= i <= r.N: |
| | 1183 | if p_GetExp(p,i,r) and p_GetExp(q,i,r): |
| | 1184 | return False |
| | 1185 | return True |
| | 1186 | |
| | 1187 | def monomial_all_divisors(self, NCPolynomial_plural t): |
| | 1188 | """ |
| | 1189 | Return a list of all monomials that divide ``t``. |
| | 1190 | |
| | 1191 | Coefficients are ignored. |
| | 1192 | |
| | 1193 | INPUT: |
| | 1194 | |
| | 1195 | - ``t`` - a monomial |
| | 1196 | |
| | 1197 | OUTPUT: |
| | 1198 | a list of monomials |
| | 1199 | |
| | 1200 | |
| | 1201 | EXAMPLES:: |
| | 1202 | |
| | 1203 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 1204 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1205 | sage: P.inject_variables() |
| | 1206 | Defining x, y, z |
| | 1207 | |
| | 1208 | sage: P.monomial_all_divisors(x^2*z^3) |
| | 1209 | [x, x^2, z, x*z, x^2*z, z^2, x*z^2, x^2*z^2, z^3, x*z^3, x^2*z^3] |
| | 1210 | |
| | 1211 | ALGORITHM: addwithcarry idea by Toon Segers |
| | 1212 | """ |
| | 1213 | |
| | 1214 | M = list() |
| | 1215 | |
| | 1216 | cdef ring *_ring = self._ring |
| | 1217 | cdef poly *maxvector = t._poly |
| | 1218 | cdef poly *tempvector = p_ISet(1, _ring) |
| | 1219 | |
| | 1220 | pos = 1 |
| | 1221 | |
| | 1222 | while not p_ExpVectorEqual(tempvector, maxvector, _ring): |
| | 1223 | tempvector = addwithcarry(tempvector, maxvector, pos, _ring) |
| | 1224 | M.append(new_NCP(self, p_Copy(tempvector,_ring))) |
| | 1225 | return M |
| | 1226 | |
| | 1227 | |
| | 1228 | |
| | 1229 | cdef class NCPolynomial_plural(RingElement): |
| | 1230 | """ |
| | 1231 | A noncommutative multivariate polynomial implemented using libSINGULAR. |
| | 1232 | """ |
| | 1233 | def __init__(self, NCPolynomialRing_plural parent): |
| | 1234 | """ |
| | 1235 | Construct a zero element in parent. |
| | 1236 | |
| | 1237 | EXAMPLES:: |
| | 1238 | |
| | 1239 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1240 | sage: H = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1241 | sage: from sage.rings.polynomial.plural import NCPolynomial_plural |
| | 1242 | sage: NCPolynomial_plural(H) |
| | 1243 | 0 |
| | 1244 | """ |
| | 1245 | self._poly = NULL |
| | 1246 | self._parent = <ParentWithBase>parent |
| | 1247 | |
| | 1248 | def __dealloc__(self): |
| | 1249 | # TODO: Warn otherwise! |
| | 1250 | # for some mysterious reason, various things may be NULL in some cases |
| | 1251 | if self._parent is not <ParentWithBase>None and (<NCPolynomialRing_plural>self._parent)._ring != NULL and self._poly != NULL: |
| | 1252 | p_Delete(&self._poly, (<NCPolynomialRing_plural>self._parent)._ring) |
| | 1253 | |
| | 1254 | # def __call__(self, *x, **kwds): # ? |
| | 1255 | |
| | 1256 | # you may have to replicate this boilerplate code in derived classes if you override |
| | 1257 | # __richcmp__. The python documentation at http://docs.python.org/api/type-structs.html |
| | 1258 | # explains how __richcmp__, __hash__, and __cmp__ are tied together. |
| | 1259 | def __hash__(self): |
| | 1260 | """ |
| | 1261 | This hash incorporates the variable name in an effort to |
| | 1262 | respect the obvious inclusions into multi-variable polynomial |
| | 1263 | rings. |
| | 1264 | |
| | 1265 | The tuple algorithm is borrowed from http://effbot.org/zone/python-hash.htm. |
| | 1266 | |
| | 1267 | EXAMPLES:: |
| | 1268 | |
| | 1269 | sage: R.<x>=QQ[] |
| | 1270 | sage: S.<x,y>=QQ[] |
| | 1271 | sage: hash(S(1/2))==hash(1/2) # respect inclusions of the rationals |
| | 1272 | True |
| | 1273 | sage: hash(S.0)==hash(R.0) # respect inclusions into mpoly rings |
| | 1274 | True |
| | 1275 | sage: # the point is to make for more flexible dictionary look ups |
| | 1276 | sage: d={S.0:12} |
| | 1277 | sage: d[R.0] |
| | 1278 | 12 |
| | 1279 | """ |
| | 1280 | return self._hash_c() |
| | 1281 | |
| | 1282 | def __richcmp__(left, right, int op): |
| | 1283 | """ |
| | 1284 | Compare left and right and return -1, 0, and 1 for <,==, and > |
| | 1285 | respectively. |
| | 1286 | |
| | 1287 | EXAMPLES:: |
| | 1288 | |
| | 1289 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1290 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1291 | sage: P.inject_variables() |
| | 1292 | Defining x, z, y |
| | 1293 | |
| | 1294 | sage: x == x |
| | 1295 | True |
| | 1296 | |
| | 1297 | sage: x > y |
| | 1298 | True |
| | 1299 | sage: y^2 > x |
| | 1300 | False |
| | 1301 | |
| | 1302 | ## sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10) |
| | 1303 | # True |
| | 1304 | |
| | 1305 | TESTS:: |
| | 1306 | |
| | 1307 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1308 | sage: P = A.g_algebra(relations={y*x:-x*y}, order='lex') |
| | 1309 | sage: P.inject_variables() |
| | 1310 | Defining x, z, y |
| | 1311 | |
| | 1312 | sage: x > P(0) |
| | 1313 | True |
| | 1314 | |
| | 1315 | sage: P(0) == P(0) |
| | 1316 | True |
| | 1317 | |
| | 1318 | sage: P(0) < P(1) |
| | 1319 | True |
| | 1320 | |
| | 1321 | sage: x > P(1) |
| | 1322 | True |
| | 1323 | |
| | 1324 | sage: 1/2*x < 3/4*x |
| | 1325 | True |
| | 1326 | |
| | 1327 | sage: (x+1) > x |
| | 1328 | True |
| | 1329 | |
| | 1330 | # sage: f = 3/4*x^2*y + 1/2*x + 2/7 |
| | 1331 | # sage: f > f |
| | 1332 | # False |
| | 1333 | # sage: f < f |
| | 1334 | # False |
| | 1335 | # sage: f == f |
| | 1336 | # True |
| | 1337 | |
| | 1338 | # sage: P.<x,y,z> = PolynomialRing(GF(127), order='degrevlex') |
| | 1339 | # sage: (66*x^2 + 23) > (66*x^2 + 2) |
| | 1340 | # True |
| | 1341 | """ |
| | 1342 | return (<Element>left)._richcmp(right, op) |
| | 1343 | |
| | 1344 | cdef int _cmp_c_impl(left, Element right) except -2: |
| | 1345 | if left is right: |
| | 1346 | return 0 |
| | 1347 | cdef poly *p = (<NCPolynomial_plural>left)._poly |
| | 1348 | cdef poly *q = (<NCPolynomial_plural>right)._poly |
| | 1349 | cdef ring *r = (<NCPolynomialRing_plural>left._parent)._ring |
| | 1350 | return singular_polynomial_cmp(p, q, r) |
| | 1351 | |
| | 1352 | cpdef ModuleElement _add_( left, ModuleElement right): |
| | 1353 | """ |
| | 1354 | Adds left and right. |
| | 1355 | |
| | 1356 | EXAMPLES:: |
| | 1357 | |
| | 1358 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1359 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1360 | sage: P.inject_variables() |
| | 1361 | Defining x, z, y |
| | 1362 | sage: 3/2*x + 1/2*y + 1 # indirect doctest |
| | 1363 | 3/2*x + 1/2*y + 1 |
| | 1364 | """ |
| | 1365 | cdef poly *_p |
| | 1366 | singular_polynomial_add(&_p, left._poly, |
| | 1367 | (<NCPolynomial_plural>right)._poly, |
| | 1368 | (<NCPolynomialRing_plural>left._parent)._ring) |
| | 1369 | return new_NCP((<NCPolynomialRing_plural>left._parent), _p) |
| | 1370 | |
| | 1371 | cpdef ModuleElement _sub_( left, ModuleElement right): |
| | 1372 | """ |
| | 1373 | Subtract left and right. |
| | 1374 | |
| | 1375 | EXAMPLES:: |
| | 1376 | |
| | 1377 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1378 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1379 | sage: P.inject_variables() |
| | 1380 | Defining x, z, y |
| | 1381 | sage: 3/2*x - 1/2*y - 1 # indirect doctest |
| | 1382 | 3/2*x - 1/2*y - 1 |
| | 1383 | |
| | 1384 | """ |
| | 1385 | cdef ring *_ring = (<NCPolynomialRing_plural>left._parent)._ring |
| | 1386 | |
| | 1387 | cdef poly *_p |
| | 1388 | singular_polynomial_sub(&_p, left._poly, |
| | 1389 | (<NCPolynomial_plural>right)._poly, |
| | 1390 | _ring) |
| | 1391 | return new_NCP((<NCPolynomialRing_plural>left._parent), _p) |
| | 1392 | |
| | 1393 | cpdef ModuleElement _rmul_(self, RingElement left): |
| | 1394 | """ |
| | 1395 | Multiply self with a base ring element. |
| | 1396 | |
| | 1397 | EXAMPLES:: |
| | 1398 | |
| | 1399 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1400 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1401 | sage: P.inject_variables() |
| | 1402 | Defining x, z, y |
| | 1403 | sage: 3/2*x # indirect doctest |
| | 1404 | 3/2*x |
| | 1405 | """ |
| | 1406 | |
| | 1407 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1408 | if not left: |
| | 1409 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 1410 | cdef poly *_p |
| | 1411 | singular_polynomial_rmul(&_p, self._poly, left, _ring) |
| | 1412 | return new_NCP((<NCPolynomialRing_plural>self._parent),_p) |
| | 1413 | |
| | 1414 | cpdef ModuleElement _lmul_(self, RingElement right): |
| | 1415 | """ |
| | 1416 | Multiply self with a base ring element. |
| | 1417 | |
| | 1418 | EXAMPLES:: |
| | 1419 | |
| | 1420 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1421 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1422 | sage: P.inject_variables() |
| | 1423 | Defining x, z, y |
| | 1424 | sage: x* (2/3) # indirect doctest |
| | 1425 | 2/3*x |
| | 1426 | """ |
| | 1427 | return self._rmul_(right) |
| | 1428 | |
| | 1429 | cpdef RingElement _mul_(left, RingElement right): |
| | 1430 | """ |
| | 1431 | Multiply left and right. |
| | 1432 | |
| | 1433 | EXAMPLES:: |
| | 1434 | |
| | 1435 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1436 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1437 | sage: P.inject_variables() |
| | 1438 | Defining x, z, y |
| | 1439 | sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1) # indirect doctest |
| | 1440 | 9/4*x^2 + 3/2*x*y - 3/4*z - 1/4*y^2 - y - 1 |
| | 1441 | |
| | 1442 | TEST:: |
| | 1443 | |
| | 1444 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1445 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1446 | sage: P.inject_variables() |
| | 1447 | Defining x, z, y |
| | 1448 | sage: (x^2^30) * x^2^30 |
| | 1449 | Traceback (most recent call last): |
| | 1450 | ... |
| | 1451 | OverflowError: Exponent overflow (...). |
| | 1452 | """ |
| | 1453 | # all currently implemented rings are commutative |
| | 1454 | cdef poly *_p |
| | 1455 | singular_polynomial_mul(&_p, left._poly, |
| | 1456 | (<NCPolynomial_plural>right)._poly, |
| | 1457 | (<NCPolynomialRing_plural>left._parent)._ring) |
| | 1458 | return new_NCP((<NCPolynomialRing_plural>left._parent),_p) |
| | 1459 | |
| | 1460 | cpdef RingElement _div_(left, RingElement right): |
| | 1461 | """ |
| | 1462 | Divide left by right |
| | 1463 | |
| | 1464 | EXAMPLES:: |
| | 1465 | |
| | 1466 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1467 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1468 | sage: R.inject_variables() |
| | 1469 | Defining x, z, y |
| | 1470 | sage: f = (x + y)/3 # indirect doctest |
| | 1471 | sage: f.parent() |
| | 1472 | Noncommutative Multivariate Polynomial Ring in x, z, y over Rational Field, nc-relations: {y*x: -x*y + z} |
| | 1473 | |
| | 1474 | TESTS:: |
| | 1475 | |
| | 1476 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1477 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1478 | sage: R.inject_variables() |
| | 1479 | Defining x, z, y |
| | 1480 | sage: x/0 |
| | 1481 | Traceback (most recent call last): |
| | 1482 | ... |
| | 1483 | ZeroDivisionError: rational division by zero |
| | 1484 | """ |
| | 1485 | cdef poly *p |
| | 1486 | cdef bint is_field = left._parent._base.is_field() |
| | 1487 | if p_IsConstant((<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring): |
| | 1488 | if is_field: |
| | 1489 | singular_polynomial_div_coeff(&p, left._poly, (<NCPolynomial_plural>right)._poly, (<NCPolynomialRing_plural>right._parent)._ring) |
| | 1490 | return new_NCP(left._parent, p) |
| | 1491 | else: |
| | 1492 | return left.change_ring(left.base_ring().fraction_field())/right |
| | 1493 | else: |
| | 1494 | return (<NCPolynomialRing_plural>left._parent).fraction_field()(left,right) |
| | 1495 | |
| | 1496 | def __pow__(NCPolynomial_plural self, exp, ignored): |
| | 1497 | """ |
| | 1498 | Return ``self**(exp)``. |
| | 1499 | |
| | 1500 | The exponent must be an integer. |
| | 1501 | |
| | 1502 | EXAMPLES:: |
| | 1503 | |
| | 1504 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1505 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1506 | sage: R.inject_variables() |
| | 1507 | Defining x, z, y |
| | 1508 | sage: f = x^3 + y |
| | 1509 | sage: f^2 |
| | 1510 | x^6 + x^2*z + y^2 |
| | 1511 | |
| | 1512 | TESTS:: |
| | 1513 | |
| | 1514 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1515 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1516 | sage: P.inject_variables() |
| | 1517 | Defining x, z, y |
| | 1518 | sage: (x+y^2^30)^10 |
| | 1519 | Traceback (most recent call last): |
| | 1520 | .... |
| | 1521 | OverflowError: Exponent overflow (...). |
| | 1522 | """ |
| | 1523 | if not PY_TYPE_CHECK_EXACT(exp, Integer) or \ |
| | 1524 | PY_TYPE_CHECK_EXACT(exp, int): |
| | 1525 | try: |
| | 1526 | exp = Integer(exp) |
| | 1527 | except TypeError: |
| | 1528 | raise TypeError, "non-integral exponents not supported" |
| | 1529 | |
| | 1530 | if exp < 0: |
| | 1531 | return 1/(self**(-exp)) |
| | 1532 | elif exp == 0: |
| | 1533 | return (<NCPolynomialRing_plural>self._parent)._one_element |
| | 1534 | |
| | 1535 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1536 | cdef poly *_p |
| | 1537 | singular_polynomial_pow(&_p, self._poly, exp, _ring) |
| | 1538 | return new_NCP((<NCPolynomialRing_plural>self._parent),_p) |
| | 1539 | |
| | 1540 | def __neg__(self): |
| | 1541 | """ |
| | 1542 | Return ``-self``. |
| | 1543 | |
| | 1544 | EXAMPLES:: |
| | 1545 | |
| | 1546 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1547 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1548 | sage: R.inject_variables() |
| | 1549 | Defining x, z, y |
| | 1550 | sage: f = x^3 + y |
| | 1551 | sage: -f |
| | 1552 | -x^3 - y |
| | 1553 | """ |
| | 1554 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1555 | |
| | 1556 | cdef poly *p |
| | 1557 | singular_polynomial_neg(&p, self._poly, _ring) |
| | 1558 | return new_NCP((<NCPolynomialRing_plural>self._parent), p) |
| | 1559 | |
| | 1560 | def _repr_(self): |
| | 1561 | """ |
| | 1562 | EXAMPLES:: |
| | 1563 | |
| | 1564 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1565 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1566 | sage: R.inject_variables() |
| | 1567 | Defining x, z, y |
| | 1568 | sage: f = x^3 + y*x*z + z |
| | 1569 | sage: f # indirect doctest |
| | 1570 | x^3 - x*z*y + z^2 + z |
| | 1571 | """ |
| | 1572 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1573 | s = singular_polynomial_str(self._poly, _ring) |
| | 1574 | return s |
| | 1575 | |
| | 1576 | cpdef _repr_short_(self): |
| | 1577 | """ |
| | 1578 | This is a faster but less pretty way to print polynomials. If |
| | 1579 | available it uses the short SINGULAR notation. |
| | 1580 | |
| | 1581 | EXAMPLES:: |
| | 1582 | |
| | 1583 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1584 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1585 | sage: R.inject_variables() |
| | 1586 | Defining x, z, y |
| | 1587 | sage: f = x^3 + y |
| | 1588 | sage: f._repr_short_() |
| | 1589 | 'x3+y' |
| | 1590 | """ |
| | 1591 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1592 | rChangeCurrRing(_ring) |
| | 1593 | if _ring.CanShortOut: |
| | 1594 | _ring.ShortOut = 1 |
| | 1595 | s = p_String(self._poly, _ring, _ring) |
| | 1596 | _ring.ShortOut = 0 |
| | 1597 | else: |
| | 1598 | s = p_String(self._poly, _ring, _ring) |
| | 1599 | return s |
| | 1600 | |
| | 1601 | def _latex_(self): |
| | 1602 | """ |
| | 1603 | Return a polynomial LaTeX representation of this polynomial. |
| | 1604 | |
| | 1605 | EXAMPLES:: |
| | 1606 | |
| | 1607 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1608 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1609 | sage: R.inject_variables() |
| | 1610 | Defining x, z, y |
| | 1611 | sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 |
| | 1612 | sage: latex(f) # indirect doctest |
| | 1613 | - x^{2} y - z^{2} - \frac{25}{27} y^{3} |
| | 1614 | """ |
| | 1615 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1616 | gens = self.parent().latex_variable_names() |
| | 1617 | base = self.parent().base() |
| | 1618 | return singular_polynomial_latex(self._poly, _ring, base, gens) |
| | 1619 | |
| | 1620 | def _repr_with_changed_varnames(self, varnames): |
| | 1621 | """ |
| | 1622 | Return string representing this polynomial but change the |
| | 1623 | variable names to ``varnames``. |
| | 1624 | |
| | 1625 | EXAMPLES:: |
| | 1626 | |
| | 1627 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1628 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1629 | sage: R.inject_variables() |
| | 1630 | Defining x, z, y |
| | 1631 | sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 |
| | 1632 | sage: print f._repr_with_changed_varnames(['FOO', 'BAR', 'FOOBAR']) |
| | 1633 | -FOO^2*FOOBAR - BAR^2 - 25/27*FOOBAR^3 |
| | 1634 | """ |
| | 1635 | return singular_polynomial_str_with_changed_varnames(self._poly, (<NCPolynomialRing_plural>self._parent)._ring, varnames) |
| | 1636 | |
| | 1637 | def degree(self, NCPolynomial_plural x=None): |
| | 1638 | """ |
| | 1639 | Return the maximal degree of this polynomial in ``x``, where |
| | 1640 | ``x`` must be one of the generators for the parent of this |
| | 1641 | polynomial. |
| | 1642 | |
| | 1643 | INPUT: |
| | 1644 | |
| | 1645 | - ``x`` - multivariate polynomial (a generator of the parent of |
| | 1646 | self) If x is not specified (or is ``None``), return the total |
| | 1647 | degree, which is the maximum degree of any monomial. |
| | 1648 | |
| | 1649 | OUTPUT: |
| | 1650 | integer |
| | 1651 | |
| | 1652 | EXAMPLES:: |
| | 1653 | |
| | 1654 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1655 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1656 | sage: R.inject_variables() |
| | 1657 | Defining x, z, y |
| | 1658 | sage: f = y^2 - x^9 - x |
| | 1659 | sage: f.degree(x) |
| | 1660 | 9 |
| | 1661 | sage: f.degree(y) |
| | 1662 | 2 |
| | 1663 | sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(x) |
| | 1664 | 3 |
| | 1665 | sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(y) |
| | 1666 | 10 |
| | 1667 | |
| | 1668 | TESTS:: |
| | 1669 | |
| | 1670 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1671 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1672 | sage: P.inject_variables() |
| | 1673 | Defining x, z, y |
| | 1674 | sage: P(0).degree(x) |
| | 1675 | -1 |
| | 1676 | sage: P(1).degree(x) |
| | 1677 | 0 |
| | 1678 | |
| | 1679 | """ |
| | 1680 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1681 | cdef poly *p = self._poly |
| | 1682 | if not x: |
| | 1683 | return singular_polynomial_deg(p,NULL,r) |
| | 1684 | |
| | 1685 | # TODO: we can do this faster |
| | 1686 | if not x in self._parent.gens(): |
| | 1687 | raise TypeError("x must be one of the generators of the parent.") |
| | 1688 | |
| | 1689 | return singular_polynomial_deg(p, (<NCPolynomial_plural>x)._poly, r) |
| | 1690 | |
| | 1691 | def total_degree(self): |
| | 1692 | """ |
| | 1693 | Return the total degree of ``self``, which is the maximum degree |
| | 1694 | of all monomials in ``self``. |
| | 1695 | |
| | 1696 | EXAMPLES:: |
| | 1697 | |
| | 1698 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1699 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1700 | sage: R.inject_variables() |
| | 1701 | Defining x, z, y |
| | 1702 | sage: f=2*x*y^3*z^2 |
| | 1703 | sage: f.total_degree() |
| | 1704 | 6 |
| | 1705 | sage: f=4*x^2*y^2*z^3 |
| | 1706 | sage: f.total_degree() |
| | 1707 | 7 |
| | 1708 | sage: f=99*x^6*y^3*z^9 |
| | 1709 | sage: f.total_degree() |
| | 1710 | 18 |
| | 1711 | sage: f=x*y^3*z^6+3*x^2 |
| | 1712 | sage: f.total_degree() |
| | 1713 | 10 |
| | 1714 | sage: f=z^3+8*x^4*y^5*z |
| | 1715 | sage: f.total_degree() |
| | 1716 | 10 |
| | 1717 | sage: f=z^9+10*x^4+y^8*x^2 |
| | 1718 | sage: f.total_degree() |
| | 1719 | 10 |
| | 1720 | |
| | 1721 | TESTS:: |
| | 1722 | |
| | 1723 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1724 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1725 | sage: R.inject_variables() |
| | 1726 | Defining x, z, y |
| | 1727 | sage: R(0).total_degree() |
| | 1728 | -1 |
| | 1729 | sage: R(1).total_degree() |
| | 1730 | 0 |
| | 1731 | """ |
| | 1732 | cdef poly *p = self._poly |
| | 1733 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1734 | return singular_polynomial_deg(p,NULL,r) |
| | 1735 | |
| | 1736 | def degrees(self): |
| | 1737 | """ |
| | 1738 | Returns a tuple with the maximal degree of each variable in |
| | 1739 | this polynomial. The list of degrees is ordered by the order |
| | 1740 | of the generators. |
| | 1741 | |
| | 1742 | EXAMPLES:: |
| | 1743 | |
| | 1744 | sage: A.<y0,y1,y2> = FreeAlgebra(QQ, 3) |
| | 1745 | sage: R = A.g_algebra(relations={y1*y0:-y0*y1 + y2}, order='lex') |
| | 1746 | sage: R.inject_variables() |
| | 1747 | Defining y0, y1, y2 |
| | 1748 | sage: q = 3*y0*y1*y1*y2; q |
| | 1749 | 3*y0*y1^2*y2 |
| | 1750 | sage: q.degrees() |
| | 1751 | (1, 2, 1) |
| | 1752 | sage: (q + y0^5).degrees() |
| | 1753 | (5, 2, 1) |
| | 1754 | """ |
| | 1755 | cdef poly *p = self._poly |
| | 1756 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1757 | cdef int i |
| | 1758 | cdef list d = [0 for _ in range(r.N)] |
| | 1759 | while p: |
| | 1760 | for i from 0 <= i < r.N: |
| | 1761 | d[i] = max(d[i],p_GetExp(p, i+1, r)) |
| | 1762 | p = pNext(p) |
| | 1763 | return tuple(d) |
| | 1764 | |
| | 1765 | |
| | 1766 | def coefficient(self, degrees): |
| | 1767 | """ |
| | 1768 | Return the coefficient of the variables with the degrees |
| | 1769 | specified in the python dictionary ``degrees``. |
| | 1770 | Mathematically, this is the coefficient in the base ring |
| | 1771 | adjoined by the variables of this ring not listed in |
| | 1772 | ``degrees``. However, the result has the same parent as this |
| | 1773 | polynomial. |
| | 1774 | |
| | 1775 | This function contrasts with the function |
| | 1776 | ``monomial_coefficient`` which returns the coefficient in the |
| | 1777 | base ring of a monomial. |
| | 1778 | |
| | 1779 | INPUT: |
| | 1780 | |
| | 1781 | - ``degrees`` - Can be any of: |
| | 1782 | - a dictionary of degree restrictions |
| | 1783 | - a list of degree restrictions (with None in the unrestricted variables) |
| | 1784 | - a monomial (very fast, but not as flexible) |
| | 1785 | |
| | 1786 | OUTPUT: |
| | 1787 | element of the parent of this element. |
| | 1788 | |
| | 1789 | .. note:: |
| | 1790 | |
| | 1791 | For coefficients of specific monomials, look at :meth:`monomial_coefficient`. |
| | 1792 | |
| | 1793 | EXAMPLES:: |
| | 1794 | |
| | 1795 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 1796 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1797 | sage: R.inject_variables() |
| | 1798 | Defining x, z, y |
| | 1799 | sage: f=x*y+y+5 |
| | 1800 | sage: f.coefficient({x:0,y:1}) |
| | 1801 | 1 |
| | 1802 | sage: f.coefficient({x:0}) |
| | 1803 | y + 5 |
| | 1804 | sage: f=(1+y+y^2)*(1+x+x^2) |
| | 1805 | sage: f.coefficient({x:0}) |
| | 1806 | z + y^2 + y + 1 |
| | 1807 | |
| | 1808 | sage: f.coefficient(x) |
| | 1809 | y^2 - y + 1 |
| | 1810 | |
| | 1811 | # f.coefficient([0,None]) # y^2 + y + 1 |
| | 1812 | |
| | 1813 | Be aware that this may not be what you think! The physical |
| | 1814 | appearance of the variable x is deceiving -- particularly if |
| | 1815 | the exponent would be a variable. :: |
| | 1816 | |
| | 1817 | sage: f.coefficient(x^0) # outputs the full polynomial |
| | 1818 | x^2*y^2 + x^2*y + x^2 + x*y^2 - x*y + x + z + y^2 + y + 1 |
| | 1819 | |
| | 1820 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1821 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1822 | sage: R.inject_variables() |
| | 1823 | Defining x, z, y |
| | 1824 | sage: f=x*y+5 |
| | 1825 | sage: c=f.coefficient({x:0,y:0}); c |
| | 1826 | 5 |
| | 1827 | sage: parent(c) |
| | 1828 | Noncommutative Multivariate Polynomial Ring in x, z, y over Finite Field of size 389, nc-relations: {y*x: -x*y + z} |
| | 1829 | |
| | 1830 | AUTHOR: |
| | 1831 | |
| | 1832 | - Joel B. Mohler (2007.10.31) |
| | 1833 | """ |
| | 1834 | cdef poly *_degrees = <poly*>0 |
| | 1835 | cdef poly *p = self._poly |
| | 1836 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1837 | cdef poly *newp = p_ISet(0,r) |
| | 1838 | cdef poly *newptemp |
| | 1839 | cdef int i |
| | 1840 | cdef int flag |
| | 1841 | cdef int gens = self._parent.ngens() |
| | 1842 | cdef int *exps = <int*>sage_malloc(sizeof(int)*gens) |
| | 1843 | for i from 0<=i<gens: |
| | 1844 | exps[i] = -1 |
| | 1845 | |
| | 1846 | if PY_TYPE_CHECK(degrees, NCPolynomial_plural) and self._parent is (<NCPolynomial_plural>degrees)._parent: |
| | 1847 | _degrees = (<NCPolynomial_plural>degrees)._poly |
| | 1848 | if pLength(_degrees) != 1: |
| | 1849 | raise TypeError, "degrees must be a monomial" |
| | 1850 | for i from 0<=i<gens: |
| | 1851 | if p_GetExp(_degrees,i+1,r)!=0: |
| | 1852 | exps[i] = p_GetExp(_degrees,i+1,r) |
| | 1853 | elif type(degrees) is list: |
| | 1854 | for i from 0<=i<gens: |
| | 1855 | if degrees[i] is None: |
| | 1856 | exps[i] = -1 |
| | 1857 | else: |
| | 1858 | exps[i] = int(degrees[i]) |
| | 1859 | elif type(degrees) is dict: |
| | 1860 | # Extract the ordered list of degree specifications from the dictionary |
| | 1861 | poly_vars = self.parent().gens() |
| | 1862 | for i from 0<=i<gens: |
| | 1863 | try: |
| | 1864 | exps[i] = degrees[poly_vars[i]] |
| | 1865 | except KeyError: |
| | 1866 | pass |
| | 1867 | else: |
| | 1868 | raise TypeError, "The input degrees must be a dictionary of variables to exponents." |
| | 1869 | |
| | 1870 | # Extract the monomials that match the specifications |
| | 1871 | while(p): |
| | 1872 | flag = 0 |
| | 1873 | for i from 0<=i<gens: |
| | 1874 | if exps[i] != -1 and p_GetExp(p,i+1,r)!=exps[i]: |
| | 1875 | #print i, p_GetExp(p,i+1,r), exps[i] |
| | 1876 | flag = 1 |
| | 1877 | if flag == 0: |
| | 1878 | newptemp = p_LmInit(p,r) |
| | 1879 | p_SetCoeff(newptemp,n_Copy(p_GetCoeff(p,r),r),r) |
| | 1880 | for i from 0<=i<gens: |
| | 1881 | if exps[i] != -1: |
| | 1882 | p_SetExp(newptemp,i+1,0,r) |
| | 1883 | p_Setm(newptemp,r) |
| | 1884 | newp = p_Add_q(newp,newptemp,r) |
| | 1885 | p = pNext(p) |
| | 1886 | |
| | 1887 | sage_free(exps) |
| | 1888 | |
| | 1889 | return new_NCP(self.parent(),newp) |
| | 1890 | |
| | 1891 | def monomial_coefficient(self, NCPolynomial_plural mon): |
| | 1892 | """ |
| | 1893 | Return the coefficient in the base ring of the monomial mon in |
| | 1894 | ``self``, where mon must have the same parent as self. |
| | 1895 | |
| | 1896 | This function contrasts with the function ``coefficient`` |
| | 1897 | which returns the coefficient of a monomial viewing this |
| | 1898 | polynomial in a polynomial ring over a base ring having fewer |
| | 1899 | variables. |
| | 1900 | |
| | 1901 | INPUT: |
| | 1902 | |
| | 1903 | - ``mon`` - a monomial |
| | 1904 | |
| | 1905 | OUTPUT: |
| | 1906 | coefficient in base ring |
| | 1907 | |
| | 1908 | SEE ALSO: |
| | 1909 | For coefficients in a base ring of fewer variables, look at ``coefficient``. |
| | 1910 | |
| | 1911 | EXAMPLES:: |
| | 1912 | |
| | 1913 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1914 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1915 | sage: P.inject_variables() |
| | 1916 | Defining x, z, y |
| | 1917 | |
| | 1918 | The parent of the return is a member of the base ring. |
| | 1919 | sage: f = 2 * x * y |
| | 1920 | sage: c = f.monomial_coefficient(x*y); c |
| | 1921 | 2 |
| | 1922 | sage: c.parent() |
| | 1923 | Finite Field of size 389 |
| | 1924 | |
| | 1925 | sage: f = y^2 + y^2*x - x^9 - 7*x + 5*x*y |
| | 1926 | sage: f.monomial_coefficient(y^2) |
| | 1927 | 1 |
| | 1928 | sage: f.monomial_coefficient(x*y) |
| | 1929 | 5 |
| | 1930 | sage: f.monomial_coefficient(x^9) |
| | 1931 | 388 |
| | 1932 | sage: f.monomial_coefficient(x^10) |
| | 1933 | 0 |
| | 1934 | """ |
| | 1935 | cdef poly *p = self._poly |
| | 1936 | cdef poly *m = mon._poly |
| | 1937 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1938 | |
| | 1939 | if not mon._parent is self._parent: |
| | 1940 | raise TypeError("mon must have same parent as self.") |
| | 1941 | |
| | 1942 | while(p): |
| | 1943 | if p_ExpVectorEqual(p, m, r) == 1: |
| | 1944 | return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base) |
| | 1945 | p = pNext(p) |
| | 1946 | |
| | 1947 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 1948 | |
| | 1949 | def dict(self): |
| | 1950 | """ |
| | 1951 | Return a dictionary representing self. This dictionary is in |
| | 1952 | the same format as the generic MPolynomial: The dictionary |
| | 1953 | consists of ``ETuple:coefficient`` pairs. |
| | 1954 | |
| | 1955 | EXAMPLES:: |
| | 1956 | |
| | 1957 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 1958 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 1959 | sage: R.inject_variables() |
| | 1960 | Defining x, z, y |
| | 1961 | |
| | 1962 | sage: f = (2*x*y^3*z^2 + (7)*x^2 + (3)) |
| | 1963 | sage: f.dict() |
| | 1964 | {(0, 0, 0): 3, (2, 0, 0): 7, (1, 2, 3): 2} |
| | 1965 | """ |
| | 1966 | cdef poly *p |
| | 1967 | cdef ring *r |
| | 1968 | cdef int n |
| | 1969 | cdef int v |
| | 1970 | r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1971 | if r!=currRing: rChangeCurrRing(r) |
| | 1972 | base = (<NCPolynomialRing_plural>self._parent)._base |
| | 1973 | p = self._poly |
| | 1974 | pd = dict() |
| | 1975 | while p: |
| | 1976 | d = dict() |
| | 1977 | for v from 1 <= v <= r.N: |
| | 1978 | n = p_GetExp(p,v,r) |
| | 1979 | if n!=0: |
| | 1980 | d[v-1] = n |
| | 1981 | |
| | 1982 | pd[ETuple(d,r.N)] = si2sa(p_GetCoeff(p, r), r, base) |
| | 1983 | |
| | 1984 | p = pNext(p) |
| | 1985 | return pd |
| | 1986 | |
| | 1987 | |
| | 1988 | cdef long _hash_c(self): |
| | 1989 | """ |
| | 1990 | See ``self.__hash__`` |
| | 1991 | """ |
| | 1992 | cdef poly *p |
| | 1993 | cdef ring *r |
| | 1994 | cdef int n |
| | 1995 | cdef int v |
| | 1996 | r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 1997 | if r!=currRing: rChangeCurrRing(r) |
| | 1998 | base = (<NCPolynomialRing_plural>self._parent)._base |
| | 1999 | p = self._poly |
| | 2000 | cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap |
| | 2001 | cdef long result_mon |
| | 2002 | var_name_hash = [hash(vn) for vn in self._parent.variable_names()] |
| | 2003 | cdef long c_hash |
| | 2004 | while p: |
| | 2005 | c_hash = hash(si2sa(p_GetCoeff(p, r), r, base)) |
| | 2006 | if c_hash != 0: # this is always going to be true, because we are sparse (correct?) |
| | 2007 | # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm. |
| | 2008 | # I omit gen,exp pairs where the exponent is zero. |
| | 2009 | result_mon = c_hash |
| | 2010 | for v from 1 <= v <= r.N: |
| | 2011 | n = p_GetExp(p,v,r) |
| | 2012 | if n!=0: |
| | 2013 | result_mon = (1000003 * result_mon) ^ var_name_hash[v-1] |
| | 2014 | result_mon = (1000003 * result_mon) ^ n |
| | 2015 | result += result_mon |
| | 2016 | |
| | 2017 | p = pNext(p) |
| | 2018 | if result == -1: |
| | 2019 | return -2 |
| | 2020 | return result |
| | 2021 | |
| | 2022 | def __getitem__(self,x): |
| | 2023 | """ |
| | 2024 | Same as ``self.monomial_coefficent`` but for exponent vectors. |
| | 2025 | |
| | 2026 | INPUT: |
| | 2027 | |
| | 2028 | - ``x`` - a tuple or, in case of a single-variable MPolynomial |
| | 2029 | ring x can also be an integer. |
| | 2030 | |
| | 2031 | EXAMPLES:: |
| | 2032 | |
| | 2033 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2034 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2035 | sage: R.inject_variables() |
| | 2036 | Defining x, z, y |
| | 2037 | sage: f = (-10*x^3*y + 17*x*y)* ( 15*z^3 + 2*x*y*z - 1); f |
| | 2038 | 20*x^4*z*y^2 - 150*x^3*z^3*y - 20*x^3*z^2*y + 10*x^3*y - 34*x^2*z*y^2 - 134*x*z^3*y + 34*x*z^2*y - 17*x*y |
| | 2039 | sage: f[4,1,2] |
| | 2040 | 20 |
| | 2041 | sage: f[1,0,1] |
| | 2042 | 372 |
| | 2043 | sage: f[0,0,0] |
| | 2044 | 0 |
| | 2045 | |
| | 2046 | sage: R.<x> = PolynomialRing(GF(7),1); R |
| | 2047 | Multivariate Polynomial Ring in x over Finite Field of size 7 |
| | 2048 | sage: f = 5*x^2 + 3; f |
| | 2049 | -2*x^2 + 3 |
| | 2050 | sage: f[2] |
| | 2051 | 5 |
| | 2052 | """ |
| | 2053 | cdef poly *m |
| | 2054 | cdef poly *p = self._poly |
| | 2055 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2056 | cdef int i |
| | 2057 | |
| | 2058 | if PY_TYPE_CHECK(x, NCPolynomial_plural): |
| | 2059 | return self.monomial_coefficient(x) |
| | 2060 | if not PY_TYPE_CHECK(x, tuple): |
| | 2061 | try: |
| | 2062 | x = tuple(x) |
| | 2063 | except TypeError: |
| | 2064 | x = (x,) |
| | 2065 | |
| | 2066 | if len(x) != (<NCPolynomialRing_plural>self._parent).__ngens: |
| | 2067 | raise TypeError, "x must have length self.ngens()" |
| | 2068 | |
| | 2069 | m = p_ISet(1,r) |
| | 2070 | i = 1 |
| | 2071 | for e in x: |
| | 2072 | overflow_check(e, r) |
| | 2073 | p_SetExp(m, i, int(e), r) |
| | 2074 | i += 1 |
| | 2075 | p_Setm(m, r) |
| | 2076 | |
| | 2077 | while(p): |
| | 2078 | if p_ExpVectorEqual(p, m, r) == 1: |
| | 2079 | p_Delete(&m,r) |
| | 2080 | return si2sa(p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base) |
| | 2081 | p = pNext(p) |
| | 2082 | |
| | 2083 | p_Delete(&m,r) |
| | 2084 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2085 | |
| | 2086 | def exponents(self, as_ETuples=True): |
| | 2087 | """ |
| | 2088 | Return the exponents of the monomials appearing in this polynomial. |
| | 2089 | |
| | 2090 | INPUT: |
| | 2091 | |
| | 2092 | - ``as_ETuples`` - (default: ``True``) if true returns the result as an list of ETuples |
| | 2093 | otherwise returns a list of tuples |
| | 2094 | |
| | 2095 | |
| | 2096 | EXAMPLES:: |
| | 2097 | |
| | 2098 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2099 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2100 | sage: R.inject_variables() |
| | 2101 | Defining x, z, y |
| | 2102 | sage: f = x^3 + y + 2*z^2 |
| | 2103 | sage: f.exponents() |
| | 2104 | [(3, 0, 0), (0, 2, 0), (0, 0, 1)] |
| | 2105 | sage: f.exponents(as_ETuples=False) |
| | 2106 | [(3, 0, 0), (0, 2, 0), (0, 0, 1)] |
| | 2107 | """ |
| | 2108 | cdef poly *p |
| | 2109 | cdef ring *r |
| | 2110 | cdef int v |
| | 2111 | cdef list pl, ml |
| | 2112 | |
| | 2113 | r = (< NCPolynomialRing_plural>self._parent)._ring |
| | 2114 | p = self._poly |
| | 2115 | |
| | 2116 | pl = list() |
| | 2117 | ml = range(r.N) |
| | 2118 | while p: |
| | 2119 | for v from 1 <= v <= r.N: |
| | 2120 | ml[v-1] = p_GetExp(p,v,r) |
| | 2121 | |
| | 2122 | if as_ETuples: |
| | 2123 | pl.append(ETuple(ml)) |
| | 2124 | else: |
| | 2125 | pl.append(tuple(ml)) |
| | 2126 | |
| | 2127 | p = pNext(p) |
| | 2128 | return pl |
| | 2129 | |
| | 2130 | def is_homogeneous(self): |
| | 2131 | """ |
| | 2132 | Return ``True`` if this polynomial is homogeneous. |
| | 2133 | |
| | 2134 | EXAMPLES:: |
| | 2135 | |
| | 2136 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2137 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2138 | sage: P.inject_variables() |
| | 2139 | Defining x, z, y |
| | 2140 | sage: (x+y+z).is_homogeneous() |
| | 2141 | True |
| | 2142 | sage: (x.parent()(0)).is_homogeneous() |
| | 2143 | True |
| | 2144 | sage: (x+y^2+z^3).is_homogeneous() |
| | 2145 | False |
| | 2146 | sage: (x^2 + y^2).is_homogeneous() |
| | 2147 | True |
| | 2148 | sage: (x^2 + y^2*x).is_homogeneous() |
| | 2149 | False |
| | 2150 | sage: (x^2*y + y^2*x).is_homogeneous() |
| | 2151 | True |
| | 2152 | """ |
| | 2153 | cdef ring *_ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2154 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2155 | return bool(pIsHomogeneous(self._poly)) |
| | 2156 | |
| | 2157 | |
| | 2158 | def is_monomial(self): |
| | 2159 | """ |
| | 2160 | Return ``True`` if this polynomial is a monomial. A monomial |
| | 2161 | is defined to be a product of generators with coefficient 1. |
| | 2162 | |
| | 2163 | EXAMPLES:: |
| | 2164 | |
| | 2165 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2166 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2167 | sage: P.inject_variables() |
| | 2168 | Defining x, z, y |
| | 2169 | sage: x.is_monomial() |
| | 2170 | True |
| | 2171 | sage: (2*x).is_monomial() |
| | 2172 | False |
| | 2173 | sage: (x*y).is_monomial() |
| | 2174 | True |
| | 2175 | sage: (x*y + x).is_monomial() |
| | 2176 | False |
| | 2177 | """ |
| | 2178 | cdef poly *_p |
| | 2179 | cdef ring *_ring |
| | 2180 | cdef number *_n |
| | 2181 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2182 | |
| | 2183 | if self._poly == NULL: |
| | 2184 | return True |
| | 2185 | |
| | 2186 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2187 | |
| | 2188 | _p = p_Head(self._poly, _ring) |
| | 2189 | _n = p_GetCoeff(_p, _ring) |
| | 2190 | |
| | 2191 | ret = bool((not self._poly.next) and n_IsOne(_n, _ring)) |
| | 2192 | |
| | 2193 | p_Delete(&_p, _ring) |
| | 2194 | return ret |
| | 2195 | |
| | 2196 | def monomials(self): |
| | 2197 | """ |
| | 2198 | Return the list of monomials in self. The returned list is |
| | 2199 | decreasingly ordered by the term ordering of |
| | 2200 | ``self.parent()``. |
| | 2201 | |
| | 2202 | EXAMPLES:: |
| | 2203 | |
| | 2204 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2205 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2206 | sage: P.inject_variables() |
| | 2207 | Defining x, z, y |
| | 2208 | sage: f = x + (3*2)*y*z^2 + (2+3) |
| | 2209 | sage: f.monomials() |
| | 2210 | [x, z^2*y, 1] |
| | 2211 | sage: f = P(3^2) |
| | 2212 | sage: f.monomials() |
| | 2213 | [1] |
| | 2214 | |
| | 2215 | TESTS:: |
| | 2216 | |
| | 2217 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2218 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2219 | sage: P.inject_variables() |
| | 2220 | Defining x, z, y |
| | 2221 | sage: f = x |
| | 2222 | sage: f.monomials() |
| | 2223 | [x] |
| | 2224 | sage: f = P(0) |
| | 2225 | sage: f.monomials() |
| | 2226 | [0] |
| | 2227 | |
| | 2228 | Check if #7152 is fixed:: |
| | 2229 | |
| | 2230 | sage: x=var('x') |
| | 2231 | sage: K.<rho> = NumberField(x**2 + 1) |
| | 2232 | sage: R.<x,y> = QQ[] |
| | 2233 | sage: p = rho*x |
| | 2234 | sage: q = x |
| | 2235 | sage: p.monomials() |
| | 2236 | [x] |
| | 2237 | sage: q.monomials() |
| | 2238 | [x] |
| | 2239 | sage: p.monomials() |
| | 2240 | [x] |
| | 2241 | """ |
| | 2242 | l = list() |
| | 2243 | cdef NCPolynomialRing_plural parent = <NCPolynomialRing_plural>self._parent |
| | 2244 | cdef ring *_ring = parent._ring |
| | 2245 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2246 | cdef poly *p = p_Copy(self._poly, _ring) |
| | 2247 | cdef poly *t |
| | 2248 | |
| | 2249 | if p == NULL: |
| | 2250 | return [parent._zero_element] |
| | 2251 | |
| | 2252 | while p: |
| | 2253 | t = pNext(p) |
| | 2254 | p.next = NULL |
| | 2255 | p_SetCoeff(p, n_Init(1,_ring), _ring) |
| | 2256 | p_Setm(p, _ring) |
| | 2257 | l.append( new_NCP(parent,p) ) |
| | 2258 | p = t |
| | 2259 | |
| | 2260 | return l |
| | 2261 | |
| | 2262 | def constant_coefficient(self): |
| | 2263 | """ |
| | 2264 | Return the constant coefficient of this multivariate |
| | 2265 | polynomial. |
| | 2266 | |
| | 2267 | EXAMPLES:: |
| | 2268 | |
| | 2269 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2270 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2271 | sage: P.inject_variables() |
| | 2272 | Defining x, z, y |
| | 2273 | sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5 |
| | 2274 | sage: f.constant_coefficient() |
| | 2275 | 5 |
| | 2276 | sage: f = 3*x^2 |
| | 2277 | sage: f.constant_coefficient() |
| | 2278 | 0 |
| | 2279 | """ |
| | 2280 | cdef poly *p = self._poly |
| | 2281 | cdef ring *r = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2282 | if p == NULL: |
| | 2283 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2284 | |
| | 2285 | while p.next: |
| | 2286 | p = pNext(p) |
| | 2287 | |
| | 2288 | if p_LmIsConstant(p, r): |
| | 2289 | return si2sa( p_GetCoeff(p, r), r, (<NCPolynomialRing_plural>self._parent)._base ) |
| | 2290 | else: |
| | 2291 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2292 | |
| | 2293 | cpdef is_constant(self): |
| | 2294 | """ |
| | 2295 | Return ``True`` if this polynomial is constant. |
| | 2296 | |
| | 2297 | EXAMPLES:: |
| | 2298 | |
| | 2299 | sage: A.<x,z,y> = FreeAlgebra(GF(389), 3) |
| | 2300 | sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2301 | sage: P.inject_variables() |
| | 2302 | Defining x, z, y |
| | 2303 | sage: x.is_constant() |
| | 2304 | False |
| | 2305 | sage: P(1).is_constant() |
| | 2306 | True |
| | 2307 | """ |
| | 2308 | return bool(p_IsConstant(self._poly, (<NCPolynomialRing_plural>self._parent)._ring)) |
| | 2309 | |
| | 2310 | def lm(NCPolynomial_plural self): |
| | 2311 | """ |
| | 2312 | Returns the lead monomial of self with respect to the term |
| | 2313 | order of ``self.parent()``. In Sage a monomial is a product of |
| | 2314 | variables in some power without a coefficient. |
| | 2315 | |
| | 2316 | EXAMPLES:: |
| | 2317 | |
| | 2318 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2319 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2320 | sage: R.inject_variables() |
| | 2321 | Defining x, y, z |
| | 2322 | sage: f = x^1*y^2 + y^3*z^4 |
| | 2323 | sage: f.lm() |
| | 2324 | x*y^2 |
| | 2325 | sage: f = x^3*y^2*z^4 + x^3*y^2*z^1 |
| | 2326 | sage: f.lm() |
| | 2327 | x^3*y^2*z^4 |
| | 2328 | |
| | 2329 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2330 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='deglex') |
| | 2331 | sage: R.inject_variables() |
| | 2332 | Defining x, y, z |
| | 2333 | sage: f = x^1*y^2*z^3 + x^3*y^2*z^0 |
| | 2334 | sage: f.lm() |
| | 2335 | x*y^2*z^3 |
| | 2336 | sage: f = x^1*y^2*z^4 + x^1*y^1*z^5 |
| | 2337 | sage: f.lm() |
| | 2338 | x*y^2*z^4 |
| | 2339 | |
| | 2340 | sage: A.<x,y,z> = FreeAlgebra(GF(127), 3) |
| | 2341 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='degrevlex') |
| | 2342 | sage: R.inject_variables() |
| | 2343 | Defining x, y, z |
| | 2344 | sage: f = x^1*y^5*z^2 + x^4*y^1*z^3 |
| | 2345 | sage: f.lm() |
| | 2346 | x*y^5*z^2 |
| | 2347 | sage: f = x^4*y^7*z^1 + x^4*y^2*z^3 |
| | 2348 | sage: f.lm() |
| | 2349 | x^4*y^7*z |
| | 2350 | |
| | 2351 | """ |
| | 2352 | cdef poly *_p |
| | 2353 | cdef ring *_ring |
| | 2354 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2355 | if self._poly == NULL: |
| | 2356 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 2357 | _p = p_Head(self._poly, _ring) |
| | 2358 | p_SetCoeff(_p, n_Init(1,_ring), _ring) |
| | 2359 | p_Setm(_p,_ring) |
| | 2360 | return new_NCP((<NCPolynomialRing_plural>self._parent), _p) |
| | 2361 | |
| | 2362 | def lc(NCPolynomial_plural self): |
| | 2363 | """ |
| | 2364 | Leading coefficient of this polynomial with respect to the |
| | 2365 | term order of ``self.parent()``. |
| | 2366 | |
| | 2367 | EXAMPLES:: |
| | 2368 | |
| | 2369 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2370 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2371 | sage: R.inject_variables() |
| | 2372 | Defining x, y, z |
| | 2373 | |
| | 2374 | sage: f = 3*x^1*y^2 + 2*y^3*z^4 |
| | 2375 | sage: f.lc() |
| | 2376 | 3 |
| | 2377 | |
| | 2378 | sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 |
| | 2379 | sage: f.lc() |
| | 2380 | 5 |
| | 2381 | """ |
| | 2382 | |
| | 2383 | cdef poly *_p |
| | 2384 | cdef ring *_ring |
| | 2385 | cdef number *_n |
| | 2386 | _ring = (<NCPolynomialRing_plural>self._parent)._ring |
| | 2387 | |
| | 2388 | if self._poly == NULL: |
| | 2389 | return (<NCPolynomialRing_plural>self._parent)._base._zero_element |
| | 2390 | |
| | 2391 | if(_ring != currRing): rChangeCurrRing(_ring) |
| | 2392 | |
| | 2393 | _p = p_Head(self._poly, _ring) |
| | 2394 | _n = p_GetCoeff(_p, _ring) |
| | 2395 | |
| | 2396 | ret = si2sa(_n, _ring, (<NCPolynomialRing_plural>self._parent)._base) |
| | 2397 | p_Delete(&_p, _ring) |
| | 2398 | return ret |
| | 2399 | |
| | 2400 | def lt(NCPolynomial_plural self): |
| | 2401 | """ |
| | 2402 | Leading term of this polynomial. In Sage a term is a product |
| | 2403 | of variables in some power and a coefficient. |
| | 2404 | |
| | 2405 | EXAMPLES:: |
| | 2406 | |
| | 2407 | sage: A.<x,y,z> = FreeAlgebra(GF(7), 3) |
| | 2408 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2409 | sage: R.inject_variables() |
| | 2410 | Defining x, y, z |
| | 2411 | |
| | 2412 | sage: f = 3*x^1*y^2 + 2*y^3*z^4 |
| | 2413 | sage: f.lt() |
| | 2414 | 3*x*y^2 |
| | 2415 | |
| | 2416 | sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 |
| | 2417 | sage: f.lt() |
| | 2418 | -2*x^3*y^2*z^4 |
| | 2419 | """ |
| | 2420 | if self._poly == NULL: |
| | 2421 | return (<NCPolynomialRing_plural>self._parent)._zero_element |
| | 2422 | |
| | 2423 | return new_NCP((<NCPolynomialRing_plural>self._parent), |
| | 2424 | p_Head(self._poly,(<NCPolynomialRing_plural>self._parent)._ring)) |
| | 2425 | |
| | 2426 | def is_zero(self): |
| | 2427 | """ |
| | 2428 | Return ``True`` if this polynomial is zero. |
| | 2429 | |
| | 2430 | EXAMPLES:: |
| | 2431 | |
| | 2432 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 2433 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2434 | sage: R.inject_variables() |
| | 2435 | Defining x, z, y |
| | 2436 | |
| | 2437 | sage: x.is_zero() |
| | 2438 | False |
| | 2439 | sage: (x-x).is_zero() |
| | 2440 | True |
| | 2441 | """ |
| | 2442 | if self._poly is NULL: |
| | 2443 | return True |
| | 2444 | else: |
| | 2445 | return False |
| | 2446 | |
| | 2447 | def __nonzero__(self): |
| | 2448 | """ |
| | 2449 | EXAMPLES:: |
| | 2450 | |
| | 2451 | sage: A.<x,z,y> = FreeAlgebra(QQ, 3) |
| | 2452 | sage: R = A.g_algebra(relations={y*x:-x*y + z}, order='lex') |
| | 2453 | sage: R.inject_variables() |
| | 2454 | Defining x, z, y |
| | 2455 | |
| | 2456 | sage: bool(x) # indirect doctest |
| | 2457 | True |
| | 2458 | sage: bool(x-x) |
| | 2459 | False |
| | 2460 | """ |
| | 2461 | if self._poly: |
| | 2462 | return True |
| | 2463 | else: |
| | 2464 | return False |
| | 2465 | |
| | 2466 | |
| | 2467 | ##################################################################### |
| | 2468 | |
| | 2469 | |
| | 2470 | cdef inline NCPolynomial_plural new_NCP(NCPolynomialRing_plural parent, |
| | 2471 | poly *juice): |
| | 2472 | """ |
| | 2473 | Construct NCPolynomial_plural from parent and SINGULAR poly. |
| | 2474 | |
| | 2475 | EXAMPLES:: |
| | 2476 | |
| | 2477 | |
| | 2478 | """ |
| | 2479 | cdef NCPolynomial_plural p = PY_NEW(NCPolynomial_plural) |
| | 2480 | p._parent = <ParentWithBase>parent |
| | 2481 | p._poly = juice |
| | 2482 | p_Normalize(p._poly, parent._ring) |
| | 2483 | return p |
| | 2484 | |
| | 2485 | |
| | 2486 | |
| | 2487 | |
| | 2488 | cpdef MPolynomialRing_libsingular new_CRing(RingWrap rw, base_ring): |
| | 2489 | """ |
| | 2490 | Construct MPolynomialRing_libsingular from ringWrap, assumming the ground field to be base_ring |
| | 2491 | |
| | 2492 | EXAMPLES:: |
| | 2493 | sage: H.<x,y,z> = PolynomialRing(QQ, 3) |
| | 2494 | sage: from sage.libs.singular.function import singular_function |
| | 2495 | |
| | 2496 | sage: ringlist = singular_function('ringlist') |
| | 2497 | sage: ring = singular_function("ring") |
| | 2498 | |
| | 2499 | sage: L = ringlist(H, ring=H); L |
| | 2500 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0]] |
| | 2501 | |
| | 2502 | sage: len(L) |
| | 2503 | 4 |
| | 2504 | |
| | 2505 | sage: W = ring(L, ring=H); W |
| | 2506 | <RingWrap> |
| | 2507 | |
| | 2508 | sage: from sage.rings.polynomial.plural import new_CRing |
| | 2509 | sage: R = new_CRing(W, H.base_ring()) |
| | 2510 | sage: R # indirect doctest |
| | 2511 | Multivariate Polynomial Ring in x, y, z over Rational Field |
| | 2512 | """ |
| | 2513 | assert( rw.is_commutative() ) |
| | 2514 | |
| | 2515 | cdef MPolynomialRing_libsingular self = <MPolynomialRing_libsingular>PY_NEW(MPolynomialRing_libsingular) |
| | 2516 | |
| | 2517 | self._ring = rw._ring |
| | 2518 | self._ring.ShortOut = 0 |
| | 2519 | |
| | 2520 | self.__ngens = rw.ngens() |
| | 2521 | self.__term_order = TermOrder(rw.ordering_string(), force=True) |
| | 2522 | |
| | 2523 | ParentWithGens.__init__(self, base_ring, rw.var_names()) |
| | 2524 | # self._populate_coercion_lists_() # ??? |
| | 2525 | |
| | 2526 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 2527 | self._has_singular = True |
| | 2528 | # self._relations = self.relations() |
| | 2529 | |
| | 2530 | return self |
| | 2531 | |
| | 2532 | cpdef NCPolynomialRing_plural new_NRing(RingWrap rw, base_ring): |
| | 2533 | """ |
| | 2534 | Construct NCPolynomialRing_plural from ringWrap, assumming the ground field to be base_ring |
| | 2535 | |
| | 2536 | EXAMPLES:: |
| | 2537 | EXAMPLES:: |
| | 2538 | |
| | 2539 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2540 | sage: H = A.g_algebra({y*x:x*y-1}) |
| | 2541 | sage: H.inject_variables() |
| | 2542 | Defining x, y, z |
| | 2543 | sage: z*x |
| | 2544 | x*z |
| | 2545 | sage: z*y |
| | 2546 | y*z |
| | 2547 | sage: y*x |
| | 2548 | x*y - 1 |
| | 2549 | sage: I = H.ideal([y^2, x^2, z^2-1]) |
| | 2550 | sage: I._groebner_basis_libsingular() |
| | 2551 | [1] |
| | 2552 | |
| | 2553 | sage: from sage.libs.singular.function import singular_function |
| | 2554 | |
| | 2555 | sage: ringlist = singular_function('ringlist') |
| | 2556 | sage: ring = singular_function("ring") |
| | 2557 | |
| | 2558 | sage: L = ringlist(H, ring=H); L |
| | 2559 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1] |
| | 2560 | [0 0 1] |
| | 2561 | [0 0 0], [ 0 -1 0] |
| | 2562 | [ 0 0 0] |
| | 2563 | [ 0 0 0]] |
| | 2564 | |
| | 2565 | sage: len(L) |
| | 2566 | 6 |
| | 2567 | |
| | 2568 | sage: W = ring(L, ring=H); W |
| | 2569 | <noncommutative RingWrap> |
| | 2570 | |
| | 2571 | sage: from sage.rings.polynomial.plural import new_NRing |
| | 2572 | sage: R = new_NRing(W, H.base_ring()) |
| | 2573 | sage: R # indirect doctest |
| | 2574 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1} |
| | 2575 | """ |
| | 2576 | |
| | 2577 | assert( not rw.is_commutative() ) |
| | 2578 | |
| | 2579 | cdef NCPolynomialRing_plural self = <NCPolynomialRing_plural>PY_NEW(NCPolynomialRing_plural) |
| | 2580 | self._ring = rw._ring |
| | 2581 | self._ring.ShortOut = 0 |
| | 2582 | |
| | 2583 | self.__ngens = rw.ngens() |
| | 2584 | self.__term_order = TermOrder(rw.ordering_string(), force=True) |
| | 2585 | |
| | 2586 | ParentWithGens.__init__(self, base_ring, rw.var_names()) |
| | 2587 | # self._populate_coercion_lists_() # ??? |
| | 2588 | |
| | 2589 | #MPolynomialRing_generic.__init__(self, base_ring, n, names, order) |
| | 2590 | self._has_singular = True |
| | 2591 | self._relations = self.relations() |
| | 2592 | |
| | 2593 | return self |
| | 2594 | |
| | 2595 | |
| | 2596 | def new_Ring(RingWrap rw, base_ring): |
| | 2597 | """ |
| | 2598 | Constructs a Sage ring out of low level RingWrap, which wraps a pointer to a Singular ring. |
| | 2599 | The constructed ring is either commutative or noncommutative depending on the Singular ring. |
| | 2600 | |
| | 2601 | EXAMPLES:: |
| | 2602 | |
| | 2603 | sage: A.<x,y,z> = FreeAlgebra(QQ, 3) |
| | 2604 | sage: H = A.g_algebra({y*x:x*y-1}) |
| | 2605 | sage: H.inject_variables() |
| | 2606 | Defining x, y, z |
| | 2607 | sage: z*x |
| | 2608 | x*z |
| | 2609 | sage: z*y |
| | 2610 | y*z |
| | 2611 | sage: y*x |
| | 2612 | x*y - 1 |
| | 2613 | sage: I = H.ideal([y^2, x^2, z^2-1]) |
| | 2614 | sage: I._groebner_basis_libsingular() |
| | 2615 | [1] |
| | 2616 | |
| | 2617 | sage: from sage.libs.singular.function import singular_function |
| | 2618 | |
| | 2619 | sage: ringlist = singular_function('ringlist') |
| | 2620 | sage: ring = singular_function("ring") |
| | 2621 | |
| | 2622 | sage: L = ringlist(H, ring=H); L |
| | 2623 | [0, ['x', 'y', 'z'], [['dp', (1, 1, 1)], ['C', (0,)]], [0], [0 1 1] |
| | 2624 | [0 0 1] |
| | 2625 | [0 0 0], [ 0 -1 0] |
| | 2626 | [ 0 0 0] |
| | 2627 | [ 0 0 0]] |
| | 2628 | |
| | 2629 | sage: len(L) |
| | 2630 | 6 |
| | 2631 | |
| | 2632 | sage: W = ring(L, ring=H); W |
| | 2633 | <noncommutative RingWrap> |
| | 2634 | |
| | 2635 | sage: from sage.rings.polynomial.plural import new_Ring |
| | 2636 | sage: R = new_Ring(W, H.base_ring()); R |
| | 2637 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: x*y - 1} |
| | 2638 | |
| | 2639 | """ |
| | 2640 | import warnings |
| | 2641 | # warnings.warn("This is a hack. Please, use it on your own risk...") |
| | 2642 | if rw.is_commutative(): |
| | 2643 | return new_CRing(rw, base_ring) |
| | 2644 | return new_NRing(rw, base_ring) |
| | 2645 | |
| | 2646 | |
| | 2647 | def SCA(base_ring, names, alt_vars, order='degrevlex'): |
| | 2648 | """ |
| | 2649 | Shortcut to construct a graded commutative algebra out of the following data: |
| | 2650 | |
| | 2651 | Input: |
| | 2652 | |
| | 2653 | - ``base_ring``: the ground field |
| | 2654 | - ``names``: a list of variable names |
| | 2655 | - ``alt_vars``: a list of indices of to be anti-commutative variables |
| | 2656 | - ``order``: orderig to be used for the constructed algebra |
| | 2657 | |
| | 2658 | EXAMPLES:: |
| | 2659 | |
| | 2660 | sage: from sage.rings.polynomial.plural import SCA |
| | 2661 | sage: E = SCA(QQ, ['x', 'y', 'z'], [0, 1], order = 'degrevlex') |
| | 2662 | sage: E |
| | 2663 | Noncommutative Multivariate Polynomial Ring in x, y, z over Rational Field, nc-relations: {y*x: -x*y} |
| | 2664 | sage: E.inject_variables() |
| | 2665 | Defining x, y, z |
| | 2666 | sage: y*x |
| | 2667 | -x*y |
| | 2668 | sage: x^2 |
| | 2669 | 0 |
| | 2670 | sage: y^2 |
| | 2671 | 0 |
| | 2672 | sage: z^2 |
| | 2673 | z^2 |
| | 2674 | """ |
| | 2675 | n = len(names) |
| | 2676 | alt_start = min(alt_vars) |
| | 2677 | alt_end = max(alt_vars) |
| | 2678 | assert( alt_start >= 0 ) |
| | 2679 | assert( (alt_end >= alt_start) and (alt_end < n) ) |
| | 2680 | |
| | 2681 | relations = {} # {y*x:-x*y} |
| | 2682 | from sage.algebras.free_algebra import FreeAlgebra |
| | 2683 | A = FreeAlgebra(base_ring, n, names) |
| | 2684 | for r in range(0, n-1, 1): |
| | 2685 | for c in range(r+1, n, 1): |
| | 2686 | if (r in alt_vars) and (c in alt_vars): |
| | 2687 | relations[ A.gen(c) * A.gen(r) ] = - A.gen(r) * A.gen(c) |
| | 2688 | |
| | 2689 | H = A.g_algebra(relations=relations, order=order) |
| | 2690 | I = H.ideal([H.gen(i) *H.gen(i) for i in alt_vars]).twostd() |
| | 2691 | return H.quotient(I) |
| | 2692 | |
| | 2693 | cdef poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring): |
| | 2694 | if p_GetExp(tempvector, pos, _ring) < p_GetExp(maxvector, pos, _ring): |
| | 2695 | p_SetExp(tempvector, pos, p_GetExp(tempvector, pos, _ring)+1, _ring) |
| | 2696 | else: |
| | 2697 | p_SetExp(tempvector, pos, 0, _ring) |
| | 2698 | tempvector = addwithcarry(tempvector, maxvector, pos + 1, _ring) |
| | 2699 | p_Setm(tempvector, _ring) |
| | 2700 | return tempvector |