Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
restrepo
GitHub Repository: restrepo/ComputationalMethods
Path: blob/master/material/LagrangePolynomial.py
934 views
1
"""
2
From: https://gist.github.com/folkertdev/084c53887c49a6248839
3
A sympy-based Lagrange polynomial constructor.
4
5
Implementation of Lagrangian interpolating polynomial.
6
See:
7
8
def lagrangePolynomial(xs, ys):
9
10
Given two 1-D arrays `xs` and `ys,` returns the Lagrange interpolating
11
polynomial through the points ``(xs, ys)``
12
13
14
Given a set 1-D arrays of inputs and outputs, the lagrangePolynomial function
15
will construct an expression that for every input gives the corresponding output.
16
For intermediate values, the polynomial interpolates (giving varying results
17
based on the shape of your input).
18
19
The Lagrangian polynomials can be obtained explicitly with (see below):
20
21
def polyL(xs,j):
22
23
as sympy polynomial, and
24
25
def L(xs,j):
26
27
as Python functions.
28
29
30
This is useful when the result needs to be used outside of Python, because the
31
expression can easily be copied. To convert the expression to a python function
32
object, use sympy.lambdify.
33
"""
34
from sympy import symbols, expand, lambdify, solve_poly_system
35
#Python library for arithmetic with arbitrary precision
36
from mpmath import tan, e
37
38
import math
39
40
from operator import mul
41
from functools import reduce, lru_cache
42
from itertools import chain
43
44
# sympy symbols
45
x = symbols('x')
46
47
# convenience functions
48
product = lambda *args: reduce(mul, *(list(args) + [1]))
49
50
# test data
51
labels = [(-3/2), (-3/4), 0, 3/4, 3/2]
52
points = [math.tan(v) for v in labels]
53
54
# this product may be reusable (when creating many functions on the same domain)
55
# therefore, cache the result
56
@lru_cache(16)
57
def l(labels, j):
58
def gen(labels, j):
59
k = len(labels)
60
current = labels[j]
61
for m in labels:
62
if m == current:
63
continue
64
yield (x - m) / (current - m)
65
return expand(product(gen(labels, j)))
66
67
def polyL(xs,j):
68
'''
69
Lagrange polynomials as sympy polynomial
70
xs: the n+1 nodes of the intepolation polynomial in the Lagrange Form
71
j: Is the j-th Lagrange polinomial for the specific xs.
72
'''
73
xs=tuple(xs)
74
return l(xs,j)
75
76
def L(xs,j):
77
'''
78
Lagrange polynomials as python function
79
xs: the n+1 nodes of the intepolation polynomial in the Lagrange Form
80
j: Is the j-th Lagrange polinomial for the specific xs.
81
'''
82
return lambdify(x, polyL(xs,j) )
83
84
def lagrangePolynomial(xs, ys):
85
'''
86
Given two 1-D arrays `x` and `w,` returns the Lagrange interpolating
87
polynomial through the points ``(x, w)``.
88
89
'''
90
# based on https://en.wikipedia.org/wiki/Lagrange_polynomial#Example_1
91
k = len(xs)
92
total = 0
93
94
# use tuple, needs to be hashable to cache
95
xs = tuple(xs)
96
97
for j, current in enumerate(ys):
98
t = current * l(xs, j)
99
total += t
100
101
return total
102
103
104
105
106
def x_intersections(function, *args):
107
"Finds all x for which function(x) = 0"
108
# solve_poly_system seems more efficient than solve for larger expressions
109
return [var for var in chain.from_iterable(solve_poly_system([function], *args)) if (var.is_real)]
110
111
def x_scale(function, factor):
112
"Scale function on the x-axis"
113
return functions.subs(x, x / factor)
114
115
if __name__ == '__main__':
116
func = lagrangePolynomial(labels, points)
117
118
pyfunc = lambdify(x, func)
119
120
for a, b in zip(labels, points):
121
assert(pyfunc(a) - b < 1e-6)
122
123