Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

""" Helpers for randomized testing """ 

 

from __future__ import print_function, division 

 

from random import uniform 

import random 

 

from sympy.core.numbers import I 

from sympy.simplify.simplify import nsimplify 

from sympy.core.containers import Tuple 

from sympy.core.numbers import comp 

from sympy.core.symbol import Symbol 

from sympy.core.compatibility import is_sequence, as_int 

 

 

def random_complex_number(a=2, b=-1, c=3, d=1, rational=False): 

""" 

Return a random complex number. 

 

To reduce chance of hitting branch cuts or anything, we guarantee 

b <= Im z <= d, a <= Re z <= c 

""" 

A, B = uniform(a, c), uniform(b, d) 

if not rational: 

return A + I*B 

return nsimplify(A, rational=True) + I*nsimplify(B, rational=True) 

 

 

def verify_numerically(f, g, z=None, tol=1.0e-6, a=2, b=-1, c=3, d=1): 

""" 

Test numerically that f and g agree when evaluated in the argument z. 

 

If z is None, all symbols will be tested. This routine does not test 

whether there are Floats present with precision higher than 15 digits 

so if there are, your results may not be what you expect due to round- 

off errors. 

 

Examples 

======== 

 

>>> from sympy import sin, cos 

>>> from sympy.abc import x 

>>> from sympy.utilities.randtest import verify_numerically as tn 

>>> tn(sin(x)**2 + cos(x)**2, 1, x) 

True 

""" 

f, g, z = Tuple(f, g, z) 

z = [z] if isinstance(z, Symbol) else (f.free_symbols | g.free_symbols) 

reps = list(zip(z, [random_complex_number(a, b, c, d) for zi in z])) 

z1 = f.subs(reps).n() 

z2 = g.subs(reps).n() 

return comp(z1, z2, tol) 

 

 

def test_derivative_numerically(f, z, tol=1.0e-6, a=2, b=-1, c=3, d=1): 

""" 

Test numerically that the symbolically computed derivative of f 

with respect to z is correct. 

 

This routine does not test whether there are Floats present with 

precision higher than 15 digits so if there are, your results may 

not be what you expect due to round-off errors. 

 

Examples 

======== 

 

>>> from sympy import sin 

>>> from sympy.abc import x 

>>> from sympy.utilities.randtest import test_derivative_numerically as td 

>>> td(sin(x), x) 

True 

""" 

from sympy.core.function import Derivative 

z0 = random_complex_number(a, b, c, d) 

f1 = f.diff(z).subs(z, z0) 

f2 = Derivative(f, z).doit_numerically(z0) 

return comp(f1.n(), f2.n(), tol) 

 

 

def _randrange(seed=None): 

"""Return a randrange generator. ``seed`` can be 

o None - return randomly seeded generator 

o int - return a generator seeded with the int 

o list - the values to be returned will be taken from the list 

in the order given; the provided list is not modified. 

 

Examples 

======== 

 

>>> from sympy.utilities.randtest import _randrange 

>>> rr = _randrange() 

>>> rr(1000) # doctest: +SKIP 

999 

>>> rr = _randrange(3) 

>>> rr(1000) # doctest: +SKIP 

238 

>>> rr = _randrange([0, 5, 1, 3, 4]) 

>>> rr(3), rr(3) 

(0, 1) 

""" 

if seed is None: 

return random.randrange 

elif isinstance(seed, int): 

return random.Random(seed).randrange 

elif is_sequence(seed): 

seed = list(seed) # make a copy 

seed.reverse() 

 

def give(a, b=None, seq=seed): 

if b is None: 

a, b = 0, a 

a, b = as_int(a), as_int(b) 

w = b - a 

if w < 1: 

raise ValueError('_randrange got empty range') 

try: 

x = seq.pop() 

except AttributeError: 

raise ValueError('_randrange expects a list-like sequence') 

except IndexError: 

raise ValueError('_randrange sequence was too short') 

if a <= x < b: 

return x 

else: 

return give(a, b, seq) 

return give 

else: 

raise ValueError('_randrange got an unexpected seed') 

 

 

def _randint(seed=None): 

"""Return a randint generator. ``seed`` can be 

o None - return randomly seeded generator 

o int - return a generator seeded with the int 

o list - the values to be returned will be taken from the list 

in the order given; the provided list is not modified. 

 

Examples 

======== 

 

>>> from sympy.utilities.randtest import _randint 

>>> ri = _randint() 

>>> ri(1, 1000) # doctest: +SKIP 

999 

>>> ri = _randint(3) 

>>> ri(1, 1000) # doctest: +SKIP 

238 

>>> ri = _randint([0, 5, 1, 2, 4]) 

>>> ri(1, 3), ri(1, 3) 

(1, 2) 

""" 

if seed is None: 

return random.randint 

elif isinstance(seed, int): 

return random.Random(seed).randint 

elif is_sequence(seed): 

seed = list(seed) # make a copy 

seed.reverse() 

 

def give(a, b, seq=seed): 

a, b = as_int(a), as_int(b) 

w = b - a 

if w < 0: 

raise ValueError('_randint got empty range') 

try: 

x = seq.pop() 

except AttributeError: 

raise ValueError('_randint expects a list-like sequence') 

except IndexError: 

raise ValueError('_randint sequence was too short') 

if a <= x <= b: 

return x 

else: 

return give(a, b, seq) 

return give 

else: 

raise ValueError('_randint got an unexpected seed')