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

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

"""Module for SymPy containers 

 

(SymPy objects that store other SymPy objects) 

 

The containers implemented in this module are subclassed to Basic. 

They are supposed to work seamlessly within the SymPy framework. 

""" 

 

from __future__ import print_function, division 

 

from sympy.core.basic import Basic 

from sympy.core.compatibility import as_int, range 

from sympy.core.sympify import sympify, converter 

from sympy.utilities.iterables import iterable 

 

 

class Tuple(Basic): 

""" 

Wrapper around the builtin tuple object 

 

The Tuple is a subclass of Basic, so that it works well in the 

SymPy framework. The wrapped tuple is available as self.args, but 

you can also access elements or slices with [:] syntax. 

 

>>> from sympy import symbols 

>>> from sympy.core.containers import Tuple 

>>> a, b, c, d = symbols('a b c d') 

>>> Tuple(a, b, c)[1:] 

(b, c) 

>>> Tuple(a, b, c).subs(a, d) 

(d, b, c) 

 

""" 

 

def __new__(cls, *args): 

args = [ sympify(arg) for arg in args ] 

obj = Basic.__new__(cls, *args) 

return obj 

 

def __getitem__(self, i): 

if isinstance(i, slice): 

indices = i.indices(len(self)) 

return Tuple(*[self.args[j] for j in range(*indices)]) 

return self.args[i] 

 

def __len__(self): 

return len(self.args) 

 

def __contains__(self, item): 

return item in self.args 

 

def __iter__(self): 

return iter(self.args) 

 

def __add__(self, other): 

if isinstance(other, Tuple): 

return Tuple(*(self.args + other.args)) 

elif isinstance(other, tuple): 

return Tuple(*(self.args + other)) 

else: 

return NotImplemented 

 

def __radd__(self, other): 

if isinstance(other, Tuple): 

return Tuple(*(other.args + self.args)) 

elif isinstance(other, tuple): 

return Tuple(*(other + self.args)) 

else: 

return NotImplemented 

 

def __mul__(self, other): 

try: 

n = as_int(other) 

except ValueError: 

raise TypeError("Can't multiply sequence by non-integer of type '%s'" % type(other)) 

return self.func(*(self.args*n)) 

 

__rmul__ = __mul__ 

 

def __eq__(self, other): 

if isinstance(other, Basic): 

return super(Tuple, self).__eq__(other) 

return self.args == other 

 

def __ne__(self, other): 

if isinstance(other, Basic): 

return super(Tuple, self).__ne__(other) 

return self.args != other 

 

def __hash__(self): 

return hash(self.args) 

 

def _to_mpmath(self, prec): 

return tuple([a._to_mpmath(prec) for a in self.args]) 

 

def __lt__(self, other): 

return sympify(self.args < other.args) 

 

def __le__(self, other): 

return sympify(self.args <= other.args) 

 

# XXX: Basic defines count() as something different, so we can't 

# redefine it here. Originally this lead to cse() test failure. 

def tuple_count(self, value): 

"""T.count(value) -> integer -- return number of occurrences of value""" 

return self.args.count(value) 

 

def index(self, value, start=None, stop=None): 

"""T.index(value, [start, [stop]]) -> integer -- return first index of value. 

Raises ValueError if the value is not present.""" 

# XXX: One would expect: 

# 

# return self.args.index(value, start, stop) 

# 

# here. Any trouble with that? Yes: 

# 

# >>> (1,).index(1, None, None) 

# Traceback (most recent call last): 

# File "<stdin>", line 1, in <module> 

# TypeError: slice indices must be integers or None or have an __index__ method 

# 

# See: http://bugs.python.org/issue13340 

 

if start is None and stop is None: 

return self.args.index(value) 

elif stop is None: 

return self.args.index(value, start) 

else: 

return self.args.index(value, start, stop) 

 

converter[tuple] = lambda tup: Tuple(*tup) 

 

 

def tuple_wrapper(method): 

""" 

Decorator that converts any tuple in the function arguments into a Tuple. 

 

The motivation for this is to provide simple user interfaces. The user can 

call a function with regular tuples in the argument, and the wrapper will 

convert them to Tuples before handing them to the function. 

 

>>> from sympy.core.containers import tuple_wrapper 

>>> def f(*args): 

... return args 

>>> g = tuple_wrapper(f) 

 

The decorated function g sees only the Tuple argument: 

 

>>> g(0, (1, 2), 3) 

(0, (1, 2), 3) 

 

""" 

def wrap_tuples(*args, **kw_args): 

newargs = [] 

for arg in args: 

if type(arg) is tuple: 

newargs.append(Tuple(*arg)) 

else: 

newargs.append(arg) 

return method(*newargs, **kw_args) 

return wrap_tuples 

 

 

class Dict(Basic): 

""" 

Wrapper around the builtin dict object 

 

The Dict is a subclass of Basic, so that it works well in the 

SymPy framework. Because it is immutable, it may be included 

in sets, but its values must all be given at instantiation and 

cannot be changed afterwards. Otherwise it behaves identically 

to the Python dict. 

 

>>> from sympy.core.containers import Dict 

 

>>> D = Dict({1: 'one', 2: 'two'}) 

>>> for key in D: 

... if key == 1: 

... print('%s %s' % (key, D[key])) 

1 one 

 

The args are sympified so the 1 and 2 are Integers and the values 

are Symbols. Queries automatically sympify args so the following work: 

 

>>> 1 in D 

True 

>>> D.has('one') # searches keys and values 

True 

>>> 'one' in D # not in the keys 

False 

>>> D[1] 

one 

 

""" 

 

def __new__(cls, *args): 

if len(args) == 1 and isinstance(args[0], (dict, Dict)): 

items = [Tuple(k, v) for k, v in args[0].items()] 

elif iterable(args) and all(len(arg) == 2 for arg in args): 

items = [Tuple(k, v) for k, v in args] 

else: 

raise TypeError('Pass Dict args as Dict((k1, v1), ...) or Dict({k1: v1, ...})') 

elements = frozenset(items) 

obj = Basic.__new__(cls, elements) 

obj.elements = elements 

obj._dict = dict(items) # In case Tuple decides it wants to sympify 

return obj 

 

def __getitem__(self, key): 

"""x.__getitem__(y) <==> x[y]""" 

return self._dict[sympify(key)] 

 

def __setitem__(self, key, value): 

raise NotImplementedError("SymPy Dicts are Immutable") 

 

@property 

def args(self): 

return tuple(self.elements) 

 

def items(self): 

'''D.items() -> list of D's (key, value) pairs, as 2-tuples''' 

return self._dict.items() 

 

def keys(self): 

'''D.keys() -> list of D's keys''' 

return self._dict.keys() 

 

def values(self): 

'''D.values() -> list of D's values''' 

return self._dict.values() 

 

def __iter__(self): 

'''x.__iter__() <==> iter(x)''' 

return iter(self._dict) 

 

def __len__(self): 

'''x.__len__() <==> len(x)''' 

return self._dict.__len__() 

 

def get(self, key, default=None): 

'''D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.''' 

return self._dict.get(sympify(key), default) 

 

def __contains__(self, key): 

'''D.__contains__(k) -> True if D has a key k, else False''' 

return sympify(key) in self._dict 

 

def __lt__(self, other): 

return sympify(self.args < other.args) 

 

@property 

def _sorted_args(self): 

from sympy.utilities import default_sort_key 

return tuple(sorted(self.args, key=default_sort_key))