Reputation: 143
given this formula implement it in python
So for n = 3
x = []
y = []
for i in range(1, 4):
x.append(i)
for j in range(1, 4):
y.append(j**2)
total = 0
for i in range(len(x)):
for j in range(len(y)):
total = total + x[i] * y[j]
print(total)
this works. But say I wanted a third sigma notation such as
Which would be the exact same as above by just adding another loop k.
My question is if theres a way to generalize this in a function given n, the value inside (i.e. j^2 * i). I'm stumped on generalizing more loops
def manysums(n, L : i.e. [[1, 2,3], [1,4,9], [1, 8, 27]]):
pass
like above where the values inside the list totals the sum value
L = [[1, 2,3], [1,4,9], [1, 8, 27], [1,2,3]]
would be 4 sigma notation which would be 4 four loops. I'm wondering whether something like this can be generalized in a function
Upvotes: 3
Views: 1473
Reputation: 46869
my suggestion is:
from itertools import product
from operator import mul
from functools import reduce
n = 3
powers = zip(*((i, i**2, i**3) for i in range(1, n+1)))
s = sum(reduce(mul, p) for p in product(*powers))
and you could even generalize powers
to a function:
def powers(n, exponents):
return [[i**e for i in range(1, n+1)] for e in exponents]
powers(n=3, exponents=[2, 1, 3]))
# [[1, 4, 9], [1, 2, 3], [1, 8, 27]]
using product
with the repeat
option the sum can be written as:
from itertools import product
n = 3
s = sum(j**2 * i * k**3 for i, j, k in product(range(1, n+1), repeat=3)))
print(s)
this can easily be generalized to more variables.
if efficiency is an issue you can pre-calculate the powers and then sum them:
powers = list(zip(*((i, i**2, i**3) for i in range(1, n+1))))
# [(1, 2, 3), (1, 4, 9), (1, 8, 27)]
s = sum(p0 * p1 * p2 for p0, p1, p2 in product(*powers))
or, in order to keep the notation short if you have way more variables you can use functools.reduce
:
from operator import mul
from functools import reduce
s = sum(reduce(mul, p) for p in product(*powers))
Upvotes: 0
Reputation: 2387
Here's a solution without any additional imports, using recursion to make the amount of inner loops dynamic. It takes the inner formula as a function, of which the number of arguments is taken to determine the recursion depth needed.
def manysums(f, n):
depth = f.__code__.co_argcount # number of nested loops
def inner_loop(vals):
if len(vals) == depth - 1: # last (most-inner) loop?
return sum(f(*(vals + (i,))) for i in range(1,n+1))
else:
return sum(inner_loop(vals + (i,)) for i in range(1,n+1))
return inner_loop(())
Use like this:
f = lambda i, j, k : j**2 * i * k**3
manysums(f, 3)
# --> 3024
f = lambda i, j, k, l : j**2 * i * k**3 * l
manysums(f, 3)
# --> 18144
Upvotes: 0
Reputation: 19885
A solution taking advantage of numpy
:
import numpy as np
from functools import reduce
def multiple_sigma(n, exponents):
arrays = [np.arange(1, n + 1) ** exponent for exponent in exponents]
return reduce(np.multiply.outer, arrays).sum()
# j ** 2, i ** 1, k ** 3 for n in [1, 3]
multiple_sigma(n=3, exponents=[2, 1, 3])
Output:
3024
Upvotes: 1
Reputation: 2497
See itertools.product
. If you're interested in how it's implemented, there's a mock implementation in the link
Cartesian product of input iterables.
Roughly equivalent to nested for-loops in a generator expression. For example,
product(A, B)
returns the same as((x,y) for x in A for y in B)
.The nested loops cycle like an odometer with the rightmost element advancing on every iteration. This pattern creates a lexicographic ordering so that if the input’s iterables are sorted, the product tuples are emitted in sorted order.
from itertools import product
for i,j,k in product([1,2,3],[1,4,9],[1,8,27]):
print(j**2 * i * k**3)
Upvotes: 1