1
$\begingroup$

I am looking for an efficient way to apply Grad recursively to a scalar function. The code I have so far is in the structure below. I define the scalar function outside the loop, take its derivatives and apply it to a list of points, then I take another Grad apply it again to the list of points and so on.

In this case, the function has 7 variables in total, but I am trying to write the structure so that it works for more or less variables as well(and derivatives are taken with respect to a subset only). The problem is that the function is very slow to calculate (complicated expression depending on special functions) and very heavy on memory.

However, I don't need to store all the components of tensors with rank>= 2 or calculate all the components of the tensors in the list of points, because the successive acting of grad will return symmetric tensors.

How could I tell Mathematica this: When taking the grad, take only of a subset of components, and when applying the function to the list of data it only has to calculate some components of the tensor?

Edit1:Simple function, just to illustrate:

F = x1^2 +...+ x^7
list = Reap@Do[ 
               F = Function[{x1,...,x7},
  Evaluate[Grad[F[x1,...,x7],{x1,x2,x3,x4}] ] 
                                   ];
    Sow[ 
    Table[ F@@Obspoints[[i]], { i,1, Length@Obspoints}] 
       ],  
      {i,1,n}]//Last//Last```
$\endgroup$
4
  • $\begingroup$ "apply Grad recursively" - whenever you want to apply a function recursively, look at Nest (or NestList if you need the intermediate results as well). Additionally, please give us an example of a simple function and the output your would like to obtain. It would be easier than trying to reverse-engineer your code. $\endgroup$
    – MarcoB
    Jan 18 at 14:28
  • $\begingroup$ Both seem bad in terms of memory, they will just apply the gradient normally again and again in a straightforward manner. This is what I am trying to avoid, every time I take a gradient the size of the resulting expression increases by a factor of 10, roughly. I simplified the code in the question. $\endgroup$
    – Felipe
    Jan 18 at 14:56
  • $\begingroup$ Felipe, once again, please include a complete example of your function, your list of points, etc, and the desired output. $\endgroup$
    – MarcoB
    Jan 18 at 17:11
  • $\begingroup$ You can use F = Function[{x1,x2,x3,x4,x5,x6,x7}, Exp[- ( x1^2 + x2^2 + x3^2 + x4^2 +x5^2 + x6^2 + x7^2)] ] and ObsPoints = RandomReal[{0,1}, {100, 7}]. $\endgroup$
    – Felipe
    Jan 18 at 17:33

1 Answer 1

1
$\begingroup$

In case someone else finds the same problem, there is at least one solution. If you define a gradient which has the following property(latex notation): $\partial_i T_{jkp} = V_{jkpi}$ and $V_{jkpi} = 0$ if i < p, then it is easy to see that $\partial_{i_n}...\partial_{i_1} V_{j} = T_{j i_1 ... i_n}$, where the only non-zero components of T are those for which $j <= i_1 <= i_2 ... <= i_n $. These can always be taken to be the independent components of a totally symmetric tensor. About how to implement this modified Grad I am not sure the way I did is the most efficient one. Assuming F[x1,...,x7]:

dummy = { {x1,...,x7}, {s1,x2,...,x7}, {s1,s2,x3,...,x7}, ..., {s1,...,s6,x7}}
gradmodified = Grad[#1, dummy[[#2]] ]&
Do[ F = Function[{x1,...,x7},
 Evaluate[ MapIndexed[ gradmodified[#1, Last[#2] ]&, F[x1,...,x7], {i} ] ] ], 
{i,1,n} ]

I introduce the variables "si" just to give zero components for the gradient. This assumes that F is initially a vector and the Do loop constructs higher order tensors. The level specification {i} assures that you are always applying the grad to the innermost list. The arrays generated in this way have the correct dimensions, can be normally applied to points and carry only the independent components of the symmetric tensor. After applying the function to a list of points, to reconstruct the result into a symmetric array I used the SymmetrizedArray function. This function requires a list of the independent components of the resulting symmetric tensor, which you can generate with the SymmetrizedIndependentComponents function. This saved me a good deal of time and memory in generating higher order tensors.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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