How can I build a polynomial lambda function from an list of coefficients?

4.6k views Asked by At

I have an list of coefficients that correspond to a polynomial expression, ie: [1,2,0] corresponds to x^2 + 2x + 0. I would like to put an arbitrary length array of these coefficients into a lambda function.

Specifically, I am using mpmath and I have a list used for the polyval module that is:

polyval(ctx, coeffs, x, derivative=False)

Given coefficients and a number, polyval() evaluates the polynomial.

And I need to use the findroot module that takes a one dimensional function, ie:

findroot(lambda x: x**3 + 2*x + 1, 2)

How can I construct a lambda function out of a list of coefficients?

4

There are 4 answers

1
sth On

Do you really need a lambda function? Using a "normal" function should be easier:

def poly(coeffs):
   def calc(x):
      result = 0
      for c in coeffs:
         result = result*x + c
      return result
   return calc

findroot(poly([1,2,0]))

And using that polyval() function you mention, something like this should work:

findroot(lambda x: polyval(ctx, [1,2,0], x))

(For an appropriate ctx value)

0
ncoghlan On

sth's polyval() based approach looks like the best answer (since you already have access to that function), but if you wanted to implement your own equivalent, the function would look more like:

def poly(coeffs):
  def calc(x)
    result = 0
    for i,c in enumerate(reversed(coeffs)):
      result += c*(x**i)
    return result
  return calc

findroot(poly([1,2,0]))
1
Emmanuel On

Lambda expression is possible, thanks to the great Python base functions ! The 1st thing is to get couples of (coef, exponent) via the powerful zip function:

>>> l = [3, 0, 4, -9]
>>> range(len(l) - 1, -1, -1)
[3, 2, 1, 0]
>>> zip(l, range(len(l) - 1, -1, -1))
[(3, 3), (0, 2), (4, 1), (-9, 0)]

I use a reversed range since greater exponents are at the beginning of the list. Now a polynom is a sum... computed thanks to the sum function !

>>> f = lambda x: sum([coef*x**exp for (coef, exp) in zip(l, range(len(l) - 1, -1, -1))])
>>> f(3)
84

and indeed 3*3^3 + 0*3^2 + 4*3^1 - 9*3^0 = 3*27 + 0 + 4*3 - 9*1 = 81 + 12 - 9 = 84. This expression of f is correct for all list of coefs l whatever its length, thanks to the use of len(l).

1
Sven Marnach On

If you really want a lambda expression, the easiset I can think of is using reduce():

coeffs = [1, 2, 0]
f = lambda x: reduce(lambda y, a: x*y + a, coeffs, 0.0)
findroot(f, 2)

Since this is also tagged numpy, you could also use numpy.poly1d:

coeffs = [1, 2, 0]
f = numpy.poly1d(coeffs)
findroot(f, 2)