# How can I optimize this short code?

I wrote two versions of this code which have similar performances. I'd like to know if it is possible to further optimize this code:

g = 0.01;
alfa[n_, t_] := g*t*Sqrt[n + 1];
beta[n_, t_, pe_] :=pe*Cos[alfa[n, t]]^2 + (1 - pe)*Cos[alfa[n - 1, t]]^2;

vettore3[t_, pe_, N_] :=
Module[{pg, vec0, vec1, alfan, betan, sinalfan1, sinalfan2, cosalfan},
pg = 1 - pe;
alfan = Prepend[ParallelTable[alfa[n, t], {n, 0, N}], 0];
sinalfan1 = Drop[Sin[alfan]^2, 1];
sinalfan2 = Drop[Sin[alfan]^2, -1];
cosalfan = Cos[alfan]^2;
betan = pe*Drop[cosalfan, 1] + (1 - pe)*Drop[cosalfan, -1];
vec0 = Prepend[ConstantArray[0, N],1];
Monitor[For[i = 0, i < N, i++,
vec1 = betan*vec0 + Prepend[Drop[pe*sinalfan1*vec0, -1], 0] +
Drop[Append[pg*sinalfan2*vec0, 0], 1];
vec0 = vec1;], Framed[i]]; Return[vec1]]

vettore4[t_, pe_, N_] :=
Module[{pg, vec, alfan, betan, sinalfan1, sinalfan2, cosalfan},
\$RecursionLimit = Infinity;
pg = 1 - pe;
alfan = Prepend[ParallelTable[alfa[n, t], {n, 0, N}], 0];
sinalfan1 = Drop[Sin[alfan]^2, 1];
sinalfan2 = Drop[Sin[alfan]^2, -1];
cosalfan = Cos[alfan]^2;
betan = pe*Drop[cosalfan, 1] + (1 - pe)*Drop[cosalfan, -1];
vec[0] = Prepend[ConstantArray[0, N], 1];
Monitor[vec[n_] := vec[n] = betan*vec[n - 1]+
Prepend[Drop[pe*sinalfan1*vec[n - 1], -1], 0] +
Drop[Append[pg*sinalfan2*vec[n - 1], 0], 1], n];
Return[vec[N]]]


Both vettore3 and vettore4 perform in a similar way. Thanks for the help!

• It would help a lot I you could describe what the code does. Also, without a few example test cases are necessary to give relevant suggestions. – Lukas Lang Aug 20 '18 at 16:40
• I wrould recommend avoiding reshaping arrays and instead of recursion and for loops try using built in vector operation. – Johu Aug 20 '18 at 16:41

## 1 Answer

• Avoid recursion. It is slow in Mathematica. Better use Do or Fold.

In particular, it is not meaningful to use the memoization construnction for vec in vettore4: For computing vec[n] you need only to now vec[n-1] and afterwards, you can forget entirely about vec[n-1] afterwards. So, this memoization may need much more memory than needed to solve the problem; allocation and deallocation of memory -- even if done automatically by Mathematica -- needs is time.

• Avoid Monitor. It slows down execution.

• N is a built-in symbol. Just don't use it as variable.

• Use packed arrays as much a possible. In particular, make sure that all entries of an array are floating point numbers if in the end the array will contain at least one floating point number.

• Use vectorization of arithmetic operations as much as possible.

• Use operations that change the size of an array (e.g. Append and Drop etc.) as few as possible.

• Safe a lot of scalar-vector multiplications by precomputing quantities that can be reused (e.g. pesinalfan and pgsinalfan below).

Here is a version of vettore3a that is faster by a factor of 20.

vettore3a[t_, pe_, nn_] :=
Module[{pg, vec0, vec1, alfan, betan, cosalfan, pesinalfan, pgsinalfan},
pg = 1. - pe;
alfan = alfa[Range[-1., nn], N[t]];
cosalfan = Cos[alfan]^2;
With[{sinalfan = Subtract[1., cosalfan[[2 ;; -2]]]},
pesinalfan = pe sinalfan;
pgsinalfan = pg sinalfan;
];
betan = pe Rest[cosalfan] + (1. - pe) Most[cosalfan];
vec0 = ConstantArray[0., nn + 1];
vec0[[1]] = 1.;
Do[
vec1 = betan vec0;
vec1[[2 ;;]] += pesinalfan vec0[[;; -2]];
vec1[[;; -2]] += pgsinalfan vec0[[2 ;;]];
vec0 = vec1;
, {nn}];
vec0
]

• Thank you very much! – Knomes Aug 21 '18 at 8:09
• You're welcome. – Henrik Schumacher Aug 21 '18 at 8:16