m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
11 KiB

6 months ago
  1. """Functions for generating interesting polynomials, e.g. for benchmarking. """
  2. from sympy.core import Add, Mul, Symbol, sympify, Dummy, symbols
  3. from sympy.core.containers import Tuple
  4. from sympy.core.singleton import S
  5. from sympy.functions.elementary.miscellaneous import sqrt
  6. from sympy.ntheory import nextprime
  7. from sympy.polys.densearith import (
  8. dmp_add_term, dmp_neg, dmp_mul, dmp_sqr
  9. )
  10. from sympy.polys.densebasic import (
  11. dmp_zero, dmp_one, dmp_ground,
  12. dup_from_raw_dict, dmp_raise, dup_random
  13. )
  14. from sympy.polys.domains import ZZ
  15. from sympy.polys.factortools import dup_zz_cyclotomic_poly
  16. from sympy.polys.polyclasses import DMP
  17. from sympy.polys.polytools import Poly, PurePoly
  18. from sympy.polys.polyutils import _analyze_gens
  19. from sympy.utilities import subsets, public, filldedent
  20. @public
  21. def swinnerton_dyer_poly(n, x=None, polys=False):
  22. """Generates n-th Swinnerton-Dyer polynomial in `x`.
  23. Parameters
  24. ----------
  25. n : int
  26. `n` decides the order of polynomial
  27. x : optional
  28. polys : bool, optional
  29. ``polys=True`` returns an expression, otherwise
  30. (default) returns an expression.
  31. """
  32. from .numberfields import minimal_polynomial
  33. if n <= 0:
  34. raise ValueError(
  35. "Cannot generate Swinnerton-Dyer polynomial of order %s" % n)
  36. if x is not None:
  37. sympify(x)
  38. else:
  39. x = Dummy('x')
  40. if n > 3:
  41. p = 2
  42. a = [sqrt(2)]
  43. for i in range(2, n + 1):
  44. p = nextprime(p)
  45. a.append(sqrt(p))
  46. return minimal_polynomial(Add(*a), x, polys=polys)
  47. if n == 1:
  48. ex = x**2 - 2
  49. elif n == 2:
  50. ex = x**4 - 10*x**2 + 1
  51. elif n == 3:
  52. ex = x**8 - 40*x**6 + 352*x**4 - 960*x**2 + 576
  53. return PurePoly(ex, x) if polys else ex
  54. @public
  55. def cyclotomic_poly(n, x=None, polys=False):
  56. """Generates cyclotomic polynomial of order `n` in `x`.
  57. Parameters
  58. ----------
  59. n : int
  60. `n` decides the order of polynomial
  61. x : optional
  62. polys : bool, optional
  63. ``polys=True`` returns an expression, otherwise
  64. (default) returns an expression.
  65. """
  66. if n <= 0:
  67. raise ValueError(
  68. "Cannot generate cyclotomic polynomial of order %s" % n)
  69. poly = DMP(dup_zz_cyclotomic_poly(int(n), ZZ), ZZ)
  70. if x is not None:
  71. poly = Poly.new(poly, x)
  72. else:
  73. poly = PurePoly.new(poly, Dummy('x'))
  74. return poly if polys else poly.as_expr()
  75. @public
  76. def symmetric_poly(n, *gens, **args):
  77. """Generates symmetric polynomial of order `n`.
  78. Returns a Poly object when ``polys=True``, otherwise
  79. (default) returns an expression.
  80. """
  81. # TODO: use an explicit keyword argument
  82. gens = _analyze_gens(gens)
  83. if n < 0 or n > len(gens) or not gens:
  84. raise ValueError("Cannot generate symmetric polynomial of order %s for %s" % (n, gens))
  85. elif not n:
  86. poly = S.One
  87. else:
  88. poly = Add(*[Mul(*s) for s in subsets(gens, int(n))])
  89. if not args.get('polys', False):
  90. return poly
  91. else:
  92. return Poly(poly, *gens)
  93. @public
  94. def random_poly(x, n, inf, sup, domain=ZZ, polys=False):
  95. """Generates a polynomial of degree ``n`` with coefficients in
  96. ``[inf, sup]``.
  97. Parameters
  98. ----------
  99. x
  100. `x` is the independent term of polynomial
  101. n : int
  102. `n` decides the order of polynomial
  103. inf
  104. Lower limit of range in which coefficients lie
  105. sup
  106. Upper limit of range in which coefficients lie
  107. domain : optional
  108. Decides what ring the coefficients are supposed
  109. to belong. Default is set to Integers.
  110. polys : bool, optional
  111. ``polys=True`` returns an expression, otherwise
  112. (default) returns an expression.
  113. """
  114. poly = Poly(dup_random(n, inf, sup, domain), x, domain=domain)
  115. return poly if polys else poly.as_expr()
  116. @public
  117. def interpolating_poly(n, x, X='x', Y='y'):
  118. """Construct Lagrange interpolating polynomial for ``n``
  119. data points. If a sequence of values are given for ``X`` and ``Y``
  120. then the first ``n`` values will be used.
  121. """
  122. ok = getattr(x, 'free_symbols', None)
  123. if isinstance(X, str):
  124. X = symbols("%s:%s" % (X, n))
  125. elif ok and ok & Tuple(*X).free_symbols:
  126. ok = False
  127. if isinstance(Y, str):
  128. Y = symbols("%s:%s" % (Y, n))
  129. elif ok and ok & Tuple(*Y).free_symbols:
  130. ok = False
  131. if not ok:
  132. raise ValueError(filldedent('''
  133. Expecting symbol for x that does not appear in X or Y.
  134. Use `interpolate(list(zip(X, Y)), x)` instead.'''))
  135. coeffs = []
  136. numert = Mul(*[x - X[i] for i in range(n)])
  137. for i in range(n):
  138. numer = numert/(x - X[i])
  139. denom = Mul(*[(X[i] - X[j]) for j in range(n) if i != j])
  140. coeffs.append(numer/denom)
  141. return Add(*[coeff*y for coeff, y in zip(coeffs, Y)])
  142. def fateman_poly_F_1(n):
  143. """Fateman's GCD benchmark: trivial GCD """
  144. Y = [Symbol('y_' + str(i)) for i in range(n + 1)]
  145. y_0, y_1 = Y[0], Y[1]
  146. u = y_0 + Add(*[y for y in Y[1:]])
  147. v = y_0**2 + Add(*[y**2 for y in Y[1:]])
  148. F = ((u + 1)*(u + 2)).as_poly(*Y)
  149. G = ((v + 1)*(-3*y_1*y_0**2 + y_1**2 - 1)).as_poly(*Y)
  150. H = Poly(1, *Y)
  151. return F, G, H
  152. def dmp_fateman_poly_F_1(n, K):
  153. """Fateman's GCD benchmark: trivial GCD """
  154. u = [K(1), K(0)]
  155. for i in range(n):
  156. u = [dmp_one(i, K), u]
  157. v = [K(1), K(0), K(0)]
  158. for i in range(0, n):
  159. v = [dmp_one(i, K), dmp_zero(i), v]
  160. m = n - 1
  161. U = dmp_add_term(u, dmp_ground(K(1), m), 0, n, K)
  162. V = dmp_add_term(u, dmp_ground(K(2), m), 0, n, K)
  163. f = [[-K(3), K(0)], [], [K(1), K(0), -K(1)]]
  164. W = dmp_add_term(v, dmp_ground(K(1), m), 0, n, K)
  165. Y = dmp_raise(f, m, 1, K)
  166. F = dmp_mul(U, V, n, K)
  167. G = dmp_mul(W, Y, n, K)
  168. H = dmp_one(n, K)
  169. return F, G, H
  170. def fateman_poly_F_2(n):
  171. """Fateman's GCD benchmark: linearly dense quartic inputs """
  172. Y = [Symbol('y_' + str(i)) for i in range(n + 1)]
  173. y_0 = Y[0]
  174. u = Add(*[y for y in Y[1:]])
  175. H = Poly((y_0 + u + 1)**2, *Y)
  176. F = Poly((y_0 - u - 2)**2, *Y)
  177. G = Poly((y_0 + u + 2)**2, *Y)
  178. return H*F, H*G, H
  179. def dmp_fateman_poly_F_2(n, K):
  180. """Fateman's GCD benchmark: linearly dense quartic inputs """
  181. u = [K(1), K(0)]
  182. for i in range(n - 1):
  183. u = [dmp_one(i, K), u]
  184. m = n - 1
  185. v = dmp_add_term(u, dmp_ground(K(2), m - 1), 0, n, K)
  186. f = dmp_sqr([dmp_one(m, K), dmp_neg(v, m, K)], n, K)
  187. g = dmp_sqr([dmp_one(m, K), v], n, K)
  188. v = dmp_add_term(u, dmp_one(m - 1, K), 0, n, K)
  189. h = dmp_sqr([dmp_one(m, K), v], n, K)
  190. return dmp_mul(f, h, n, K), dmp_mul(g, h, n, K), h
  191. def fateman_poly_F_3(n):
  192. """Fateman's GCD benchmark: sparse inputs (deg f ~ vars f) """
  193. Y = [Symbol('y_' + str(i)) for i in range(n + 1)]
  194. y_0 = Y[0]
  195. u = Add(*[y**(n + 1) for y in Y[1:]])
  196. H = Poly((y_0**(n + 1) + u + 1)**2, *Y)
  197. F = Poly((y_0**(n + 1) - u - 2)**2, *Y)
  198. G = Poly((y_0**(n + 1) + u + 2)**2, *Y)
  199. return H*F, H*G, H
  200. def dmp_fateman_poly_F_3(n, K):
  201. """Fateman's GCD benchmark: sparse inputs (deg f ~ vars f) """
  202. u = dup_from_raw_dict({n + 1: K.one}, K)
  203. for i in range(0, n - 1):
  204. u = dmp_add_term([u], dmp_one(i, K), n + 1, i + 1, K)
  205. v = dmp_add_term(u, dmp_ground(K(2), n - 2), 0, n, K)
  206. f = dmp_sqr(
  207. dmp_add_term([dmp_neg(v, n - 1, K)], dmp_one(n - 1, K), n + 1, n, K), n, K)
  208. g = dmp_sqr(dmp_add_term([v], dmp_one(n - 1, K), n + 1, n, K), n, K)
  209. v = dmp_add_term(u, dmp_one(n - 2, K), 0, n - 1, K)
  210. h = dmp_sqr(dmp_add_term([v], dmp_one(n - 1, K), n + 1, n, K), n, K)
  211. return dmp_mul(f, h, n, K), dmp_mul(g, h, n, K), h
  212. # A few useful polynomials from Wang's paper ('78).
  213. from sympy.polys.rings import ring
  214. def _f_0():
  215. R, x, y, z = ring("x,y,z", ZZ)
  216. return x**2*y*z**2 + 2*x**2*y*z + 3*x**2*y + 2*x**2 + 3*x + 4*y**2*z**2 + 5*y**2*z + 6*y**2 + y*z**2 + 2*y*z + y + 1
  217. def _f_1():
  218. R, x, y, z = ring("x,y,z", ZZ)
  219. return x**3*y*z + x**2*y**2*z**2 + x**2*y**2 + 20*x**2*y*z + 30*x**2*y + x**2*z**2 + 10*x**2*z + x*y**3*z + 30*x*y**2*z + 20*x*y**2 + x*y*z**3 + 10*x*y*z**2 + x*y*z + 610*x*y + 20*x*z**2 + 230*x*z + 300*x + y**2*z**2 + 10*y**2*z + 30*y*z**2 + 320*y*z + 200*y + 600*z + 6000
  220. def _f_2():
  221. R, x, y, z = ring("x,y,z", ZZ)
  222. return x**5*y**3 + x**5*y**2*z + x**5*y*z**2 + x**5*z**3 + x**3*y**2 + x**3*y*z + 90*x**3*y + 90*x**3*z + x**2*y**2*z - 11*x**2*y**2 + x**2*z**3 - 11*x**2*z**2 + y*z - 11*y + 90*z - 990
  223. def _f_3():
  224. R, x, y, z = ring("x,y,z", ZZ)
  225. return x**5*y**2 + x**4*z**4 + x**4 + x**3*y**3*z + x**3*z + x**2*y**4 + x**2*y**3*z**3 + x**2*y*z**5 + x**2*y*z + x*y**2*z**4 + x*y**2 + x*y*z**7 + x*y*z**3 + x*y*z**2 + y**2*z + y*z**4
  226. def _f_4():
  227. R, x, y, z = ring("x,y,z", ZZ)
  228. return -x**9*y**8*z - x**8*y**5*z**3 - x**7*y**12*z**2 - 5*x**7*y**8 - x**6*y**9*z**4 + x**6*y**7*z**3 + 3*x**6*y**7*z - 5*x**6*y**5*z**2 - x**6*y**4*z**3 + x**5*y**4*z**5 + 3*x**5*y**4*z**3 - x**5*y*z**5 + x**4*y**11*z**4 + 3*x**4*y**11*z**2 - x**4*y**8*z**4 + 5*x**4*y**7*z**2 + 15*x**4*y**7 - 5*x**4*y**4*z**2 + x**3*y**8*z**6 + 3*x**3*y**8*z**4 - x**3*y**5*z**6 + 5*x**3*y**4*z**4 + 15*x**3*y**4*z**2 + x**3*y**3*z**5 + 3*x**3*y**3*z**3 - 5*x**3*y*z**4 + x**2*z**7 + 3*x**2*z**5 + x*y**7*z**6 + 3*x*y**7*z**4 + 5*x*y**3*z**4 + 15*x*y**3*z**2 + y**4*z**8 + 3*y**4*z**6 + 5*z**6 + 15*z**4
  229. def _f_5():
  230. R, x, y, z = ring("x,y,z", ZZ)
  231. return -x**3 - 3*x**2*y + 3*x**2*z - 3*x*y**2 + 6*x*y*z - 3*x*z**2 - y**3 + 3*y**2*z - 3*y*z**2 + z**3
  232. def _f_6():
  233. R, x, y, z, t = ring("x,y,z,t", ZZ)
  234. return 2115*x**4*y + 45*x**3*z**3*t**2 - 45*x**3*t**2 - 423*x*y**4 - 47*x*y**3 + 141*x*y*z**3 + 94*x*y*z*t - 9*y**3*z**3*t**2 + 9*y**3*t**2 - y**2*z**3*t**2 + y**2*t**2 + 3*z**6*t**2 + 2*z**4*t**3 - 3*z**3*t**2 - 2*z*t**3
  235. def _w_1():
  236. R, x, y, z = ring("x,y,z", ZZ)
  237. return 4*x**6*y**4*z**2 + 4*x**6*y**3*z**3 - 4*x**6*y**2*z**4 - 4*x**6*y*z**5 + x**5*y**4*z**3 + 12*x**5*y**3*z - x**5*y**2*z**5 + 12*x**5*y**2*z**2 - 12*x**5*y*z**3 - 12*x**5*z**4 + 8*x**4*y**4 + 6*x**4*y**3*z**2 + 8*x**4*y**3*z - 4*x**4*y**2*z**4 + 4*x**4*y**2*z**3 - 8*x**4*y**2*z**2 - 4*x**4*y*z**5 - 2*x**4*y*z**4 - 8*x**4*y*z**3 + 2*x**3*y**4*z + x**3*y**3*z**3 - x**3*y**2*z**5 - 2*x**3*y**2*z**3 + 9*x**3*y**2*z - 12*x**3*y*z**3 + 12*x**3*y*z**2 - 12*x**3*z**4 + 3*x**3*z**3 + 6*x**2*y**3 - 6*x**2*y**2*z**2 + 8*x**2*y**2*z - 2*x**2*y*z**4 - 8*x**2*y*z**3 + 2*x**2*y*z**2 + 2*x*y**3*z - 2*x*y**2*z**3 - 3*x*y*z + 3*x*z**3 - 2*y**2 + 2*y*z**2
  238. def _w_2():
  239. R, x, y = ring("x,y", ZZ)
  240. return 24*x**8*y**3 + 48*x**8*y**2 + 24*x**7*y**5 - 72*x**7*y**2 + 25*x**6*y**4 + 2*x**6*y**3 + 4*x**6*y + 8*x**6 + x**5*y**6 + x**5*y**3 - 12*x**5 + x**4*y**5 - x**4*y**4 - 2*x**4*y**3 + 292*x**4*y**2 - x**3*y**6 + 3*x**3*y**3 - x**2*y**5 + 12*x**2*y**3 + 48*x**2 - 12*y**3
  241. def f_polys():
  242. return _f_0(), _f_1(), _f_2(), _f_3(), _f_4(), _f_5(), _f_6()
  243. def w_polys():
  244. return _w_1(), _w_2()