2010/2/21 Øyvind Jensen <jensen.oyv...@gmail.com>:
> The keyword pretty_indices used to be boolean, but is now a dict of lists
> containing letters to label the new dummy indices.  This allows the user much
> better control over the resulting expression.
>
> Docstring and doctests updated accordingly.
> ---
>  sympy/physics/secondquant.py |  104 
> +++++++++++++++++++++++++++---------------
>  1 files changed, 67 insertions(+), 37 deletions(-)
>
> diff --git a/sympy/physics/secondquant.py b/sympy/physics/secondquant.py
> index 6a5fa60..9285f83 100644
> --- a/sympy/physics/secondquant.py
> +++ b/sympy/physics/secondquant.py
> @@ -2541,7 +2541,7 @@ def _substitute(expr, ordered_dummies, arg_iterator, 
> **require):
>     return result
>
>
> -def substitute_dummies(expr, new_indices=False, reverse_order=True, 
> pretty_indices=True):
> +def substitute_dummies(expr, new_indices=False, reverse_order=True, 
> pretty_indices={}):
>     """
>     Collect terms by substitution of dummy variables.
>
> @@ -2551,19 +2551,22 @@ def substitute_dummies(expr, new_indices=False, 
> reverse_order=True, pretty_indic
>     The idea is to substitute all dummy variables consistently depending on
>     position in the term.  For each term, we collect a sequence of all dummy
>     variables, where the order is determined by index position.  These indices
> -    are then substituted consistently in each term.  E.g.
> +    are then substituted consistently in each term.
> +
> +    Examples
> +    ========
>
>     >>> from sympy import symbols, Function
>     >>> from sympy.physics.secondquant import substitute_dummies
> -    >>> a,b = symbols('ab',dummy=True)
> -    >>> c,d = symbols('cd',dummy=True)
> +    >>> a,b,c,d = symbols('abcd',dummy=True, above_fermi=True)
> +    >>> i,j = symbols('ij',dummy=True, below_fermi=True)
>     >>> f = Function('f')
>
>     >>> expr = f(a,b) + f(c,d); expr
>     f(_a, _b) + f(_c, _d)
>
> -    Since a, b, c and d are summation indices, this can be simplified to a
> -    single summation term with a factor 2
> +    Since a, b, c and d are equivalent summation indices, the expression can 
> be
> +    simplified to a single term (for which the dummy indices are still 
> summed over)
>
>     >>> substitute_dummies(expr, reverse_order=False)
>     2*f(_a, _b)
> @@ -2577,37 +2580,67 @@ def substitute_dummies(expr, new_indices=False, 
> reverse_order=True, pretty_indic
>     >>> substitute_dummies(expr, reverse_order=True)
>     2*f(_b, _a)
>
> -    """
> +    Controlling output
> +    ==================
>
> -    # pretty_indices = True    # Prettier
> -    # pretty_indices = False   # Easier to debug
> +    By default the dummy symbols that are already present in the expression
> +    will be reused.  However, if new_indices=True, new dummies will be
> +    generated and inserted.
>
> +    The keyword 'pretty_indices' can be used to control this generation of 
> new
> +    symbols.
>
> -    if not pretty_indices:
> -        def _i(number):
> -            return 'i_'+str(number)
> -        def _a(number):
> -            return 'a_'+str(number)
> -        def _p(number):
> -            return 'p_'+str(number)
> +    By default the new dummies will be generated on the form i_1, i_2, a_1,
> +    etc.  If you supply a dictionary with key:value pairs in the form:
>
> +        { index_group: string_of_letters }
> +
> +    The letters will be used as labels for the new dummy symbols.  The
> +    index_groups must be one of 'above', 'below' or 'general'.
> +
> +    >>> expr = f(a,b,i,j)
> +    >>> my_dummies = { 'above':'st','below':'uv' }
> +    >>> substitute_dummies(expr, new_indices=True, pretty_indices=my_dummies)
> +    f(_t, _s, _v, _u)
> +
> +    If we run out of letters, or if there is no keyword for some index_group
> +    the default dummy generator will be used as a fallback:
> +
> +    >>> p,q = symbols('pq',dummy=True)  # general indices
> +    >>> expr = f(p,q)
> +    >>> substitute_dummies(expr, new_indices=True, pretty_indices=my_dummies)
> +    f(_p_1, _p_0)
> +
> +    """
> +
> +    # setup the replacing dummies
> +    if new_indices:
> +        letters_above  = pretty_indices.get('above',"")
> +        letters_below  = pretty_indices.get('below',"")
> +        letters_general= pretty_indices.get('general',"")
> +        len_above  = len(letters_above)
> +        len_below  = len(letters_below)
> +        len_general= len(letters_general)
>
> -    else:
>         def _i(number):
> -            if number<5:
> -                return "klmno"[number]
> -            else:
> -                return 'o_'+str(number-5)
> +            try:
> +                return letters_below[number]
> +            except IndexError:
> +                return 'i_'+str(number-len_below)
> +
>         def _a(number):
> -            if number<6:
> -                return "cdefgh"[number]
> -            else:
> -                return 'h_'+str(number-6)
> +            try:
> +                return letters_above[number]
> +            except IndexError:
> +                return 'a_'+str(number-len_above)
> +
>         def _p(number):
> -            if number<7:
> -                return "tuvwxyz"[number]
> -            else:
> -                return 'z_'+str(number-7)
> +            try:
> +                return letters_general[number]
> +            except IndexError:
> +                return 'p_'+str(number-len_general)
> +
> +
>
>     # reverse iterator for use in _get_dummies()
>     if reverse_order:
> @@ -2632,21 +2665,20 @@ def arg_iterator(seq):
>     dummies = [ d for d in expr.atoms() if isinstance(d,Dummy) ]
>     dummies.sort()
>
> +    # generate lists with the dummies we will insert
>     a = i = p = 0
>     for d in dummies:
>         assum = d.assumptions0
>         assum["dummy"]=True
> +
>         if assum.get("above_fermi"):
> -            sym = _a(a)
> -            a +=1
> +            if new_indices: sym = _a(a); a +=1
>             l1 = aboves
>         elif assum.get("below_fermi"):
> -            sym = _i(i)
> -            i +=1
> +            if new_indices: sym = _i(i); i +=1
>             l1 = belows
>         else:
> -            sym = _p(p)
> -            p +=1
> +            if new_indices: sym = _p(p); p +=1
>             l1 = generals
>
>         if new_indices:
> @@ -2655,8 +2687,6 @@ def arg_iterator(seq):
>             l1.append(d)
>
>
> -
> -
>     cases = (
>             ({'above_fermi':True}, aboves),
>             ({'below_fermi':True}, belows),
> --
> 1.6.5
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sympy-patches" group.
> To post to this group, send email to sympy-patc...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sympy-patches+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sympy-patches?hl=en.

I would prefer if this would use the new assumptions system. Or should
'above_fermi' etc. be tied to symbols? The rest of the patches looks
fine to me, assuming all tests pass.

Vinzent

-- 
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to sympy-patc...@googlegroups.com.
To unsubscribe from this group, send email to 
sympy-patches+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en.

Reply via email to