Coverage for /usr/lib/python3/dist-packages/sympy/polys/polyfuncs.py: 15%
112 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""High-level polynomials manipulation functions. """
4from sympy.core import S, Basic, symbols, Dummy
5from sympy.polys.polyerrors import (
6 PolificationFailed, ComputationFailed,
7 MultivariatePolynomialError, OptionError)
8from sympy.polys.polyoptions import allowed_flags, build_options
9from sympy.polys.polytools import poly_from_expr, Poly
10from sympy.polys.specialpolys import (
11 symmetric_poly, interpolating_poly)
12from sympy.polys.rings import sring
13from sympy.utilities import numbered_symbols, take, public
15@public
16def symmetrize(F, *gens, **args):
17 r"""
18 Rewrite a polynomial in terms of elementary symmetric polynomials.
20 A symmetric polynomial is a multivariate polynomial that remains invariant
21 under any variable permutation, i.e., if `f = f(x_1, x_2, \dots, x_n)`,
22 then `f = f(x_{i_1}, x_{i_2}, \dots, x_{i_n})`, where
23 `(i_1, i_2, \dots, i_n)` is a permutation of `(1, 2, \dots, n)` (an
24 element of the group `S_n`).
26 Returns a tuple of symmetric polynomials ``(f1, f2, ..., fn)`` such that
27 ``f = f1 + f2 + ... + fn``.
29 Examples
30 ========
32 >>> from sympy.polys.polyfuncs import symmetrize
33 >>> from sympy.abc import x, y
35 >>> symmetrize(x**2 + y**2)
36 (-2*x*y + (x + y)**2, 0)
38 >>> symmetrize(x**2 + y**2, formal=True)
39 (s1**2 - 2*s2, 0, [(s1, x + y), (s2, x*y)])
41 >>> symmetrize(x**2 - y**2)
42 (-2*x*y + (x + y)**2, -2*y**2)
44 >>> symmetrize(x**2 - y**2, formal=True)
45 (s1**2 - 2*s2, -2*y**2, [(s1, x + y), (s2, x*y)])
47 """
48 allowed_flags(args, ['formal', 'symbols'])
50 iterable = True
52 if not hasattr(F, '__iter__'):
53 iterable = False
54 F = [F]
56 R, F = sring(F, *gens, **args)
57 gens = R.symbols
59 opt = build_options(gens, args)
60 symbols = opt.symbols
61 symbols = [next(symbols) for i in range(len(gens))]
63 result = []
65 for f in F:
66 p, r, m = f.symmetrize()
67 result.append((p.as_expr(*symbols), r.as_expr(*gens)))
69 polys = [(s, g.as_expr()) for s, (_, g) in zip(symbols, m)]
71 if not opt.formal:
72 for i, (sym, non_sym) in enumerate(result):
73 result[i] = (sym.subs(polys), non_sym)
75 if not iterable:
76 result, = result
78 if not opt.formal:
79 return result
80 else:
81 if iterable:
82 return result, polys
83 else:
84 return result + (polys,)
87@public
88def horner(f, *gens, **args):
89 """
90 Rewrite a polynomial in Horner form.
92 Among other applications, evaluation of a polynomial at a point is optimal
93 when it is applied using the Horner scheme ([1]).
95 Examples
96 ========
98 >>> from sympy.polys.polyfuncs import horner
99 >>> from sympy.abc import x, y, a, b, c, d, e
101 >>> horner(9*x**4 + 8*x**3 + 7*x**2 + 6*x + 5)
102 x*(x*(x*(9*x + 8) + 7) + 6) + 5
104 >>> horner(a*x**4 + b*x**3 + c*x**2 + d*x + e)
105 e + x*(d + x*(c + x*(a*x + b)))
107 >>> f = 4*x**2*y**2 + 2*x**2*y + 2*x*y**2 + x*y
109 >>> horner(f, wrt=x)
110 x*(x*y*(4*y + 2) + y*(2*y + 1))
112 >>> horner(f, wrt=y)
113 y*(x*y*(4*x + 2) + x*(2*x + 1))
115 References
116 ==========
117 [1] - https://en.wikipedia.org/wiki/Horner_scheme
119 """
120 allowed_flags(args, [])
122 try:
123 F, opt = poly_from_expr(f, *gens, **args)
124 except PolificationFailed as exc:
125 return exc.expr
127 form, gen = S.Zero, F.gen
129 if F.is_univariate:
130 for coeff in F.all_coeffs():
131 form = form*gen + coeff
132 else:
133 F, gens = Poly(F, gen), gens[1:]
135 for coeff in F.all_coeffs():
136 form = form*gen + horner(coeff, *gens, **args)
138 return form
141@public
142def interpolate(data, x):
143 """
144 Construct an interpolating polynomial for the data points
145 evaluated at point x (which can be symbolic or numeric).
147 Examples
148 ========
150 >>> from sympy.polys.polyfuncs import interpolate
151 >>> from sympy.abc import a, b, x
153 A list is interpreted as though it were paired with a range starting
154 from 1:
156 >>> interpolate([1, 4, 9, 16], x)
157 x**2
159 This can be made explicit by giving a list of coordinates:
161 >>> interpolate([(1, 1), (2, 4), (3, 9)], x)
162 x**2
164 The (x, y) coordinates can also be given as keys and values of a
165 dictionary (and the points need not be equispaced):
167 >>> interpolate([(-1, 2), (1, 2), (2, 5)], x)
168 x**2 + 1
169 >>> interpolate({-1: 2, 1: 2, 2: 5}, x)
170 x**2 + 1
172 If the interpolation is going to be used only once then the
173 value of interest can be passed instead of passing a symbol:
175 >>> interpolate([1, 4, 9], 5)
176 25
178 Symbolic coordinates are also supported:
180 >>> [(i,interpolate((a, b), i)) for i in range(1, 4)]
181 [(1, a), (2, b), (3, -a + 2*b)]
182 """
183 n = len(data)
185 if isinstance(data, dict):
186 if x in data:
187 return S(data[x])
188 X, Y = list(zip(*data.items()))
189 else:
190 if isinstance(data[0], tuple):
191 X, Y = list(zip(*data))
192 if x in X:
193 return S(Y[X.index(x)])
194 else:
195 if x in range(1, n + 1):
196 return S(data[x - 1])
197 Y = list(data)
198 X = list(range(1, n + 1))
200 try:
201 return interpolating_poly(n, x, X, Y).expand()
202 except ValueError:
203 d = Dummy()
204 return interpolating_poly(n, d, X, Y).expand().subs(d, x)
207@public
208def rational_interpolate(data, degnum, X=symbols('x')):
209 """
210 Returns a rational interpolation, where the data points are element of
211 any integral domain.
213 The first argument contains the data (as a list of coordinates). The
214 ``degnum`` argument is the degree in the numerator of the rational
215 function. Setting it too high will decrease the maximal degree in the
216 denominator for the same amount of data.
218 Examples
219 ========
221 >>> from sympy.polys.polyfuncs import rational_interpolate
223 >>> data = [(1, -210), (2, -35), (3, 105), (4, 231), (5, 350), (6, 465)]
224 >>> rational_interpolate(data, 2)
225 (105*x**2 - 525)/(x + 1)
227 Values do not need to be integers:
229 >>> from sympy import sympify
230 >>> x = [1, 2, 3, 4, 5, 6]
231 >>> y = sympify("[-1, 0, 2, 22/5, 7, 68/7]")
232 >>> rational_interpolate(zip(x, y), 2)
233 (3*x**2 - 7*x + 2)/(x + 1)
235 The symbol for the variable can be changed if needed:
236 >>> from sympy import symbols
237 >>> z = symbols('z')
238 >>> rational_interpolate(data, 2, X=z)
239 (105*z**2 - 525)/(z + 1)
241 References
242 ==========
244 .. [1] Algorithm is adapted from:
245 http://axiom-wiki.newsynthesis.org/RationalInterpolation
247 """
248 from sympy.matrices.dense import ones
250 xdata, ydata = list(zip(*data))
252 k = len(xdata) - degnum - 1
253 if k < 0:
254 raise OptionError("Too few values for the required degree.")
255 c = ones(degnum + k + 1, degnum + k + 2)
256 for j in range(max(degnum, k)):
257 for i in range(degnum + k + 1):
258 c[i, j + 1] = c[i, j]*xdata[i]
259 for j in range(k + 1):
260 for i in range(degnum + k + 1):
261 c[i, degnum + k + 1 - j] = -c[i, k - j]*ydata[i]
262 r = c.nullspace()[0]
263 return (sum(r[i] * X**i for i in range(degnum + 1))
264 / sum(r[i + degnum + 1] * X**i for i in range(k + 1)))
267@public
268def viete(f, roots=None, *gens, **args):
269 """
270 Generate Viete's formulas for ``f``.
272 Examples
273 ========
275 >>> from sympy.polys.polyfuncs import viete
276 >>> from sympy import symbols
278 >>> x, a, b, c, r1, r2 = symbols('x,a:c,r1:3')
280 >>> viete(a*x**2 + b*x + c, [r1, r2], x)
281 [(r1 + r2, -b/a), (r1*r2, c/a)]
283 """
284 allowed_flags(args, [])
286 if isinstance(roots, Basic):
287 gens, roots = (roots,) + gens, None
289 try:
290 f, opt = poly_from_expr(f, *gens, **args)
291 except PolificationFailed as exc:
292 raise ComputationFailed('viete', 1, exc)
294 if f.is_multivariate:
295 raise MultivariatePolynomialError(
296 "multivariate polynomials are not allowed")
298 n = f.degree()
300 if n < 1:
301 raise ValueError(
302 "Cannot derive Viete's formulas for a constant polynomial")
304 if roots is None:
305 roots = numbered_symbols('r', start=1)
307 roots = take(roots, n)
309 if n != len(roots):
310 raise ValueError("required %s roots, got %s" % (n, len(roots)))
312 lc, coeffs = f.LC(), f.all_coeffs()
313 result, sign = [], -1
315 for i, coeff in enumerate(coeffs[1:]):
316 poly = symmetric_poly(i + 1, roots)
317 coeff = sign*(coeff/lc)
318 result.append((poly, coeff))
319 sign = -sign
321 return result