Ticket #9370: trac_9370-module-elt-repr-all-in-one.patch

File trac_9370-module-elt-repr-all-in-one.patch, 37.3 KB (added by jhpalmieri, 10 years ago)

apply only this patch

  • sage/combinat/combinatorial_algebra.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1299818903 28800
    # Node ID 4a4d7a0ac621db0a488af651c4a5884357088a4d
    # Parent  361a4ad7d52c69b64ae2e658ffd0820af0d87e93
    #9370: customize printing of CombinatorialFreeModuleElements.
    All-in-one patch.
    
    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/combinat/combinatorial_algebra.py
    a b symmetric functions. 
    1919    ...         self._one = Partition([])
    2020    ...         self._name = 'Power-sum symmetric functions'
    2121    ...         CombinatorialAlgebra.__init__(self, R, Partitions())
    22     ...
    23     ...     _prefix = 'p'
     22    ...         self.print_options(prefix='p')
    2423    ...
    2524    ...     def _multiply_basis(self, a, b):
    2625    ...         l = list(a)+list(b)
    symmetric functions. 
    4241The important things to define are ._basis_keys which
    4342specifies the combinatorial class that indexes the basis elements,
    4443._one which specifies the identity element in the algebra, ._name
    45 which specifies the name of the algebra, ._prefix which is the
    46 string put in front of each basis element, and finally a _multiply
    47 or _multiply basis method that defines the multiplication in the
     44which specifies the name of the algebra, .print_options is used to set
     45the print options for the elements, and finally a _multiply
     46or _multiply_basis method that defines the multiplication in the
    4847algebra.
    4948"""
    5049#*****************************************************************************
  • sage/combinat/free_module.py

    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/combinat/free_module.py
    a b class CombinatorialFreeModuleElement(Ele 
    132132            sage: e = F.basis()
    133133            sage: e['a'] + 2*e['b'] # indirect doctest
    134134            F['a'] + 2*F['b']
     135            sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='')
     136            sage: e = F.basis()
     137            sage: e['a'] + 2*e['b'] # indirect doctest
     138            ['a'] + 2*['b']
     139            sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='', scalar_mult=' ', bracket=False)
     140            sage: e = F.basis()
     141            sage: e['a'] + 2*e['b'] # indirect doctest
     142            'a' + 2 'b'
    135143        """
    136144        v = self._monomial_coefficients.items()
    137145        try:
    138             v = sorted(v)
     146            v.sort()
    139147        except StandardError: # Sorting the output is a plus, but if we can't, no big deal
    140148            pass
    141149        repr_term = self.parent()._repr_term
    142         mons = [ repr_term(m) for (m, _) in v ]
    143         cffs = [ x for (_, x) in v ]
    144         x = repr_lincomb(mons, cffs).replace("*1 "," ")
    145         if x[len(x)-2:] == "*1":
    146             return x[:len(x)-2]
     150        v = [ (repr_term(m),x) for (m, x) in v ]
     151        if v:
     152            mons, cffs = zip(*v)
    147153        else:
    148             return x
     154            mons = cffs = []
     155        ast = self.parent()._print_options.get('scalar_mult', "*")
     156        x = repr_lincomb(mons, cffs,scalar_mult=ast).replace("%s1 "%ast," ")
     157        if x[len(x)-2:] == "%s1"%ast:
     158            x = x[:len(x)-2]
     159        return x
    149160
    150161    def _latex_(self):
    151162        """
    class CombinatorialFreeModuleElement(Ele 
    162173            sage: QS3 = SymmetricGroupAlgebra(QQ,3)
    163174            sage: a = 2 + QS3([2,1,3])
    164175            sage: latex(a) #indirect doctest
    165             2[1,2,3] + [2,1,3]
     176            2[1, 2, 3] + [2, 1, 3]
     177
     178       ::
     179
     180            sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='beta', latex_prefix='\\beta')
     181            sage: x = F.an_element()
     182            sage: x
     183            2*beta['a'] + 2*beta['b']
     184            sage: latex(x)
     185            2\beta_{a} + 2\beta_{b}
    166186        """
    167187        v = self._monomial_coefficients.items()
    168         v.sort()
    169         prefix = self.parent().prefix()
    170         if prefix == "":
    171             mons = [ prefix + '[' + ",".join(map(str, m)) + ']' for (m, _) in v ]
     188        try:
     189            v.sort()
     190        except StandardError: # Sorting the output is a plus, but if we can't, no big deal
     191            pass
     192
     193        alg = self.parent()
     194        latex_term = alg._latex_term
     195        v = [ (latex_term(m), x) for (m, x) in v ]
     196        if v:
     197            mons, cffs = zip(*v)
    172198        else:
    173             mons = [ prefix + '_{' + ",".join(map(str, m)) + '}' for (m, _) in v ]
    174         cffs = [ x for (_, x) in v ]
    175         x = repr_lincomb(mons, cffs, is_latex=True).replace("*1 "," ")
    176         if x[len(x)-2:] == "*1":
    177             return x[:len(x)-2]
     199            mons = cffs = []
     200        ast = alg._print_options.get('latex_scalar_mult')
     201        if ast is None:
     202            ast = alg._print_options.get('scalar_mult')
     203            if ast == '*':
     204                ast = ''
     205        ast_replace = ast if ast else ''
     206        ln = len(ast_replace)
     207        x = repr_lincomb(mons, cffs, is_latex=True, latex_scalar_mult=ast)
     208        if ln>0 and x[len(x)-ln-1:] == ast_replace+"1":
     209            return x[:len(x)-ln-1]
    178210        else:
    179211            return x
    180212
    def _divide_if_possible(x, y): 
    697729
    698730class CombinatorialFreeModule(UniqueRepresentation, Module):
    699731    r"""
     732    Class for free modules with a named basis
     733
     734    INPUT:
     735
     736    - ``R`` - base ring
     737
     738    - ``basis_keys`` - list, tuple, family, set, etc. defining the
     739      indexing set for the basis of this module
     740
     741    - ``element_class`` - the class of which elements of this module
     742      should be instances (optional, default None, in which case the
     743      elements are instances of
     744      :class:`CombinatorialFreeModuleElement`)
     745
     746    - ``category`` - the category in which this module lies (optional,
     747      default None, in which case use the "category of modules with
     748      basis" over the base ring ``R``)
     749
     750    Options controlling the printing of elements:
     751
     752    - ``prefix`` - string, prefix used for printing elements of this
     753      module (optional, default 'B').  With the default, a monomial
     754      indexed by 'a' would be printed as ``B['a']``.
     755
     756    - ``latex_prefix`` - string or None, prefix used in the LaTeX
     757      representation of elements (optional, default None). If this is
     758      anything except the empty string, it prints the index as a
     759      subscript.  If this is None, it uses the setting for ``prefix``,
     760      so if ``prefix`` is set to "B", then a monomial indexed by 'a'
     761      would be printed as ``B_{a}``.  If this is the empty string, then
     762      don't print monomials as subscripts: the monomial indexed by 'a'
     763      would be printed as ``a``, or as ``[a]`` if ``latex_bracket`` is
     764      True.
     765
     766    - ``bracket`` - None, bool, string, or list or tuple of
     767      strings (optional, default None): if None, use the value of the
     768      attribute ``self._repr_option_bracket``, which has default value
     769      True.  (``self._repr_option_bracket`` is available for backwards
     770      compatibility.  Users should set ``bracket`` instead.  If
     771      ``bracket`` is set to anything except None, it overrides
     772      the value of ``self._repr_option_bracket``.)  If False, do not
     773      include brackets when printing elements: a monomial indexed by
     774      'a' would be printed as ``B'a'``, and a monomial indexed by
     775      (1,2,3) would be printed as ``B(1,2,3)``.  If True, use "[" and
     776      "]" as brackets.  If it is one of "[", "(", or "{", use it and
     777      its partner as brackets.  If it is any other string, use it as
     778      both brackets.  If it is a list or tuple of strings, use the
     779      first entry as the left bracket and the second entry as the
     780      right bracket.
     781
     782    - ``latex_bracket`` - bool, string, or list or tuple of strings
     783      (optional, default False): if False, do not include brackets in
     784      the LaTeX representation of elements.  This option is only
     785      relevant if ``latex_prefix`` is the empty string; otherwise,
     786      brackets are not used regardless.  If True, use "\\left[" and
     787      "\\right]" as brackets.  If this is one of "[", "(", "\\{", "|",
     788      or "||", use it and its partner, prepended with "\\left" and
     789      "\\right", as brackets.  If this is any other string, use it as
     790      both brackets.  If this is a list or tuple of strings, use the
     791      first entry as the left bracket and the second entry as the
     792      right bracket.
     793
     794    - ``scalar_mult`` - string to use for scalar multiplication in
     795      the print representation (optional, default "*")
     796
     797    - ``latex_scalar_mult`` - string or None (optional, default None),
     798      string to use for scalar multiplication in the latex
     799      representation.  If None, use the empty string if ``scalar_mult``
     800      is set to "*", otherwise use the value of ``scalar_mult``.
     801
     802    - ``tensor_symbol`` - string or None (optional, default None),
     803      string to use for tensor product in the print representation. If
     804      None, use the ``sage.categories.tensor.symbol``.
     805
     806    These print options may also be accessed and modified using the
     807    :meth:`print_options` method, after the module has been defined.
     808
    700809    EXAMPLES:
    701810
    702811    We construct a free module whose basis is indexed by the letters a, b, c::
    class CombinatorialFreeModule(UniqueRepr 
    739848        sage: F.sum(F.monomial(i) for i in [1,2,3])
    740849        B[1] + B[2] + B[3]
    741850
    742     Note that the constructed free module depends on the order of the basis::
     851    Note that free modules with a given basis and parameters are unique::
     852
     853        sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4))
     854        sage: F1 is F
     855        True
     856
     857    The constructed free module depends on the order of the basis and
     858    on the other parameters, like the prefix::
    743859
    744860        sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4))
    745861        sage: F1 is F
    class CombinatorialFreeModule(UniqueRepr 
    747863        sage: F1 = CombinatorialFreeModule(QQ, [4,3,2,1])
    748864        sage: F1 == F
    749865        False
     866        sage: F2 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F')
     867        sage: F2 == F
     868        False
     869
     870    Because of this, if you create a free module with certain
     871    parameters and then modify its prefix or other print options, this
     872    affects all modules which were defined using the same parameters::
     873
     874        sage: F2.print_options(prefix='x')
     875        sage: F2.prefix()
     876        'x'
     877        sage: F3 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F')
     878        sage: F3 is F2   # F3 was defined just like F2
     879        True
     880        sage: F3.prefix()
     881        'x'
     882        sage: F4 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F', bracket=True)
     883        sage: F4 == F2   # F4 was NOT defined just like F2
     884        False
     885        sage: F4.prefix()
     886        'F'
     887
     888    The default category is the category of modules with basis over
     889    the base ring::
     890
     891        sage: CombinatorialFreeModule(GF(3), ((1,2), (3,4))).category()
     892        Category of modules with basis over Finite Field of size 3
     893
     894    See :mod:`sage.categories.examples.algebras_with_basis` and
     895    :mod:`sage.categories.examples.hopf_algebras_with_basis` for
     896    illustrations of the use of the ``category`` keyword, and see
     897    :class:`sage.combinat.root_system.weight_space.WeightSpace` for an
     898    example of the use of ``element_class``.
     899
     900    Customizing print and LaTeX representations of elements::
     901
     902        sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='x')
     903        sage: e = F.basis()
     904        sage: e['a'] - 3 * e['b']
     905        x['a'] - 3*x['b']
     906
     907        sage: F.print_options(prefix='x', scalar_mult=' ', bracket='{')
     908        sage: e['a'] - 3 * e['b']
     909        x{'a'} - 3 x{'b'}
     910        sage: latex(e['a'] - 3 * e['b'])
     911        x_{a} + \left(-3\right) x_{b}
     912
     913        sage: F.print_options(latex_prefix='y')
     914        sage: latex(e['a'] - 3 * e['b'])
     915        y_{a} + \left(-3\right) y_{b}
     916       
     917        sage: F = CombinatorialFreeModule(QQ, [(1,2), (3,4)])
     918        sage: e = F.basis()
     919        sage: e[(1,2)] - 3 * e[(3,4)]
     920        B[(1, 2)] - 3*B[(3, 4)]
     921
     922        sage: F.print_options(bracket=['_{', '}'])
     923        sage: e[(1,2)] - 3 * e[(3,4)]
     924        B_{(1, 2)} - 3*B_{(3, 4)}
     925
     926        sage: F.print_options(prefix='', bracket=False)
     927        sage: e[(1,2)] - 3 * e[(3,4)]
     928        (1, 2) - 3*(3, 4)
    750929    """
    751930
    752931    @staticmethod
    class CombinatorialFreeModule(UniqueRepr 
    758937            sage: G = CombinatorialFreeModule(QQ, ('a','b','c'))
    759938            sage: F is G
    760939            True
     940
     941            sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], latex_bracket=['LEFT', 'RIGHT'])
     942            sage: F.print_options()['latex_bracket']
     943            ('LEFT', 'RIGHT')
    761944        """
    762945        # Convert the argument args[1] into a FiniteEumeratedSet
    763946        # if it is a list or a tuple in order it to have a cardinality() method.
    class CombinatorialFreeModule(UniqueRepr 
    765948        # to __init__ to let it handle proper exception raising.
    766949        if len(args) >= 2 and isinstance(args[1], (list, tuple)):
    767950            args = (args[0], FiniteEnumeratedSet(args[1])) + args[2:]
     951        # bracket or latex_bracket might be lists, so convert
     952        # them to tuples so that they're hashable.
     953        bracket = keywords.get('bracket', None)
     954        if isinstance(bracket, list):
     955            keywords['bracket'] = tuple(bracket)
     956        latex_bracket = keywords.get('latex_bracket', None)
     957        if isinstance(latex_bracket, list):
     958            keywords['latex_bracket'] = tuple(latex_bracket)
    768959        return super(CombinatorialFreeModule, cls).__classcall__(cls, *args, **keywords)
    769960
    770961    Element = CombinatorialFreeModuleElement
    771962
    772     def __init__(self, R, basis_keys, element_class = None, prefix="B", category = None):
     963    def __init__(self, R, basis_keys, element_class = None, prefix="B", category = None, **kwds):
    773964        r"""
    774965        TESTS::
    775966
    class CombinatorialFreeModule(UniqueRepr 
    8401031
    8411032        self._order = None
    8421033
    843         if not hasattr(self, "_prefix"):
    844             self._prefix = prefix
     1034        # printing options for elements (set when initializing self).
     1035        # This includes self._repr_option_bracket (kept for backwards
     1036        # compatibility, declared to be True by default, needs to be
     1037        # overridden explicitly).
     1038        self._print_options = {}
     1039        self._print_options['prefix'] = prefix
     1040        # 'bracket': its default value here is None, meaning that
     1041        # the value of self._repr_option_bracket is used; the default
     1042        # value of that attribute is True -- see immediately before
     1043        # the method _repr_term.  If 'bracket' is any value
     1044        # except None, then it overrides the value of
     1045        # self._repr_option_bracket.  Future users might consider
     1046        # using 'bracket' instead of _repr_option_bracket.
     1047        self._print_options['bracket'] = kwds.get('bracket', None)
     1048        self._print_options['latex_bracket'] = kwds.get('latex_bracket', False)
     1049        self._print_options['latex_prefix'] = kwds.get('latex_prefix', None)
     1050        self._print_options['scalar_mult'] = kwds.get('scalar_mult', "*")
     1051        self._print_options['latex_scalar_mult'] = kwds.get('latex_scalar_mult', None)
     1052        self._print_options['tensor_symbol'] = kwds.get('tensor_symbol', None)
    8451053
    8461054    # mostly for backward compatibility
    8471055    @lazy_attribute
    class CombinatorialFreeModule(UniqueRepr 
    11821390        cc = self.get_order()
    11831391        return self._from_dict(dict( (cc[index], coeff) for (index,coeff) in vector.iteritems()))
    11841392
    1185 
    11861393    def prefix(self):
    11871394        """
    11881395        Returns the prefix used when displaying elements of self.
    class CombinatorialFreeModule(UniqueRepr 
    11991406            sage: X.prefix()
    12001407            'X'
    12011408        """
    1202         return self._prefix
     1409        return self._print_options['prefix']
     1410
     1411    def print_options(self, **kwds):
     1412        """
     1413        Return the current print options, or set an option.
     1414
     1415        INPUT: all of the input is optional; if present, it should be
     1416        in the form of keyword pairs, such as
     1417        ``latex_bracket='('``.  The allowable keywords are:
     1418
     1419        - ``prefix``
     1420        - ``latex_prefix``
     1421        - ``bracket``
     1422        - ``latex_bracket``
     1423        - ``scalar_mult``
     1424        - ``latex_scalar_mult``
     1425        - ``tensor_symbol``
     1426
     1427        See the documentation for :class:`CombinatorialFreeModule` for
     1428        descriptions of the effects of setting each of these options.
     1429
     1430        OUTPUT: if the user provides any input, set the appropriate
     1431        option(s) and return nothing.  Otherwise, return the
     1432        dictionary of settings for print and LaTeX representations.
     1433
     1434        EXAMPLES::
     1435
     1436            sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='x')
     1437            sage: F.print_options()
     1438            {'latex_prefix': None, 'scalar_mult': '*', 'prefix': 'x', 'bracket': None, 'latex_bracket': False, 'latex_scalar_mult': None, 'tensor_symbol': None}
     1439            sage: F.print_options(bracket='(')
     1440            sage: F.print_options()
     1441            {'latex_prefix': None, 'scalar_mult': '*', 'prefix': 'x', 'bracket': '(', 'latex_bracket': False, 'latex_scalar_mult': None, 'tensor_symbol': None}
     1442        """
     1443        # don't just use kwds.get(...) because I want to distinguish
     1444        # between an argument like "option=None" and the option not
     1445        # being there altogether.
     1446        args = False
     1447
     1448        for option in kwds:
     1449            if option in ['prefix', 'latex_prefix', 'bracket', 'latex_bracket',
     1450                          'scalar_mult', 'latex_scalar_mult', 'tensor_symbol']:
     1451                args = True
     1452                self._print_options[option] = kwds[option]
     1453            else:
     1454                raise ValueError, '%s is not a valid print option.' % option
     1455        if not args:
     1456            return self._print_options
     1457        return
    12031458
    12041459    _repr_option_bracket = True
    12051460
    12061461    def _repr_term(self, m):
    12071462        """
    1208         Returns a string representing the basis elements indexed by m.
    1209 
    1210         The output can be customized by mean of:
    1211          - self.prefix()
    1212          - self._repr_option_bracket # TODO: find a good name
    1213            (suggestions: _repr_with_bracket or _repr_add_bracket)
     1463        Returns a string representing the basis element indexed by m.
     1464
     1465        The output can be customized by setting any of the following
     1466        options when initializing the module:
     1467
     1468        - prefix
     1469        - bracket
     1470        - scalar_mult
     1471
     1472        Alternatively, one can use the :meth:`print_options` method
     1473        to achieve the same effect.  To modify the bracket setting,
     1474        one can also set ``self._repr_option_bracket`` as long as one
     1475        has *not* set the ``bracket`` option: if the
     1476        ``bracket`` option is anything but ``None``, it overrides
     1477        the value of ``self._repr_option_bracket``.
     1478
     1479        See the documentation for :class:`CombinatorialFreeModule` for
     1480        details on the initialization options.
    12141481
    12151482        EXAMPLES::
    12161483
    class CombinatorialFreeModule(UniqueRepr 
    12191486            sage: e['a'] + 2*e['b']    # indirect doctest
    12201487            B['a'] + 2*B['b']
    12211488
    1222             sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix="C")
     1489            sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix="F")
    12231490            sage: e = F.basis()
    12241491            sage: e['a'] + 2*e['b']    # indirect doctest
    1225             C['a'] + 2*C['b']
     1492            F['a'] + 2*F['b']
    12261493
    12271494            sage: QS3 = CombinatorialFreeModule(QQ, Permutations(3), prefix="")
    12281495            sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1])
    12291496            sage: a                      # indirect doctest
    12301497            2*[[1, 2, 3]] + 4*[[3, 2, 1]]
    12311498
    1232             sage: QS3._repr_option_bracket = False
     1499            sage: QS3.print_options(bracket = False)
    12331500            sage: a              # indirect doctest
    12341501            2*[1, 2, 3] + 4*[3, 2, 1]
    12351502
    1236             sage: QS3._repr_option_bracket = True
     1503            sage: QS3.print_options(prefix='')
    12371504            sage: a              # indirect doctest
    1238             2*[[1, 2, 3]] + 4*[[3, 2, 1]]
     1505            2*[1, 2, 3] + 4*[3, 2, 1]
     1506
     1507            sage: QS3.print_options(bracket="|", scalar_mult=" *@* ")
     1508            sage: a              # indirect doctest
     1509            2 *@* |[1, 2, 3]| + 4 *@* |[3, 2, 1]|
    12391510
    12401511        TESTS::
    12411512
    class CombinatorialFreeModule(UniqueRepr 
    12441515            sage: e[('a','b')] + 2*e[('c','d')]    # indirect doctest
    12451516            B[('a', 'b')] + 2*B[('c', 'd')]
    12461517        """
    1247         if self._repr_option_bracket:
    1248             return self.prefix()+"["+repr(m)+"]" # mind the (m), to accept a tuple for m
     1518        bracket = self._print_options.get('bracket', None)
     1519        bracket_d = {"{": "}", "[": "]", "(": ")"}
     1520        if bracket is None:
     1521            bracket = self._repr_option_bracket
     1522        if bracket is True:
     1523            left = "["
     1524            right = "]"
     1525        elif bracket is False:
     1526            left = ""
     1527            right = ""
     1528        elif isinstance(bracket, (tuple, list)):
     1529            left = bracket[0]
     1530            right = bracket[1]
     1531        elif bracket in bracket_d:
     1532            left = bracket
     1533            right = bracket_d[bracket]
    12491534        else:
    1250             return self.prefix()+repr(m)
    1251 
     1535            left = bracket
     1536            right = bracket
     1537        return self.prefix() + left + repr(m) + right # mind the (m), to accept a tuple for m
     1538
     1539    def _latex_term(self, m):
     1540        """
     1541        Returns a string for the LaTeX code for the basis element
     1542        indexed by m.
     1543
     1544        The output can be customized by setting any of the following
     1545        options when initializing the module:
     1546
     1547        - prefix
     1548        - latex_prefix
     1549        - latex_bracket
     1550
     1551        (Alternatively, one can use the :meth:`print_options` method
     1552        to achieve the same effect.)
     1553
     1554        See the documentation for :class:`CombinatorialFreeModule` for
     1555        details on the initialization options.
     1556
     1557        EXAMPLES::
     1558
     1559            sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
     1560            sage: e = F.basis()
     1561            sage: latex(e['a'] + 2*e['b'])    # indirect doctest
     1562            B_{a} + 2B_{b}
     1563
     1564            sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix="C")
     1565            sage: e = F.basis()
     1566            sage: latex(e['a'] + 2*e['b'])    # indirect doctest
     1567            C_{a} + 2C_{b}
     1568
     1569            sage: QS3 = CombinatorialFreeModule(QQ, Permutations(3), prefix="", scalar_mult="*")
     1570            sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1])
     1571            sage: latex(a)                     # indirect doctest
     1572            2[1, 2, 3] + 4[3, 2, 1]
     1573            sage: QS3.print_options(latex_bracket=True)
     1574            sage: latex(a)                     # indirect doctest
     1575            2\left[[1, 2, 3]\right] + 4\left[[3, 2, 1]\right]
     1576            sage: QS3.print_options(latex_bracket="(")
     1577            sage: latex(a)                     # indirect doctest
     1578            2\left([1, 2, 3]\right) + 4\left([3, 2, 1]\right)
     1579            sage: QS3.print_options(latex_bracket=('\\myleftbracket', '\\myrightbracket'))
     1580            sage: latex(a)                     # indirect doctest
     1581            2\myleftbracket[1, 2, 3]\myrightbracket + 4\myleftbracket[3, 2, 1]\myrightbracket
     1582
     1583        TESTS::
     1584
     1585            sage: F = CombinatorialFreeModule(QQ, [('a', 'b'), (0,1,2)])
     1586            sage: e = F.basis()
     1587            sage: latex(e[('a','b')])    # indirect doctest
     1588            B_{\left(a, b\right)}
     1589            sage: latex(2*e[(0,1,2)])    # indirect doctest
     1590            2B_{\left(0, 1, 2\right)}
     1591            sage: F = CombinatorialFreeModule(QQ, [('a', 'b'), (0,1,2)], prefix="")
     1592            sage: e = F.basis()
     1593            sage: latex(2*e[(0,1,2)])    # indirect doctest
     1594            2\left(0, 1, 2\right)
     1595        """
     1596        from sage.misc.latex import latex
     1597        import re
     1598        s = latex(m)
     1599        s = re.sub("\\\\texttt{([^}]*)}", "\\1", s)
     1600        # dictionary with left-right pairs of "brackets".  put pairs
     1601        # in here accept \\left and \\right as prefixes.
     1602        bracket_d = {"{": "\\}", "[": "]", "(": ")", "\\{": "\\}",
     1603                     "|": "|", "||": "||"}
     1604        bracket = self._print_options.get('latex_bracket', False)
     1605        if bracket is True:
     1606            left = "\\left["
     1607            right = "\\right]"
     1608        elif bracket is False:
     1609            left = ""
     1610            right = ""
     1611        elif isinstance(bracket, (tuple, list)):
     1612            left = bracket[0]
     1613            right = bracket[1]
     1614        elif bracket in bracket_d:
     1615            left = bracket
     1616            right = bracket_d[bracket]
     1617            if left == "{":
     1618                left = "\\{"
     1619            left = "\\left" + left
     1620            right = "\\right" + right
     1621        else:
     1622            left = bracket
     1623            right = bracket
     1624        prefix = self._print_options.get('latex_prefix')
     1625        if prefix is None:
     1626            prefix = self._print_options.get('prefix')
     1627        if prefix == "":
     1628            return left + s + right
     1629        return "%s_{%s}" % (prefix, s)
    12521630
    12531631    def __cmp__(self, other):
    12541632        """
    class CombinatorialFreeModule_Tensor(Com 
    16822060                sage: F = CombinatorialFreeModule(ZZ, [1,2]); F
    16832061                F
    16842062            """
     2063            from sage.categories.tensor import tensor
    16852064            self._sets = modules
    16862065            CombinatorialFreeModule.__init__(self, modules[0].base_ring(), CartesianProduct(*[module.basis().keys() for module in modules]).map(tuple), **options)
     2066            # the following is not the best option, but it's better than nothing.
     2067            self._print_options['tensor_symbol'] = options.get('tensor_symbol', tensor.symbol)
    16872068
    16882069        def _repr_(self):
    16892070            """
     2071            This is customizable by setting
     2072            ``self.print_options('tensor_symbol'=...)``.
     2073
    16902074            TESTS::
    16912075
    16922076                sage: F = CombinatorialFreeModule(ZZ, [1,2,3])
    16932077                sage: G = CombinatorialFreeModule(ZZ, [1,2,3,8])
    1694                 sage: tensor([F, G]) # indirect doctest
    1695                 Free module generated by {1, 2, 3} over Integer Ring # Free module generated by {1, 2, 3, 8} over Integer Ring
     2078                sage: F.rename("F")
     2079                sage: G.rename("G")
     2080                sage: T = tensor([F, G])
     2081                sage: T # indirect doctest
     2082                F # G
     2083                sage: T.print_options(tensor_symbol= ' @ ')  # note the spaces
     2084                sage: T # indirect doctest
     2085                F @ G
    16962086            """
    16972087            from sage.categories.tensor import tensor
    1698             return tensor.symbol.join(["%s"%module for module in self._sets])
     2088            if hasattr(self, "_print_options"):
     2089                symb = self._print_options['tensor_symbol']
     2090                if symb is None:
     2091                    symb = tensor.symbol
     2092            else:
     2093                symb = tensor.symbol
     2094            return symb.join(["%s"%module for module in self._sets])
    16992095            # TODO: make this overridable by setting _name
    17002096
     2097        def _latex_(self):
     2098            """
     2099            TESTS::
     2100
     2101                sage: F = CombinatorialFreeModule(ZZ, [1,2,3])
     2102                sage: G = CombinatorialFreeModule(ZZ, [1,2,3,8])
     2103                sage: F.rename("F")
     2104                sage: G.rename("G")
     2105                sage: latex(tensor([F, F, G])) # indirect doctest
     2106                \texttt{F} \otimes \texttt{F} \otimes \texttt{G}
     2107                sage: F._latex_ = lambda : "F"
     2108                sage: G._latex_ = lambda : "G"
     2109                sage: latex(tensor([F, F, G])) # indirect doctest
     2110                F \otimes F \otimes G
     2111            """
     2112            from sage.misc.latex import latex
     2113            symb = " \\otimes "
     2114            return symb.join(["%s"%latex(module) for module in self._sets])
     2115
    17012116        def _repr_term(self, term):
    17022117            """
    17032118            TESTS::
    17042119
    1705                 sage: F = CombinatorialFreeModule(ZZ, [1,2,3])
    1706                 sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4])
     2120                sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix="F")
     2121                sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix="G")
    17072122                sage: f =   F.monomial(1) + 2 * F.monomial(2)
    17082123                sage: g = 2*G.monomial(3) +     G.monomial(4)
    17092124                sage: tensor([f, g]) # indirect doctest
    1710                 2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4]
     2125                2*F[1] # G[3] + F[1] # G[4] + 4*F[2] # G[3] + 2*F[2] # G[4]
    17112126            """
    17122127            from sage.categories.tensor import tensor
    1713             return tensor.symbol.join(module._repr_term(t) for (module, t) in zip(self._sets, term))
    1714 
    1715         # TODO: latex
     2128            if hasattr(self, "_print_options"):
     2129                symb = self._print_options['tensor_symbol']
     2130                if symb is None:
     2131                    symb = tensor.symbol
     2132            else:
     2133                symb = tensor.symbol
     2134            return symb.join(module._repr_term(t) for (module, t) in zip(self._sets, term))
     2135
     2136        def _latex_term(self, term):
     2137            """
     2138            TESTS::
     2139
     2140                sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='x')
     2141                sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix='y')
     2142                sage: f =   F.monomial(1) + 2 * F.monomial(2)
     2143                sage: g = 2*G.monomial(3) +     G.monomial(4)
     2144                sage: latex(tensor([f, g])) # indirect doctest
     2145                2x_{1} \otimes y_{3} + x_{1} \otimes y_{4} + 4x_{2} \otimes y_{3} + 2x_{2} \otimes y_{4}
     2146            """
     2147            symb = " \\otimes "
     2148            return symb.join(module._latex_term(t) for (module, t) in zip(self._sets, term))
    17162149
    17172150        @cached_method
    17182151        def tensor_constructor(self, modules):
  • sage/combinat/root_system/root_space.py

    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/combinat/root_system/root_space.py
    a b class RootSpace(ClearCacheOnPickle, Comb 
    3939        sage: r = RootSystem(['A',4]).root_lattice()
    4040        sage: r.simple_root(1)
    4141        alpha[1]
     42        sage: latex(r.simple_root(1))
     43        \alpha_{1}
    4244
    4345    """
    4446
    class RootSpace(ClearCacheOnPickle, Comb 
    5254        """
    5355        self.root_system = root_system
    5456        basis_name = "alphacheck" if root_system.dual_side else "alpha"
     57        basis_name_latex  = "\\alpha^\\vee" if root_system.dual_side else "\\alpha"
    5558        CombinatorialFreeModule.__init__(self, base_ring,
    5659                                         root_system.index_set(),
    5760                                         element_class = RootSpaceElement,
    58                                          prefix=basis_name)
     61                                         prefix=basis_name,
     62                                         latex_prefix=basis_name_latex)
    5963
    6064    def _repr_(self):
    6165        """
  • sage/combinat/schubert_polynomial.py

    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/combinat/schubert_polynomial.py
    a b class SchubertPolynomialRing_xbasis(Comb 
    184184            True
    185185        """
    186186        self._name = "Schubert polynomial ring with X basis"
    187         self._prefix = "X"
    188187        self._repr_option_bracket = False
    189188        self._one = permutation.Permutation([1])
    190189        CombinatorialAlgebra.__init__(self, R, cc = permutation.Permutations(), category = GradedAlgebrasWithBasis(R))
     190        self.print_options(prefix='X')
    191191
    192192    def _element_constructor_(self, x):
    193193        """
  • sage/combinat/symmetric_group_algebra.py

    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/combinat/symmetric_group_algebra.py
    a b class SymmetricGroupAlgebra_n(Combinator 
    101101        """
    102102        self.n = n
    103103        self._name = "Symmetric group algebra of order %s"%self.n
    104         CombinatorialFreeModule.__init__(self, R, permutation.Permutations(n), category = FiniteDimensionalAlgebrasWithBasis(R))
     104        CombinatorialFreeModule.__init__(self, R, permutation.Permutations(n), prefix='', latex_prefix='', category = FiniteDimensionalAlgebrasWithBasis(R))
    105105        # This is questionable, and won't be inherited properly
    106106        if n > 0:
    107107            S = SymmetricGroupAlgebra(R, n-1)
    108108            self.register_coercion(S.canonical_embedding(self))
    109109       
    110110    # _repr_ customization: output the basis element indexed by [1,2,3] as [1,2,3]
    111     _prefix = ""
    112111    _repr_option_bracket = False
    113112
    114113    @cached_method
    class HeckeAlgebraSymmetricGroup_generic 
    735734        self._q = q
    736735       
    737736        CombinatorialAlgebra.__init__(self, R)
     737        # _repr_ customization: output the basis element indexed by [1,2,3] as [1,2,3]
     738        self.print_options(prefix="")
    738739
    739     # _repr_ customization: output the basis element indexed by [1,2,3] as [1,2,3]
    740     _prefix = ""
    741740    _repr_option_bracket = False
    742741
    743742    def q(self):
    class HeckeAlgebraSymmetricGroup_t(Hecke 
    779778            sage: H3 == loads(dumps(H3))
    780779            True
    781780        """
    782         self._prefix = "T"
    783781        HeckeAlgebraSymmetricGroup_generic.__init__(self, R, n, q)
    784782        self._name += " on the T basis"
     783        self.print_options(prefix="T")
    785784       
    786785    def t_action_on_basis(self, perm, i):
    787786        """
  • sage/misc/misc.py

    diff -r 361a4ad7d52c -r 4a4d7a0ac621 sage/misc/misc.py
    a b def coeff_repr(c, is_latex=False): 
    669669        else:
    670670            return "(%s)"%s
    671671    return s
    672        
    673 def repr_lincomb(symbols, coeffs, is_latex=False):
     672
     673def repr_lincomb(symbols, coeffs, is_latex=False, scalar_mult='*', latex_scalar_mult=None):
    674674    """
    675675    Compute a string representation of a linear combination of some
    676676    formal symbols.
    677677   
    678678    INPUT:
    679    
    680    
    681     -  ``symbols`` - list of symbols
    682    
    683     -  ``coeffs`` - list of coefficients of the symbols
    684    
    685    
     679
     680    - ``symbols`` -- list of symbols
     681    - ``coeffs`` -- list of coefficients of the symbols
     682    - ``scalar_mult`` -- (default:'*') string representing the multiplication
     683    - ``latex_scalar_mult`` -- (default:None) None or a string representing
     684      the multiplication in latex
     685
     686        - if None and ``scalar_mult`` is '*', the empty string '' is used
     687        - if None and ``scalar_mult`` is not '*', ``scalar_mult`` is used
     688        - otherwise: ``latex_scalar_mult`` is used
     689
    686690    OUTPUT:
    687    
    688    
     691
    689692    -  ``str`` - a string
    690    
    691    
    692     EXAMPLES::
    693    
     693
     694    EXAMPLES:
     695
     696    - examples without scalar_mult or latex_scalar_mult::
     697
    694698        sage: repr_lincomb(['a','b','c'], [1,2,3])
    695699        'a + 2*b + 3*c'
    696700        sage: repr_lincomb(['a','b','c'], [1,'2+3*x',3])
    def repr_lincomb(symbols, coeffs, is_lat 
    704708        sage: t = PolynomialRing(RationalField(),'t').gen()
    705709        sage: repr_lincomb(['a', 's', ''], [-t,t-2,t**2+2])
    706710        '-t*a + (t-2)*s + (t^2+2)'
     711
     712    - example for scalar_mult::
     713
     714        sage: repr_lincomb(['a','b','c'], [1,2,3], scalar_mult='**')
     715        'a + 2**b + 3**c'
     716
     717        sage: repr_lincomb(['a','b','c'], [1,2,3], scalar_mult='**')
     718        'a + 2**b + 3**c'
     719
     720    - examples for latex_scalar_mult::
     721
     722        sage: repr_lincomb(['a','b','c'], [1,2,3], is_latex=True)
     723        'a + 2b + 3c'
     724
     725        sage: repr_lincomb(['a','b','c'], [1,2,3], is_latex=True, scalar_mult='**')
     726        'a + 2**b + 3**c'
     727
     728        sage: repr_lincomb(['a','b','c'], [1,2,3], is_latex=True, latex_scalar_mult='*')
     729        'a + 2*b + 3*c'
     730
     731    - examples for scalar_mult and latex_scalar_mult::
     732
     733        sage: repr_lincomb(['a','b','c'], [1,2,3], latex_scalar_mult='*')
     734        'a + 2*b + 3*c'
     735        sage: repr_lincomb(['a','b','c'], [1,2,3], is_latex=True, latex_scalar_mult='*')
     736        'a + 2*b + 3*c'
     737
     738        sage: repr_lincomb(['a','b','c'], [1,2,3], scalar_mult='**', latex_scalar_mult='*')
     739        'a + 2**b + 3**c'
     740        sage: repr_lincomb(['a','b','c'], [1,2,3], is_latex=True, scalar_mult='**', latex_scalar_mult='*')
     741        'a + 2*b + 3*c'
    707742    """
    708743    s = ""
    709744    first = True
    710745    i = 0
    711746
     747    if is_latex:
     748        if latex_scalar_mult is None:
     749            if scalar_mult == '*':
     750                scalar_mult = ''
     751        else:
     752            scalar_mult = latex_scalar_mult
     753    l = len(scalar_mult)
     754
    712755    all_atomic = True
    713756    for c in coeffs:
    714757        if is_latex and hasattr(symbols[i], '_latex_'):
    def repr_lincomb(symbols, coeffs, is_lat 
    717760            b = str(symbols[i])
    718761        if c != 0:
    719762            coeff = coeff_repr(c, is_latex)
    720             if coeff == "1":
    721                 coeff = ""
    722             elif coeff == "-1":
    723                 coeff = "-"
    724             elif not is_latex and len(b) > 0:
    725                 b = "*" + b
    726             elif len(coeff) > 0 and b == "1":
    727                 b = ""
    728             if not first:
    729                 coeff = " + %s"%coeff
    730             else:
    731                 coeff = "%s"%coeff
     763            if coeff != "0":
     764                if coeff == "1":
     765                    coeff = ""
     766                elif coeff == "-1":
     767                    coeff = "-"
     768                elif len(b) > 0:
     769                    b = scalar_mult + b
     770                elif len(coeff) > 0 and b == "1":
     771                    b = ""
     772                if not first:
     773                    if len(coeff) > 0 and coeff[0] == "-":
     774                        coeff = " - %s"%coeff[1:]
     775                    else:
     776                        coeff = " + %s"%coeff
     777                else:
     778                    coeff = "%s"%coeff
    732779            s += "%s%s"%(coeff, b)
    733780            first = False
    734781        i += 1
    735782    if first:
    736         s = "0"
    737     s = s.replace("+ -","- ")
    738     if s[:2] == "1*":
    739         s = s[2:]
    740     elif s[:3] == "-1*":
    741         s = "-" + s[3:]
    742     s = s.replace(" 1*", " ")
    743     if s == "":
     783        return "0"
     784    elif s == "":
    744785        return "1"
    745     return s
     786    else:
     787        return s
     788
     789
    746790
    747791def strunc(s, n = 60):
    748792    """