Reputation: 8376
Using sympy
I have two lists:
terms = [1, x, x*(x-1)]
coefficients = [-1,8.1,7]
I need to get the output:
-1+8.1*x+7*x(x-1)
I tried:
print (sum(a,x__i) for a, x__i in izip(terminos,coeficientes))
But I actually got a generator
, I tried such based on a working code:
def lag_l(xx, j):
x = Symbol("x")
parts = ((x - x_i) / (xx[j] - x_i) for i, x_i in enumerate(xx) if i != j)
return prod(parts)
def lag_L(xx, yy):
return sum(y*lag_l(xx, j) for j, y in enumerate(yy))
How can I complete this?
Upvotes: 2
Views: 1617
Reputation: 880807
In [159]: import sympy as sy
In [160]: from sympy.abc import x
In [161]: terms = [1, x, x*(x-1)]
In [162]: coefficients = [-1,8.1,7]
In [163]: sum(t*c for t, c in zip(terms, coefficients))
Out[163]: 7*x*(x - 1) + 8.1*x - 1
Interestingly, sum(term*coef for term, coef in zip(terms, coefficients))
is a bit faster than sum(coef * term for coef, term in zip(coefficients, terms))
:
In [182]: %timeit sum(term * coef for term, coef in zip(terms, coefficients))
10000 loops, best of 3: 34.1 µs per loop
In [183]: %timeit sum(coef * term for coef, term in zip(coefficients, terms))
10000 loops, best of 3: 38.7 µs per loop
The reason for this is because coef * term
calls coef.__mul__(term)
which then has to call term.__rmul__(coef)
since ints do not know how to multiply with sympy
Symbols. That extra function call makes coef * term
slower than term * coef
. (term * coef
calls term.__mul__(coef)
directly.)
Here are some more microbenchmarks:
In [178]: %timeit sum(IT.imap(op.mul, coefficients, terms))
10000 loops, best of 3: 38 µs per loop
In [186]: %timeit sum(IT.imap(op.mul, terms, coefficients))
10000 loops, best of 3: 32.8 µs per loop
In [179]: %timeit sum(map(op.mul, coefficients, terms))
10000 loops, best of 3: 38.5 µs per loop
In [188]: %timeit sum(map(op.mul, terms, coefficients))
10000 loops, best of 3: 33.3 µs per loop
Notice that the order of the terms
and coefficients
matters, but otherwise there is little time difference between these variants. For larger input, they also perform about the same:
In [203]: terms = [1, x, x*(x-1)] * 100000
In [204]: coefficients = [-1,8.1,7] * 100000
In [205]: %timeit sum(IT.imap(op.mul, terms, coefficients))
1 loops, best of 3: 3.63 s per loop
In [206]: %timeit sum(term * coef for term, coef in zip(terms, coefficients))
1 loops, best of 3: 3.63 s per loop
In [207]: %timeit sum(map(op.mul, terms, coefficients))
1 loops, best of 3: 3.48 s per loop
Also be aware that if you do not know (through profiling) that this operation is a critical bottleneck in your code, worrying about these slight differences is a waste of your time, since the time it takes to pre-optimize this stuff is far greater than the amount of time you save whilst the code is running. As they say, preoptimization is the root of all evil. I'm probably already guilty of that.
In Python2,
sum(IT.imap(op.mul, coefficients, terms))
uses the least memory.
In Python3, zip
and map
returns iterators, so
sum(t*c for t, c in zip(terms, coefficients))
sum(map(op.mul, coefficients, terms))
would also be memory-efficient.
Upvotes: 3
Reputation: 102039
Using a simple generator expression:
sum(coef * term for coef, term in zip(coefficients, terms))
Alternatively, instead of using zip
you want to use something similar to zip_with
:
def zip_with(operation, *iterables):
for elements in zip(*iterables):
yield operation(*elements)
And use it as:
import operator as op
sum(zip_with(op.mul, coefficients, terms))
As unutbu mentioned python already provide such a function in itertools.imap
under python2 and the built'-in's map
in python3, so you can avoid re-writing it and use either:
sum(itertools.imap(op.mul, coefficients, terms))
or
sum(map(op.mul, coefficients, terms) #python3
python 2 map
works slightly differently when you pass more than one sequence and the length differ.
Upvotes: 1