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 best solutions below

1
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
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
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
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)