Ticket #3662: trac_3662-1.patch
| File trac_3662-1.patch, 51.1 KB (added by mhansen, 5 years ago) |
|---|
-
sage/combinat/all.py
# HG changeset patch # User Mike Hansen <mhansen@gmail.com> # Date 1218040523 18000 # Node ID 7b3cf283f954b3cc9da1e7d5ec49e538876e87e6 # Parent 7ecb9807b7b2ee73a1d5cbab60afaa967c775e3a Separate out free module functionality from CombinatorialAlgebra. diff -r 7ecb9807b7b2 -r 7b3cf283f954 sage/combinat/all.py
a b 4 4 from sage.combinat.crystals.all import * 5 5 from sage.combinat.dlx import * #?? 6 6 7 #Combinatorial Algebra 7 # Free modules and friends 8 from free_module import CombinatorialFreeModule 8 9 from combinatorial_algebra import CombinatorialAlgebra 9 10 10 11 -
sage/combinat/combinatorial_algebra.py
diff -r 7ecb9807b7b2 -r 7b3cf283f954 sage/combinat/combinatorial_algebra.py
a b 56 56 # http://www.gnu.org/licenses/ 57 57 #***************************************************************************** 58 58 59 from sage.rings.all import Ring, Integer 60 from sage.misc.misc import repr_lincomb 59 from sage.rings.all import Integer 61 60 from sage.algebras.algebra import Algebra 61 from sage.rings.ring import Ring 62 62 from sage.algebras.algebra_element import AlgebraElement 63 import sage.structure.parent_base64 import sage.combinat.partition65 from sage.modules.free_module_element import vector66 63 from sage.matrix.all import MatrixSpace 64 from sage.combinat.free_module import CombinatorialFreeModuleElement, CombinatorialFreeModule, CombinatorialFreeModuleInterface 67 65 68 class CombinatorialAlgebraElement(AlgebraElement ):66 class CombinatorialAlgebraElement(AlgebraElement, CombinatorialFreeModuleElement): 69 67 def __init__(self, A, x): 70 68 """ 71 69 Create a combinatorial algebra element x. This should never … … 82 80 AlgebraElement.__init__(self, A) 83 81 self._monomial_coefficients = x 84 82 85 def __iter__(self):86 """87 EXAMPLES:88 sage: s = SFASchur(QQ)89 sage: a = s([2,1]) + s([3])90 sage: [i for i in sorted(a)]91 [([2, 1], 1), ([3], 1)]92 83 93 """94 return self._monomial_coefficients.iteritems()95 96 def __contains__(self, x):97 """98 Returns whether or not a combinatorial object x indexing a basis99 element is in the support of self.100 101 EXAMPLES:102 sage: s = SFASchur(QQ)103 sage: a = s([2,1]) + s([3])104 sage: Partition([2,1]) in a105 True106 sage: Partition([1,1,1]) in a107 False108 """109 return x in self._monomial_coefficients and self._monomial_coefficients[x] != 0110 111 def monomial_coefficients(self):112 """113 Return the internal dictionary which has the combinatorial114 objects indexing the basis as keys and their corresponding115 coefficients as values.116 117 EXAMPLES:118 sage: s = SFASchur(QQ)119 sage: a = s([2,1])+2*s([3,2])120 sage: d = a.monomial_coefficients()121 sage: type(d)122 <type 'dict'>123 sage: d[ Partition([2,1]) ]124 1125 sage: d[ Partition([3,2]) ]126 2127 """128 return self._monomial_coefficients129 130 def __repr__(self):131 """132 EXAMPLES:133 sage: QS3 = SymmetricGroupAlgebra(QQ,3)134 sage: a = 2 + QS3([2,1,3])135 sage: print a.__repr__()136 2*[1, 2, 3] + [2, 1, 3]137 """138 v = self._monomial_coefficients.items()139 v.sort()140 prefix = self.parent().prefix()141 mons = [ prefix + repr(m) for (m, _) in v ]142 cffs = [ x for (_, x) in v ]143 x = repr_lincomb(mons, cffs).replace("*1 "," ")144 if x[len(x)-2:] == "*1":145 return x[:len(x)-2]146 else:147 return x148 149 def _latex_(self):150 """151 EXAMPLES:152 sage: QS3 = SymmetricGroupAlgebra(QQ,3)153 sage: a = 2 + QS3([2,1,3])154 sage: latex(a) #indirect doctest155 2[1,2,3] + [2,1,3]156 """157 v = self._monomial_coefficients.items()158 v.sort()159 prefix = self.parent().prefix()160 if prefix == "":161 mons = [ prefix + '[' + ",".join(map(str, m)) + ']' for (m, _) in v ]162 else:163 mons = [ prefix + '_{' + ",".join(map(str, m)) + '}' for (m, _) in v ]164 cffs = [ x for (_, x) in v ]165 x = repr_lincomb(mons, cffs, is_latex=True).replace("*1 "," ")166 if x[len(x)-2:] == "*1":167 return x[:len(x)-2]168 else:169 return x170 171 def __cmp__(left, right):172 """173 The ordering is the one on the underlying sorted list of174 (monomial,coefficients) pairs.175 176 EXAMPLES:177 sage: s = SFASchur(QQ)178 sage: a = s([2,1])179 sage: b = s([1,1,1])180 sage: cmp(a,b) #indirect doctest181 1182 """183 nonzero = lambda mc: mc[1] != 0184 v = filter(nonzero, left._monomial_coefficients.items())185 v.sort()186 w = filter(nonzero, right._monomial_coefficients.items())187 w.sort()188 return cmp(v, w)189 190 def _add_(self, y):191 """192 EXAMPLES:193 sage: s = SFASchur(QQ)194 sage: s([2,1]) + s([5,4]) # indirect doctest195 s[2, 1] + s[5, 4]196 sage: a = s([2,1]) + 0197 sage: len(a.monomial_coefficients())198 1199 """200 A = self.parent()201 BR = A.base_ring()202 z_elt = dict(self._monomial_coefficients)203 for m, c in y._monomial_coefficients.iteritems():204 if z_elt.has_key(m):205 cm = z_elt[m] + c206 if cm == 0:207 del z_elt[m]208 else:209 z_elt[m] = cm210 else:211 z_elt[m] = c212 213 214 #Remove all entries that are equal to 0215 del_list = []216 zero = BR(0)217 for m, c in z_elt.iteritems():218 if c == zero:219 del_list.append(m)220 for m in del_list:221 del z_elt[m]222 223 return A._from_dict(z_elt)224 225 226 def _neg_(self):227 """228 EXAMPLES:229 sage: s = SFASchur(QQ)230 sage: -s([2,1]) # indirect doctest231 -s[2, 1]232 """233 return self.map_coefficients(lambda c: -c)234 235 236 def _sub_(self, y):237 """238 EXAMPLES:239 sage: s = SFASchur(QQ)240 sage: s([2,1]) - s([5,4]) # indirect doctest241 s[2, 1] - s[5, 4]242 """243 A = self.parent()244 BR = A.base_ring()245 z_elt = dict(self._monomial_coefficients)246 for m, c in y._monomial_coefficients.iteritems():247 if z_elt.has_key(m):248 cm = z_elt[m] - c249 if cm == 0:250 del z_elt[m]251 else:252 z_elt[m] = cm253 else:254 z_elt[m] = -c255 256 #Remove all entries that are equal to 0257 zero = BR(0)258 del_list = []259 for m, c in z_elt.iteritems():260 if c == zero:261 del_list.append(m)262 for m in del_list:263 del z_elt[m]264 265 return A._from_dict(z_elt)266 267 84 def _mul_(self, y): 268 85 """ 269 86 EXAMPLES: … … 316 133 sage: s([2])^2 317 134 s[2, 2] + s[3, 1] + s[4] 318 135 319 320 136 TESTS: 321 137 sage: s = SFASchur(QQ) 322 138 sage: z = s([2,1]) … … 339 155 for _ in range(n): 340 156 z *= self 341 157 return z 342 343 def _coefficient_fast(self, m, default=None):344 """345 Returns the coefficient of m in self, where m is key346 in self._monomial_coefficients.347 348 EXAMPLES:349 sage: p = Partition([2,1])350 sage: s = SFASchur(QQ)351 sage: a = s([2,1])352 sage: a._coefficient_fast([2,1])353 Traceback (most recent call last):354 ...355 TypeError: list objects are unhashable356 sage: a._coefficient_fast(p)357 1358 sage: a._coefficient_fast(p, 2)359 1360 """361 if default is None:362 default = self.base_ring()(0)363 return self._monomial_coefficients.get(m, default)364 365 def coefficient(self, m):366 """367 EXAMPLES:368 sage: s = SFASchur(QQ)369 sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1])370 sage: z.coefficient([4])371 1372 sage: z.coefficient([2,1])373 -2374 """375 p = self.parent()376 if isinstance(m, p._combinatorial_class.object_class):377 return self._monomial_coefficients.get(m, p.base_ring().zero_element())378 if m in p._combinatorial_class:379 return self._monomial_coefficients.get(p._combinatorial_class.object_class(m), p.base_ring().zero_element())380 else:381 raise TypeError, "you must specify an element of %s"%p._combinatorial_class382 383 384 def is_zero(self):385 """386 Returns True if and only self == 0.387 388 EXAMPLES:389 sage: s = SFASchur(QQ)390 sage: s([2,1]).is_zero()391 False392 sage: s(0).is_zero()393 True394 sage: (s([2,1]) - s([2,1])).is_zero()395 True396 """397 BR = self.parent().base_ring()398 for v in self._monomial_coefficients.values():399 if v != BR(0):400 return False401 return True402 403 def __len__(self):404 """405 Returns the number of basis elements of self with406 nonzero coefficients.407 408 EXAMPLES:409 sage: s = SFASchur(QQ)410 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1])411 sage: len(z)412 4413 """414 return self.length()415 416 def length(self):417 """418 Returns the number of basis elements of self with419 nonzero coefficients.420 421 EXAMPLES:422 sage: s = SFASchur(QQ)423 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1])424 sage: z.length()425 4426 """427 return len( filter(lambda x: self._monomial_coefficients[x] != 0, self._monomial_coefficients) )428 429 def support(self):430 """431 Returns a pair [mons, cffs] of lists of the monomials432 of self (mons) and their respective coefficients (cffs).433 434 EXAMPLES:435 sage: s = SFASchur(QQ)436 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1])437 sage: z.support()438 [[[1], [1, 1, 1], [2, 1], [4]], [1, 1, 1, 1]]439 """440 v = self._monomial_coefficients.items()441 v.sort()442 mons = [ m for (m, _) in v ]443 cffs = [ x for (_, x) in v ]444 return [mons, cffs]445 446 def monomials(self):447 """448 Returns a list of the combinatorial objects indexing449 the basis elements of self which non-zero coefficients.450 451 EXAMPLES:452 sage: s = SFASchur(QQ)453 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1])454 sage: z.monomials()455 [[1], [1, 1, 1], [2, 1], [4]]456 """457 v = self._monomial_coefficients.items()458 v.sort()459 mons = [ m for (m, _) in v ]460 return mons461 462 def coefficients(self):463 """464 Returns a list of the coefficents appearing on the465 basiselements in self.466 467 EXAMPLES:468 sage: s = SFASchur(QQ)469 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1])470 sage: z.coefficients()471 [1, 1, 1, 1]472 """473 v = self._monomial_coefficients.items()474 v.sort()475 cffs = [ c for (_, c) in v ]476 return cffs477 478 def _vector_(self, new_BR=None):479 """480 Returns a vector version of self. If new_BR is specified,481 then in returns a vector over new_BR.482 483 EXAMPLES:484 sage: QS3 = SymmetricGroupAlgebra(QQ, 3)485 sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1])486 sage: a._vector_()487 (2, 0, 0, 0, 0, 4)488 sage: vector(a)489 (2, 0, 0, 0, 0, 4)490 sage: a._vector_(RDF)491 (2.0, 0.0, 0.0, 0.0, 0.0, 4.0)492 """493 parent = self.parent()494 if parent.get_order() is None:495 cc = parent._combinatorial_class496 else:497 cc = parent.get_order()498 499 if new_BR is None:500 new_BR = parent.base_ring()501 502 return vector(new_BR, [new_BR(self._monomial_coefficients.get(m, 0)) for m in cc])503 504 def to_vector(self):505 """506 Returns a vector version of self.507 508 EXAMPLES:509 sage: QS3 = SymmetricGroupAlgebra(QQ, 3)510 sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1])511 sage: a.to_vector()512 (2, 0, 0, 0, 0, 4)513 """514 return self._vector_()515 158 516 159 def _matrix_(self, new_BR = None): 517 160 """ … … 550 193 if new_BR is None: 551 194 new_BR = BR 552 195 553 MS = MatrixSpace(new_BR, parent. _dim, parent._dim)196 MS = MatrixSpace(new_BR, parent.dimension(), parent.dimension()) 554 197 l = [ (self*parent(m)).to_vector() for m in cc ] 555 198 return MS(l).transpose() 556 199 … … 582 225 """ 583 226 return self._matrix_() 584 227 585 def map_coefficients(self, f):586 """587 Returns a new element of self.parent() obtained588 by applying the function f to all of the coefficients589 of self.590 591 EXAMPLES:592 sage: s = SFASchur(QQ)593 sage: a = s([2,1])+2*s([3,2])594 sage: a.map_coefficients(lambda x: x*2)595 2*s[2, 1] + 4*s[3, 2]596 """597 res = self.parent()(0)598 z_elt = {}599 for m,c in self.monomial_coefficients().iteritems():600 z_elt[m] = f(c)601 res._monomial_coefficients = z_elt602 return res603 604 def map_basis(self, f):605 """606 Returns a new element of self.parent() obtained607 by applying the function f to all of the combinatorial608 objects indexing the basis elements.609 610 EXAMPLES:611 sage: s = SFASchur(QQ)612 sage: a = s([2,1])+2*s([3,2])613 sage: a.map_basis(lambda x: x.conjugate())614 s[2, 1] + 2*s[2, 2, 1]615 """616 res = self.parent()(0)617 z_elt = {}618 for m,c in self.monomial_coefficients().iteritems():619 z_elt[f(m)] = c620 res._monomial_coefficients = z_elt621 return res622 623 def map_mc(self, f):624 """625 Returns a new element of self.parent() obtained626 by applying the function f to a monomial coefficient627 (m,c) pair. f returns a (new_m, new_c) pair.628 629 EXAMPLES:630 sage: s = SFASchur(QQ)631 sage: f = lambda m,c: (m.conjugate(), 2*c)632 sage: a = s([2,1]) + s([1,1,1])633 sage: a.map_mc(f)634 2*s[2, 1] + 2*s[3]635 """636 z_elt = {}637 for m,c in self.monomial_coefficients().iteritems():638 new_m, new_c = f(m,c)639 z_elt[new_m] = new_c640 return self.parent()._from_dict(z_elt)641 228 642 class CombinatorialAlgebra( Algebra):643 def __init__(self, R, element_class =None):229 class CombinatorialAlgebra(CombinatorialFreeModuleInterface, Algebra): 230 def __init__(self, R, element_class = None): 644 231 """ 645 232 TESTS: 646 233 sage: s = SFASchur(QQ) 647 234 sage: s == loads(dumps(s)) 648 235 True 649 236 """ 650 #Make sure R is a ring with unit element651 if not isinstance(R, Ring):652 raise TypeError, "Argument R must be a ring."653 try:654 z = R(Integer(1))655 except:656 raise ValueError, "R must have a unit element"657 658 237 #Check to make sure that the user defines the necessary 659 #attributes / methods to make the combinatorial algebra238 #attributes / methods to make the combinatorial module 660 239 #work 661 240 required = ['_combinatorial_class','_one',] 662 241 for r in required: … … 676 255 else: 677 256 self._element_class = element_class 678 257 679 #Set the dimension 680 try: 681 self._dim = self._combinatorial_class.count() 682 except (ValueError, NotImplementedError): 683 self._dim = None 684 685 self._order = None 686 687 #Initialize the base structure 688 sage.structure.parent_base.ParentWithBase.__init__(self, R) 689 690 _prefix = "" 691 _name = "CombinatorialAlgebra -- change me" 692 693 def basis(self): 694 """ 695 Returns a list of the basis elements of self. 696 697 EXAMPLES: 698 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 699 sage: QS3.basis() 700 [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 701 702 """ 703 return [self(x) for x in self._combinatorial_class] 704 705 def __call__(self, x): 706 """ 707 Coerce x into self. 708 709 EXAMPLES: 710 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 711 sage: QS3(2) 712 2*[1, 2, 3] 713 sage: QS3([2,3,1]) 714 [2, 3, 1] 715 """ 716 R = self.base_ring() 717 eclass = self._element_class 718 719 #Coerce ints to Integers 720 if isinstance(x, int): 721 x = Integer(x) 722 723 724 if hasattr(self, '_coerce_start'): 725 try: 726 return self._coerce_start(x) 727 except TypeError: 728 pass 729 730 #x is an element of the same type of combinatorial algebra 731 if hasattr(x, 'parent') and x.parent().__class__ is self.__class__: 732 P = x.parent() 733 #same base ring 734 if P is self: 735 return x 736 #different base ring -- coerce the coefficients from into R 737 else: 738 return eclass(self, dict([ (e1,R(e2)) for e1,e2 in x._monomial_coefficients.items()])) 739 #x is an element of the basis combinatorial class 740 elif isinstance(x, self._combinatorial_class.object_class): 741 return eclass(self, {x:R(1)}) 742 elif x in self._combinatorial_class: 743 return eclass(self, {self._combinatorial_class.object_class(x):R(1)}) 744 #Coerce elements of the base ring 745 elif hasattr(x, 'parent') and x.parent() is R: 746 if x == R(0): 747 return eclass(self, {}) 748 else: 749 return eclass(self, {self._one:x}) 750 #Coerce things that coerce into the base ring 751 elif R.has_coerce_map_from(x.parent()): 752 rx = R(x) 753 if rx == R(0): 754 return eclass(self, {}) 755 else: 756 return eclass(self, {self._one:R(x)}) 757 else: 758 if hasattr(self, '_coerce_end'): 759 try: 760 return self._coerce_start(x) 761 except TypeError: 762 pass 763 raise TypeError, "do not know how to make x (= %s) an element of self (=%s)"%(x,self) 764 765 766 def _an_element_impl(self): 767 """ 768 Returns an element of self, namely the unit element. 769 770 EXAMPLES: 771 sage: s = SFASchur(QQ) 772 sage: s._an_element_impl() 773 s[] 774 sage: _.parent() is s 775 True 776 """ 777 return self._element_class(self, {self._one:self.base_ring()(1)}) 778 779 def __repr__(self): 780 """ 781 EXAMPLES: 782 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 783 sage: print QS3.__repr__() 784 Symmetric group algebra of order 3 over Rational Field 785 786 """ 787 return self._name + " over %s"%self.base_ring() 788 789 def combinatorial_class(self): 790 """ 791 Returns the combinatorial class that indexes the basis 792 elements. 793 794 EXAMPLES: 795 sage: s = SFASchur(QQ) 796 sage: s.combinatorial_class() 797 Partitions 798 """ 799 return self._combinatorial_class 800 801 def _coerce_impl(self, x): 802 """ 803 EXAMPLES: 804 sage: s = SFASchur(QQ) 805 sage: s._coerce_impl(2) 806 2*s[] 807 """ 808 try: 809 R = x.parent() 810 if R.__class__ is self.__class__: 811 #Only perform the coercion if we can go from the base 812 #ring of x to the base ring of self 813 if self.base_ring().has_coerce_map_from( R.base_ring() ): 814 return self(x) 815 except AttributeError: 816 pass 817 818 # any ring that coerces to the base ring 819 return self._coerce_try(x, [self.base_ring()]) 820 821 def dimension(self): 822 """ 823 Returns the dimension of the combinatorial algebra (which is given 824 by the number of elements in the associated combinatorial class). 825 826 EXAMPLES: 827 sage: s = SFASchur(QQ) 828 sage: s.dimension() 829 +Infinity 830 """ 831 return self._combinatorial_class.count() 832 833 def set_order(self, order): 834 """ 835 Sets the order of the elements of the combinatorial class. 836 837 If .set_order() has not been called, then the ordering is 838 the one used in the generation of the elements of self's 839 associated combinatorial class. 840 841 EXAMPLES: 842 sage: QS2 = SymmetricGroupAlgebra(QQ,2) 843 sage: b = QS2.basis() 844 sage: b.reverse() 845 sage: QS2.set_order(b) 846 sage: QS2.get_order() 847 [[2, 1], [1, 2]] 848 849 """ 850 self._order = order 851 852 def get_order(self): 853 """ 854 Returns the order of the elements in the basis. 855 856 EXAMPLES: 857 sage: QS2 = SymmetricGroupAlgebra(QQ,2) 858 sage: QS2.get_order() 859 [[1, 2], [2, 1]] 860 """ 861 if self._order is None: 862 self._order = self.combinatorial_class().list() 863 return self._order 864 865 def prefix(self): 866 """ 867 Returns the prefix used when displaying elements of self. 868 869 EXAMPLES: 870 sage: X = SchubertPolynomialRing(QQ) 871 sage: X.prefix() 872 'X' 873 """ 874 return self._prefix 875 876 def __cmp__(self, other): 877 """ 878 EXAMPLES: 879 sage: XQ = SchubertPolynomialRing(QQ) 880 sage: XZ = SchubertPolynomialRing(ZZ) 881 sage: XQ == XZ #indirect doctest 882 False 883 sage: XQ == XQ 884 True 885 """ 886 if not isinstance(other, self.__class__): 887 return -1 888 c = cmp(self.base_ring(), other.base_ring()) 889 if c: return c 890 return 0 891 892 def _apply_module_morphism(self, x, f): 893 """ 894 Returns the image of x under the module morphism defined by 895 extending f by linearity. 896 897 INPUT: 898 -- x : a element of self 899 -- f : a function that takes in a combinatorial object 900 indexing a basis element and returns an element 901 of the target domain 902 903 EXAMPLES: 904 sage: s = SFASchur(QQ) 905 sage: a = s([3]) + s([2,1]) + s([1,1,1]) 906 sage: b = 2*a 907 sage: f = lambda part: len(part) 908 sage: s._apply_module_morphism(a, f) #1+2+3 909 6 910 sage: s._apply_module_morphism(b, f) #2*(1+2+3) 911 12 912 258 CombinatorialFreeModuleInterface.__init__(self, R, self._element_class) 913 259 914 """915 res = 0916 for m, c in x._monomial_coefficients.iteritems():917 res += c*f(m)918 return res919 920 921 def _apply_module_endomorphism(self, a, f):922 """923 This takes in a function from the basis elements924 to the elements of self and applies it linearly925 to a. Note that _apply_module_endomorphism does not926 require multiplication on self to be defined.927 928 EXAMPLES:929 sage: s = SFASchur(QQ)930 sage: f = lambda part: 2*s(part.conjugate())931 sage: s._apply_module_endomorphism( s([2,1]) + s([1,1,1]), f)932 2*s[2, 1] + 2*s[3]933 934 """935 mcs = a.monomial_coefficients()936 base_ring = self.base_ring()937 zero = base_ring(0)938 939 z_elt = {}940 for basis_element in mcs:941 f_mcs = f(basis_element).monomial_coefficients()942 for f_basis_element in f_mcs:943 z_elt[ f_basis_element ] = z_elt.get(f_basis_element, zero) + mcs[basis_element]*f_mcs[f_basis_element]944 945 return self._from_dict(z_elt)946 947 948 260 def multiply(self,left,right): 949 261 """ 950 262 Returns left*right where left and right are elements of self. … … 1006 318 del z_elt[m] 1007 319 1008 320 return self._from_dict(z_elt) 1009 1010 def _from_dict(self, d, coerce=False):1011 """1012 Given a monomial coefficient dictionary d, return the element1013 of self with the dictionary.1014 1015 EXAMPLES:1016 sage: e = SFAElementary(QQ)1017 sage: s = SFASchur(QQ)1018 sage: a = e([2,1]) + e([1,1,1]); a1019 e[1, 1, 1] + e[2, 1]1020 sage: s._from_dict(a.monomial_coefficients())1021 s[1, 1, 1] + s[2, 1]1022 1023 sage: part = Partition([2,1])1024 sage: d = {part:1}1025 sage: a = s._from_dict(d,coerce=True); a1026 s[2, 1]1027 sage: a.coefficient(part).parent()1028 Rational Field1029 """1030 if coerce:1031 R = self.base_ring()1032 d = [ (m,R(c)) for m,c in d.iteritems() ]1033 d = dict(d)1034 1035 return self._element_class(self, d) -
new file sage/combinat/free_module.py
diff -r 7ecb9807b7b2 -r 7b3cf283f954 sage/combinat/free_module.py
- + 1 #***************************************************************************** 2 # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 3 # 4 # Distributed under the terms of the GNU General Public License (GPL) 5 # 6 # This code is distributed in the hope that it will be useful, 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9 # General Public License for more details. 10 # 11 # The full text of the GPL is available at: 12 # 13 # http://www.gnu.org/licenses/ 14 #***************************************************************************** 15 from sage.structure.element import ModuleElement 16 from sage.modules.free_module_element import vector 17 from sage.misc.misc import repr_lincomb 18 from sage.modules.module import Module 19 from sage.rings.all import Ring, Integer 20 import sage.structure.parent_base 21 from sage.combinat.family import Family 22 23 # TODO: 24 # Rewrite all tests in a more self contained way 25 26 class CombinatorialFreeModuleElement(ModuleElement): 27 def __init__(self, M, x): 28 """ 29 Create a combinatorial module element x. This should never 30 be called directly, but only through the parent combinatorial 31 module's __call__ method. 32 33 """ 34 ModuleElement.__init__(self, M) 35 self._monomial_coefficients = x 36 37 def __iter__(self): 38 """ 39 EXAMPLES: 40 sage: s = SFASchur(QQ) 41 sage: a = s([2,1]) + s([3]) 42 sage: [i for i in sorted(a)] 43 [([2, 1], 1), ([3], 1)] 44 45 """ 46 return self._monomial_coefficients.iteritems() 47 48 def __contains__(self, x): 49 """ 50 Returns whether or not a combinatorial object x indexing a basis 51 element is in the support of self. 52 53 EXAMPLES: 54 sage: s = SFASchur(QQ) 55 sage: a = s([2,1]) + s([3]) 56 sage: Partition([2,1]) in a 57 True 58 sage: Partition([1,1,1]) in a 59 False 60 """ 61 return x in self._monomial_coefficients and self._monomial_coefficients[x] != 0 62 63 def monomial_coefficients(self): 64 """ 65 Return the internal dictionary which has the combinatorial 66 objects indexing the basis as keys and their corresponding 67 coefficients as values. 68 69 EXAMPLES: 70 sage: s = SFASchur(QQ) 71 sage: a = s([2,1])+2*s([3,2]) 72 sage: d = a.monomial_coefficients() 73 sage: type(d) 74 <type 'dict'> 75 sage: d[ Partition([2,1]) ] 76 1 77 sage: d[ Partition([3,2]) ] 78 2 79 """ 80 return self._monomial_coefficients 81 82 def __repr__(self): 83 """ 84 EXAMPLES: 85 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 86 sage: a = 2 + QS3([2,1,3]) 87 sage: print a.__repr__() 88 2*[1, 2, 3] + [2, 1, 3] 89 """ 90 v = self._monomial_coefficients.items() 91 v.sort() 92 prefix = self.parent().prefix() 93 mons = [ prefix + repr(m) for (m, _) in v ] 94 cffs = [ x for (_, x) in v ] 95 x = repr_lincomb(mons, cffs).replace("*1 "," ") 96 if x[len(x)-2:] == "*1": 97 return x[:len(x)-2] 98 else: 99 return x 100 101 def _latex_(self): 102 """ 103 EXAMPLES: 104 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 105 sage: a = 2 + QS3([2,1,3]) 106 sage: latex(a) #indirect doctest 107 2[1,2,3] + [2,1,3] 108 """ 109 v = self._monomial_coefficients.items() 110 v.sort() 111 prefix = self.parent().prefix() 112 if prefix == "": 113 mons = [ prefix + '[' + ",".join(map(str, m)) + ']' for (m, _) in v ] 114 else: 115 mons = [ prefix + '_{' + ",".join(map(str, m)) + '}' for (m, _) in v ] 116 cffs = [ x for (_, x) in v ] 117 x = repr_lincomb(mons, cffs, is_latex=True).replace("*1 "," ") 118 if x[len(x)-2:] == "*1": 119 return x[:len(x)-2] 120 else: 121 return x 122 123 def __cmp__(left, right): 124 """ 125 The ordering is the one on the underlying sorted list of 126 (monomial,coefficients) pairs. 127 128 EXAMPLES: 129 sage: s = SFASchur(QQ) 130 sage: a = s([2,1]) 131 sage: b = s([1,1,1]) 132 sage: cmp(a,b) #indirect doctest 133 1 134 """ 135 nonzero = lambda mc: mc[1] != 0 136 v = filter(nonzero, left._monomial_coefficients.items()) 137 v.sort() 138 w = filter(nonzero, right._monomial_coefficients.items()) 139 w.sort() 140 return cmp(v, w) 141 142 def _add_(self, y): 143 """ 144 EXAMPLES: 145 sage: s = SFASchur(QQ) 146 sage: s([2,1]) + s([5,4]) # indirect doctest 147 s[2, 1] + s[5, 4] 148 sage: a = s([2,1]) + 0 149 sage: len(a.monomial_coefficients()) 150 1 151 """ 152 A = self.parent() 153 BR = A.base_ring() 154 z_elt = dict(self._monomial_coefficients) 155 for m, c in y._monomial_coefficients.iteritems(): 156 if z_elt.has_key(m): 157 cm = z_elt[m] + c 158 if cm == 0: 159 del z_elt[m] 160 else: 161 z_elt[m] = cm 162 else: 163 z_elt[m] = c 164 165 166 #Remove all entries that are equal to 0 167 del_list = [] 168 zero = BR(0) 169 for m, c in z_elt.iteritems(): 170 if c == zero: 171 del_list.append(m) 172 for m in del_list: 173 del z_elt[m] 174 175 return A._from_dict(z_elt) 176 177 178 def _neg_(self): 179 """ 180 EXAMPLES: 181 sage: s = SFASchur(QQ) 182 sage: -s([2,1]) # indirect doctest 183 -s[2, 1] 184 """ 185 return self.map_coefficients(lambda c: -c) 186 187 188 def _sub_(self, y): 189 """ 190 EXAMPLES: 191 sage: s = SFASchur(QQ) 192 sage: s([2,1]) - s([5,4]) # indirect doctest 193 s[2, 1] - s[5, 4] 194 """ 195 A = self.parent() 196 BR = A.base_ring() 197 z_elt = dict(self._monomial_coefficients) 198 for m, c in y._monomial_coefficients.iteritems(): 199 if z_elt.has_key(m): 200 cm = z_elt[m] - c 201 if cm == 0: 202 del z_elt[m] 203 else: 204 z_elt[m] = cm 205 else: 206 z_elt[m] = -c 207 208 #Remove all entries that are equal to 0 209 zero = BR(0) 210 del_list = [] 211 for m, c in z_elt.iteritems(): 212 if c == zero: 213 del_list.append(m) 214 for m in del_list: 215 del z_elt[m] 216 217 return A._from_dict(z_elt) 218 219 220 def _coefficient_fast(self, m, default=None): 221 """ 222 Returns the coefficient of m in self, where m is key 223 in self._monomial_coefficients. 224 225 EXAMPLES: 226 sage: p = Partition([2,1]) 227 sage: s = SFASchur(QQ) 228 sage: a = s([2,1]) 229 sage: a._coefficient_fast([2,1]) 230 Traceback (most recent call last): 231 ... 232 TypeError: list objects are unhashable 233 sage: a._coefficient_fast(p) 234 1 235 sage: a._coefficient_fast(p, 2) 236 1 237 """ 238 if default is None: 239 default = self.base_ring()(0) 240 return self._monomial_coefficients.get(m, default) 241 242 def coefficient(self, m): 243 """ 244 245 # NT: coefficient_fast should be the default, just with appropriate assertions 246 # that can be turned on or of 247 248 EXAMPLES: 249 sage: s = SFASchur(QQ) 250 sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1]) 251 sage: z.coefficient([4]) 252 1 253 sage: z.coefficient([2,1]) 254 -2 255 """ 256 p = self.parent() 257 if isinstance(m, p._combinatorial_class.object_class): 258 return self._monomial_coefficients.get(m, p.base_ring().zero_element()) 259 if m in p._combinatorial_class: 260 return self._monomial_coefficients.get(p._combinatorial_class.object_class(m), p.base_ring().zero_element()) 261 else: 262 raise TypeError, "you must specify an element of %s"%p._combinatorial_class 263 264 265 def is_zero(self): 266 """ 267 Returns True if and only self == 0. 268 269 EXAMPLES: 270 sage: s = SFASchur(QQ) 271 sage: s([2,1]).is_zero() 272 False 273 sage: s(0).is_zero() 274 True 275 sage: (s([2,1]) - s([2,1])).is_zero() 276 True 277 """ 278 BR = self.parent().base_ring() 279 for v in self._monomial_coefficients.values(): 280 if v != BR(0): 281 return False 282 return True 283 284 def __len__(self): 285 """ 286 Returns the number of basis elements of self with 287 nonzero coefficients. 288 289 EXAMPLES: 290 sage: s = SFASchur(QQ) 291 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) 292 sage: len(z) 293 4 294 """ 295 return self.length() 296 297 def length(self): 298 """ 299 Returns the number of basis elements of self with 300 nonzero coefficients. 301 302 EXAMPLES: 303 sage: s = SFASchur(QQ) 304 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) 305 sage: z.length() 306 4 307 """ 308 return len( filter(lambda x: self._monomial_coefficients[x] != 0, self._monomial_coefficients) ) 309 310 311 def support(self): 312 """ 313 # NT: ??? 314 Returns a pair [mons, cffs] of lists of the monomials 315 of self (mons) and their respective coefficients (cffs). 316 317 EXAMPLES: 318 sage: s = SFASchur(QQ) 319 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) 320 sage: z.support() 321 [[[1], [1, 1, 1], [2, 1], [4]], [1, 1, 1, 1]] 322 """ 323 v = self._monomial_coefficients.items() 324 v.sort() 325 mons = [ m for (m, _) in v ] 326 cffs = [ x for (_, x) in v ] 327 return [mons, cffs] 328 329 def monomials(self): 330 """ 331 Returns a list of the combinatorial objects indexing 332 the basis elements of self which non-zero coefficients. 333 334 EXAMPLES: 335 sage: s = SFASchur(QQ) 336 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) 337 sage: z.monomials() 338 [[1], [1, 1, 1], [2, 1], [4]] 339 """ 340 v = self._monomial_coefficients.items() 341 v.sort() 342 mons = [ m for (m, _) in v ] 343 return mons 344 345 def coefficients(self): 346 """ 347 Returns a list of the coefficents appearing on the 348 basiselements in self. 349 350 EXAMPLES: 351 sage: s = SFASchur(QQ) 352 sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) 353 sage: z.coefficients() 354 [1, 1, 1, 1] 355 """ 356 v = self._monomial_coefficients.items() 357 v.sort() 358 cffs = [ c for (_, c) in v ] 359 return cffs 360 361 def _vector_(self, new_BR=None): 362 """ 363 Returns a vector version of self. If new_BR is specified, 364 then in returns a vector over new_BR. 365 366 EXAMPLES: 367 sage: QS3 = SymmetricGroupAlgebra(QQ, 3) 368 sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1]) 369 sage: a._vector_() 370 (2, 0, 0, 0, 0, 4) 371 sage: vector(a) 372 (2, 0, 0, 0, 0, 4) 373 sage: a._vector_(RDF) 374 (2.0, 0.0, 0.0, 0.0, 0.0, 4.0) 375 """ 376 parent = self.parent() 377 if parent.get_order() is None: 378 cc = parent._combinatorial_class 379 else: 380 cc = parent.get_order() 381 382 if new_BR is None: 383 new_BR = parent.base_ring() 384 385 return vector(new_BR, [new_BR(self._monomial_coefficients.get(m, 0)) for m in cc]) 386 387 def to_vector(self): 388 """ 389 Returns a vector version of self. 390 391 EXAMPLES: 392 sage: QS3 = SymmetricGroupAlgebra(QQ, 3) 393 sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1]) 394 sage: a.to_vector() 395 (2, 0, 0, 0, 0, 4) 396 """ 397 return self._vector_() 398 399 400 def map_coefficients(self, f): 401 """ 402 Returns a new element of self.parent() obtained 403 by applying the function f to all of the coefficients 404 of self. 405 406 EXAMPLES: 407 sage: s = SFASchur(QQ) 408 sage: a = s([2,1])+2*s([3,2]) 409 sage: a.map_coefficients(lambda x: x*2) 410 2*s[2, 1] + 4*s[3, 2] 411 """ 412 res = self.parent()(0) 413 z_elt = {} 414 for m,c in self.monomial_coefficients().iteritems(): 415 z_elt[m] = f(c) 416 res._monomial_coefficients = z_elt 417 return res 418 419 def map_basis(self, f): 420 """ 421 Returns a new element of self.parent() obtained 422 by applying the function f to all of the combinatorial 423 objects indexing the basis elements. 424 425 FIXME: rename to map_support? 426 427 EXAMPLES: 428 sage: s = SFASchur(QQ) 429 sage: a = s([2,1])+2*s([3,2]) 430 sage: a.map_basis(lambda x: x.conjugate()) 431 s[2, 1] + 2*s[2, 2, 1] 432 """ 433 res = self.parent()(0) 434 z_elt = {} 435 for m,c in self.monomial_coefficients().iteritems(): 436 z_elt[f(m)] = c 437 res._monomial_coefficients = z_elt 438 return res 439 440 def map_mc(self, f): 441 """ 442 Returns a new element of self.parent() obtained 443 by applying the function f to a monomial coefficient 444 (m,c) pair. f returns a (new_m, new_c) pair. 445 446 FIXME: map_monomial? 447 448 EXAMPLES: 449 sage: s = SFASchur(QQ) 450 sage: f = lambda m,c: (m.conjugate(), 2*c) 451 sage: a = s([2,1]) + s([1,1,1]) 452 sage: a.map_mc(f) 453 2*s[2, 1] + 2*s[3] 454 """ 455 z_elt = {} 456 for m,c in self.monomial_coefficients().iteritems(): 457 new_m, new_c = f(m,c) 458 z_elt[new_m] = new_c 459 return self.parent()._from_dict(z_elt) 460 461 # NT: There is nothing combinatorial here 462 # NT: It's really too bad that we can't have the ring as second optional argument 463 class CombinatorialFreeModuleInterface(): # Should not it inherit from ParentWithBase? 464 def __init__(self, R, element_class): 465 #Make sure R is a ring with unit element 466 if not isinstance(R, Ring): 467 raise TypeError, "Argument R must be a ring." 468 try: 469 # R._one_element? 470 z = R(Integer(1)) 471 except: 472 raise ValueError, "R must have a unit element" 473 474 self._element_class = element_class 475 self._order = None 476 477 #Initialize the base structure 478 sage.structure.parent_base.ParentWithBase.__init__(self, R) 479 480 _prefix = "" 481 _name = "CombinatorialModule -- change me" 482 483 484 # Should be an attribute? 485 def basis(self): 486 """ 487 Returns a list of the basis elements of self. 488 489 EXAMPLES: 490 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 491 sage: list(QS3.basis()) 492 [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 493 494 sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) 495 sage: F.basis() 496 Finite family {'a': B('a'), 'c': B('c'), 'b': B('b')} 497 498 """ 499 return Family(self._combinatorial_class, self.term) 500 501 def __call__(self, x): 502 """ 503 Coerce x into self. 504 505 EXAMPLES: 506 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 507 sage: QS3(2) 508 2*[1, 2, 3] 509 sage: QS3([2,3,1]) 510 [2, 3, 1] 511 """ 512 R = self.base_ring() 513 eclass = self._element_class 514 515 #Coerce ints to Integers 516 if isinstance(x, int): 517 x = Integer(x) 518 519 520 if hasattr(self, '_coerce_start'): 521 try: 522 return self._coerce_start(x) 523 except TypeError: 524 pass 525 526 # NT: coercion from the indexing set is louzy: 527 # in FreeModule(ZZ, [1,2,3]), how do tell the difference between 528 # an element of the ground ring and one of the indexing set? 529 530 #x is an element of the same type of combinatorial algebra 531 if hasattr(x, 'parent') and x.parent().__class__ is self.__class__: 532 P = x.parent() 533 #same base ring 534 if P is self: 535 return x 536 #different base ring -- coerce the coefficients from into R 537 else: 538 return eclass(self, dict([ (e1,R(e2)) for e1,e2 in x._monomial_coefficients.items()])) 539 #x is an element of the basis combinatorial class 540 elif isinstance(x, self._combinatorial_class.object_class): 541 return eclass(self, {x:R(1)}) 542 elif x in self._combinatorial_class: 543 return eclass(self, {self._combinatorial_class.object_class(x):R(1)}) 544 #Coerce elements of the base ring 545 elif hasattr(x, 'parent') and x.parent() is R: 546 if x == R(0): 547 return eclass(self, {}) 548 else: 549 return eclass(self, {self._one:x}) 550 #Coerce things that coerce into the base ring 551 elif R.has_coerce_map_from(x.parent()): 552 rx = R(x) 553 if rx == R(0): 554 return eclass(self, {}) 555 else: 556 return eclass(self, {self._one:R(x)}) 557 else: 558 if hasattr(self, '_coerce_end'): 559 try: 560 return self._coerce_start(x) 561 except TypeError: 562 pass 563 raise TypeError, "do not know how to make x (= %s) an element of self (=%s)"%(x,self) 564 565 def _an_element_impl(self): 566 """ 567 Returns an element of self, namely the unit element. 568 569 EXAMPLES: 570 sage: s = SFASchur(QQ) 571 sage: s._an_element_impl() 572 s[] 573 sage: _.parent() is s 574 True 575 """ 576 return self._element_class(self, {self._one:self.base_ring()(1)}) 577 578 def __repr__(self): 579 """ 580 EXAMPLES: 581 sage: QS3 = SymmetricGroupAlgebra(QQ,3) 582 sage: print QS3.__repr__() 583 Symmetric group algebra of order 3 over Rational Field 584 585 """ 586 return self._name + " over %s"%self.base_ring() 587 588 def combinatorial_class(self): 589 """ 590 Returns the combinatorial class that indexes the basis 591 elements. 592 593 EXAMPLES: 594 sage: s = SFASchur(QQ) 595 sage: s.combinatorial_class() 596 Partitions 597 """ 598 return self._combinatorial_class 599 600 def _coerce_impl(self, x): 601 """ 602 EXAMPLES: 603 sage: s = SFASchur(QQ) 604 sage: s._coerce_impl(2) 605 2*s[] 606 """ 607 try: 608 R = x.parent() 609 if R.__class__ is self.__class__: 610 #Only perform the coercion if we can go from the base 611 #ring of x to the base ring of self 612 if self.base_ring().has_coerce_map_from( R.base_ring() ): 613 return self(x) 614 except AttributeError: 615 pass 616 617 # any ring that coerces to the base ring 618 return self._coerce_try(x, [self.base_ring()]) 619 620 def dimension(self): 621 """ 622 Returns the dimension of the combinatorial algebra (which is given 623 by the number of elements in the associated combinatorial class). 624 625 EXAMPLES: 626 sage: s = SFASchur(QQ) 627 sage: s.dimension() 628 +Infinity 629 """ 630 return self._combinatorial_class.count() 631 632 def set_order(self, order): 633 """ 634 Sets the order of the elements of the combinatorial class. 635 636 If .set_order() has not been called, then the ordering is 637 the one used in the generation of the elements of self's 638 associated combinatorial class. 639 640 EXAMPLES: 641 sage: QS2 = SymmetricGroupAlgebra(QQ,2) 642 sage: b = list(QS2.basis().keys()) 643 sage: b.reverse() 644 sage: QS2.set_order(b) 645 sage: QS2.get_order() 646 [[2, 1], [1, 2]] 647 648 """ 649 self._order = order 650 651 def get_order(self): 652 """ 653 Returns the order of the elements in the basis. 654 655 EXAMPLES: 656 sage: QS2 = SymmetricGroupAlgebra(QQ,2) 657 sage: QS2.get_order() 658 [[1, 2], [2, 1]] 659 """ 660 if self._order is None: 661 self._order = self.combinatorial_class().list() 662 return self._order 663 664 def prefix(self): 665 """ 666 Returns the prefix used when displaying elements of self. 667 668 EXAMPLES: 669 sage: X = SchubertPolynomialRing(QQ) 670 sage: X.prefix() 671 'X' 672 """ 673 return self._prefix 674 675 def __cmp__(self, other): 676 """ 677 EXAMPLES: 678 sage: XQ = SchubertPolynomialRing(QQ) 679 sage: XZ = SchubertPolynomialRing(ZZ) 680 sage: XQ == XZ #indirect doctest 681 False 682 sage: XQ == XQ 683 True 684 """ 685 if not isinstance(other, self.__class__): 686 return -1 687 c = cmp(self.base_ring(), other.base_ring()) 688 if c: return c 689 return 0 690 691 def _apply_module_morphism(self, x, f): 692 """ 693 Returns the image of x under the module morphism defined by 694 extending f by linearity. 695 696 INPUT: 697 -- x : a element of self 698 -- f : a function that takes in a combinatorial object 699 indexing a basis element and returns an element 700 of the target domain 701 702 EXAMPLES: 703 sage: s = SFASchur(QQ) 704 sage: a = s([3]) + s([2,1]) + s([1,1,1]) 705 sage: b = 2*a 706 sage: f = lambda part: len(part) 707 sage: s._apply_module_morphism(a, f) #1+2+3 708 6 709 sage: s._apply_module_morphism(b, f) #2*(1+2+3) 710 12 711 712 713 """ 714 res = 0 715 for m, c in x._monomial_coefficients.iteritems(): 716 res += c*f(m) 717 return res 718 719 720 def _apply_module_endomorphism(self, a, f): 721 """ 722 This takes in a function from the basis elements 723 to the elements of self and applies it linearly 724 to a. Note that _apply_module_endomorphism does not 725 require multiplication on self to be defined. 726 727 EXAMPLES: 728 sage: s = SFASchur(QQ) 729 sage: f = lambda part: 2*s(part.conjugate()) 730 sage: s._apply_module_endomorphism( s([2,1]) + s([1,1,1]), f) 731 2*s[2, 1] + 2*s[3] 732 733 """ 734 mcs = a.monomial_coefficients() 735 base_ring = self.base_ring() 736 zero = base_ring(0) 737 738 z_elt = {} 739 for basis_element in mcs: 740 f_mcs = f(basis_element).monomial_coefficients() 741 for f_basis_element in f_mcs: 742 z_elt[ f_basis_element ] = z_elt.get(f_basis_element, zero) + mcs[basis_element]*f_mcs[f_basis_element] 743 744 return self._from_dict(z_elt) 745 746 def term(self, i): 747 return self._from_dict({i:self.base_ring()._one_element}) 748 749 def _from_dict(self, d, coerce=False): 750 """ 751 Given a monomial coefficient dictionary d, return the element 752 of self with the dictionary. 753 754 EXAMPLES: 755 sage: e = SFAElementary(QQ) 756 sage: s = SFASchur(QQ) 757 sage: a = e([2,1]) + e([1,1,1]); a 758 e[1, 1, 1] + e[2, 1] 759 sage: s._from_dict(a.monomial_coefficients()) 760 s[1, 1, 1] + s[2, 1] 761 762 sage: part = Partition([2,1]) 763 sage: d = {part:1} 764 sage: a = s._from_dict(d,coerce=True); a 765 s[2, 1] 766 sage: a.coefficient(part).parent() 767 Rational Field 768 """ 769 if coerce: 770 R = self.base_ring() 771 d = [ (m,R(c)) for m,c in d.iteritems() ] 772 d = dict(d) 773 774 return self._element_class(self, d) 775 776 class CombinatorialFreeModule(CombinatorialFreeModuleInterface, Module): 777 r""" 778 EXAMPLES: 779 We construct a free module whose basis is indexed by the letters a,b,c: 780 781 sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) 782 sage: F 783 Free module generated by ['a', 'b', 'c'] over Rational Field 784 785 Its basis is a family, indexed by a,b,c: 786 FIXME in family: we should preserve the order of the indices 787 sage: e = F.basis() 788 789 sage: e.keys() 790 ['a', 'b', 'c'] 791 sage: list(e) 792 [B('a'), B('b'), B('c')] 793 794 Let us construct some elements, and compute with them: 795 sage: e['a'] 796 B('a') 797 sage: 2*e['a'] 798 2*B('a') 799 sage: e['a'] + 3*e['b'] 800 2*B('a') + 3*e['b'] 801 """ 802 803 804 def __init__(self, R, combinatorial_class): 805 self._combinatorial_class = combinatorial_class 806 self._name = "Free module generated by %s"%combinatorial_class 807 CombinatorialFreeModuleInterface.__init__(self, R, CombinatorialFreeModuleElement) 808 pass
