import heyoka as hy
x, y, z = hy.make_vars("x", "y", "z")
hy.sum([x, y, z])
(x + y + z)
The {func}heyoka.sum()
function takes in input a list of expressions and returns a multivariate summation of those expressions.
The other way is to use the binary +
operator:
x + y + z
((x + y) + z)
The binary operator is just a wrapper around the {func}heyoka.sum()
function. However, as you can also infer from the screen output, writing x + y + z
does not produce a ternary sum. Rather, it produces a binary sum in which the first term is another binary sum - that is, a nested sum. This is a consequence of how binary operators are parsed in Python.
Deeply nested binary sums can be less efficient than flat multivariate sums. Thus, if you need to build long summations, the recommended way is to prepare a list of terms and then invoke {func}heyoka.sum()
, rather the repeatedly invoking the +
or +=
operators.
import heyoka as hy
long_sum = hy.expression(0.)
# Suboptimal, avoid this if possible.
for i in range(10):
long_sum += hy.expression(f"x_{i}")
long_sum
(((((((((x_0 + x_1) + x_2) + x_3) + x_4) + x_5) + x_6) + x_7) + x_8) + x_9)
# Do this instead.
terms = [hy.expression(f"x_{i}") for i in range(10)]
long_sum = hy.sum(terms)
long_sum
(x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9)
{note}
The builtin {func}`sum()` function is just a wrapper around the binary ``+`` operator. Make sure to use {func}`heyoka.sum()` instead if you want to create a multivariate summation.
Everything that was said in this section about summations also applies to products (see the {func}heyoka.prod()
function).
from heyoka import prod, make_vars
x, y, z = make_vars("x", "y", "z")
prod([x, y, z])
(x * y * z)
Whereas previous versions of heyoka.py would automatically turn products into powers when appropriate, starting from heyoka.py 5.0.0 this automatic transformation is not applied any more.
Powers are in general more efficient than products or nested multiplications, as they can be automatically-differentiated faster and, during evaluation, heyoka.py takes care behind the scenes of transforming small integral/rational powers into repeated multiplications.
Thus, you should ensure that powers are created as powers:
# Don't do this!
x * x * x
((x * x) * x)
# Write this instead.
x**3
x**3.0000000000000000
This guideline is most important when squaring, as in this special case the automatic differentiation rule is particularly efficient.