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.

217 lines
6.3 KiB

6 months ago
  1. """
  2. When you need to use random numbers in SymPy library code, import from here
  3. so there is only one generator working for SymPy. Imports from here should
  4. behave the same as if they were being imported from Python's random module.
  5. But only the routines currently used in SymPy are included here. To use others
  6. import ``rng`` and access the method directly. For example, to capture the
  7. current state of the generator use ``rng.getstate()``.
  8. There is intentionally no Random to import from here. If you want
  9. to control the state of the generator, import ``seed`` and call it
  10. with or without an argument to set the state.
  11. Examples
  12. ========
  13. >>> from sympy.core.random import random, seed
  14. >>> assert random() < 1
  15. >>> seed(1); a = random()
  16. >>> b = random()
  17. >>> seed(1); c = random()
  18. >>> assert a == c
  19. >>> assert a != b # remote possibility this will fail
  20. """
  21. from sympy.utilities.iterables import is_sequence
  22. from sympy.utilities.misc import as_int
  23. import random as _random
  24. rng = _random.Random()
  25. choice = rng.choice
  26. random = rng.random
  27. randint = rng.randint
  28. randrange = rng.randrange
  29. seed = rng.seed
  30. shuffle = rng.shuffle
  31. uniform = rng.uniform
  32. def random_complex_number(a=2, b=-1, c=3, d=1, rational=False, tolerance=None):
  33. """
  34. Return a random complex number.
  35. To reduce chance of hitting branch cuts or anything, we guarantee
  36. b <= Im z <= d, a <= Re z <= c
  37. When rational is True, a rational approximation to a random number
  38. is obtained within specified tolerance, if any.
  39. """
  40. from sympy.core.numbers import I
  41. from sympy.simplify.simplify import nsimplify
  42. A, B = uniform(a, c), uniform(b, d)
  43. if not rational:
  44. return A + I*B
  45. return (nsimplify(A, rational=True, tolerance=tolerance) +
  46. I*nsimplify(B, rational=True, tolerance=tolerance))
  47. def verify_numerically(f, g, z=None, tol=1.0e-6, a=2, b=-1, c=3, d=1):
  48. """
  49. Test numerically that f and g agree when evaluated in the argument z.
  50. If z is None, all symbols will be tested. This routine does not test
  51. whether there are Floats present with precision higher than 15 digits
  52. so if there are, your results may not be what you expect due to round-
  53. off errors.
  54. Examples
  55. ========
  56. >>> from sympy import sin, cos
  57. >>> from sympy.abc import x
  58. >>> from sympy.core.random import verify_numerically as tn
  59. >>> tn(sin(x)**2 + cos(x)**2, 1, x)
  60. True
  61. """
  62. from sympy.core.symbol import Symbol
  63. from sympy.core.sympify import sympify
  64. from sympy.core.numbers import comp
  65. f, g = (sympify(i) for i in (f, g))
  66. if z is None:
  67. z = f.free_symbols | g.free_symbols
  68. elif isinstance(z, Symbol):
  69. z = [z]
  70. reps = list(zip(z, [random_complex_number(a, b, c, d) for _ in z]))
  71. z1 = f.subs(reps).n()
  72. z2 = g.subs(reps).n()
  73. return comp(z1, z2, tol)
  74. def test_derivative_numerically(f, z, tol=1.0e-6, a=2, b=-1, c=3, d=1):
  75. """
  76. Test numerically that the symbolically computed derivative of f
  77. with respect to z is correct.
  78. This routine does not test whether there are Floats present with
  79. precision higher than 15 digits so if there are, your results may
  80. not be what you expect due to round-off errors.
  81. Examples
  82. ========
  83. >>> from sympy import sin
  84. >>> from sympy.abc import x
  85. >>> from sympy.core.random import test_derivative_numerically as td
  86. >>> td(sin(x), x)
  87. True
  88. """
  89. from sympy.core.numbers import comp
  90. from sympy.core.function import Derivative
  91. z0 = random_complex_number(a, b, c, d)
  92. f1 = f.diff(z).subs(z, z0)
  93. f2 = Derivative(f, z).doit_numerically(z0)
  94. return comp(f1.n(), f2.n(), tol)
  95. def _randrange(seed=None):
  96. """Return a randrange generator.
  97. ``seed`` can be
  98. * None - return randomly seeded generator
  99. * int - return a generator seeded with the int
  100. * list - the values to be returned will be taken from the list
  101. in the order given; the provided list is not modified.
  102. Examples
  103. ========
  104. >>> from sympy.core.random import _randrange
  105. >>> rr = _randrange()
  106. >>> rr(1000) # doctest: +SKIP
  107. 999
  108. >>> rr = _randrange(3)
  109. >>> rr(1000) # doctest: +SKIP
  110. 238
  111. >>> rr = _randrange([0, 5, 1, 3, 4])
  112. >>> rr(3), rr(3)
  113. (0, 1)
  114. """
  115. if seed is None:
  116. return randrange
  117. elif isinstance(seed, int):
  118. rng.seed(seed)
  119. return randrange
  120. elif is_sequence(seed):
  121. seed = list(seed) # make a copy
  122. seed.reverse()
  123. def give(a, b=None, seq=seed):
  124. if b is None:
  125. a, b = 0, a
  126. a, b = as_int(a), as_int(b)
  127. w = b - a
  128. if w < 1:
  129. raise ValueError('_randrange got empty range')
  130. try:
  131. x = seq.pop()
  132. except IndexError:
  133. raise ValueError('_randrange sequence was too short')
  134. if a <= x < b:
  135. return x
  136. else:
  137. return give(a, b, seq)
  138. return give
  139. else:
  140. raise ValueError('_randrange got an unexpected seed')
  141. def _randint(seed=None):
  142. """Return a randint generator.
  143. ``seed`` can be
  144. * None - return randomly seeded generator
  145. * int - return a generator seeded with the int
  146. * list - the values to be returned will be taken from the list
  147. in the order given; the provided list is not modified.
  148. Examples
  149. ========
  150. >>> from sympy.core.random import _randint
  151. >>> ri = _randint()
  152. >>> ri(1, 1000) # doctest: +SKIP
  153. 999
  154. >>> ri = _randint(3)
  155. >>> ri(1, 1000) # doctest: +SKIP
  156. 238
  157. >>> ri = _randint([0, 5, 1, 2, 4])
  158. >>> ri(1, 3), ri(1, 3)
  159. (1, 2)
  160. """
  161. if seed is None:
  162. return randint
  163. elif isinstance(seed, int):
  164. rng.seed(seed)
  165. return randint
  166. elif is_sequence(seed):
  167. seed = list(seed) # make a copy
  168. seed.reverse()
  169. def give(a, b, seq=seed):
  170. a, b = as_int(a), as_int(b)
  171. w = b - a
  172. if w < 0:
  173. raise ValueError('_randint got empty range')
  174. try:
  175. x = seq.pop()
  176. except IndexError:
  177. raise ValueError('_randint sequence was too short')
  178. if a <= x <= b:
  179. return x
  180. else:
  181. return give(a, b, seq)
  182. return give
  183. else:
  184. raise ValueError('_randint got an unexpected seed')