Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have written a function (version 8) that takes as an input a list of indices such as {i,j,k} and outputs a fully symmetric tensor function containing $p_i$ and $g_{ij}$ ($g_{ij}$ is itself understood to be symmetric under $i\leftrightarrow j$).

myFunc[tensorList_?ListQ] := Module[{rank = Length[tensorList], perms, i, j, k, r},
  perms = Select[Permutations[tensorList, {rank}], Signature[#] == 1 &];

  Return[Sum[If[rank <= 1, 1, 2^(1 - r)/(r! (rank - 2 r)!)]*
    Factor[Sum[
      Product[Subscript[p, perms[[i]][[j]]],
        {j, 1, rank - 2 r}] 
      Product[Subscript[g, Times @@ perms[[i]][[2 k - 1 ;; 2 k]]],
        {k, rank/2 - r + 1, rank/2}], {i, 1, Max[1, rank!/2]}]] 
    f[2 r, rank], {r, 0, rank/2}]]
]

Example of usage:

myFunc[{i}] returns $f[0, 1]p_i$

myFunc[{i,j}] returns $f[2, 2]g_{ij}+f[0,2]p_i p_j$.

etc.

Problem: My function only works when all elements of input list have unique names like {i,j,k}. I don't know how to modify it so that it can accept lists like {i,j,j}.

for example, I'd like myFunc[{i,i}] to return $f[2,2]\,g_{i^2}+f[0,2]p_i p_i$.

and yes, I know that I'm multiplying indices of g, which I'd like to keep.

Any hints please? (and any pointers on ethics of function construction would be nice!)

share|improve this question
add comment

1 Answer 1

up vote 4 down vote accepted

To address your question on a high level only (how do I make my function to interpret the input {i, j, j} to contain distinct elements, like {i, j, k}), I recommend an approach similar to one that I made in one of my own questions:

myOtherFunc[list_] := 
  With[{tempList = Array[Unique[] &, Length@list]}, 
     myFunc[tempList] /. Thread[tempList -> list]]

This gives you the results you're looking for because it replaces your input symbols with temporary unique symbols (which are treated as such in your function), and then replaces them with the desired ones afterwards.

Regarding your function, since you asked for some pointers:

A bit of Part cleanup helps. Instead of [[i]][[j]] consider [[i, j]].

For symbols like perms, which you only define once then keep unchanged, it's better to use the faster With rather than Module. In fact, LetL makes more sense than nested Withs (the code for LetL is somewhere on this site, I swear).

Get rid of the Return.

Instead of using your If construct (whose static condition is needlessly evaluated for every Sum iteration), create a variable e (again using the ever so convenient LetL).

EDIT: scoping i, j, k, r is unnecessary if you use the myOtherFunc construct b/c it already replaces your variables with unique ones, effectively re-creating the Module.

Here's the improved myFunc:

myFunc[tensorList_?ListQ] := 
  LetL[{
    rank = Length[tensorList], 
    perms = Select[Permutations[tensorList, {rank}], Signature[#] == 1 &],
    e = If[rank <= 1, 1, 2^(1 - r)/(r! (rank - 2 r)!)]},
    Sum[
      e *
      Factor[Sum[
        Product[Subscript[p, perms[[i, j]]], {j, 1, rank - 2 r}] *
        Product[Subscript[g, Times @@ perms[[i, 2 k - 1 ;; 2 k]]], {k, rank/2 - r + 1, rank/2}],
        {i, 1, Max[1, rank!/2]}]] *
      f[2 r, rank],
    {r, 0, rank/2}]
  ]

EDIT 2: Just something that came to me as I was viewing myOtherFunc:

#[] & /@ ConstantArray[Unique, len]

Is functionally equivalent to

Array[Unique[] &, len]

But the former is 10x faster b/c it takes advantage of the controlled evaluation and is more memory efficient during computation.

share|improve this answer
    
This is excellent! Thanks! –  QuantumDot Jan 6 '13 at 6:15
    
@QuantumDot I added some stuff regarding your function. LetL is here. –  VF1 Jan 6 '13 at 6:23
    
Wonderful edit with very helpful comments! The reason I localized {i,j,k,r} is because otherwise I couldn't use i,j,... as elements of the input list. It seems to lead to conflicting variables. –  QuantumDot Jan 6 '13 at 6:34
    
@QuantumDot Ah! I see - I was only considering the case that an external value for i would influence the iteration, not the other way around. Even in this case, it's better to localize differently (I'll put up an edit) –  VF1 Jan 6 '13 at 6:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.