Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top