]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/symbol_sequence.py
5 An iterable object which acts like a sequence of symbolic
6 expressions (variables).
10 - ``name`` -- The sequence name. For example, if you name the
11 sequence `x`, the variables will be called `x_0`, `x_1`,...
13 - ``latex_name`` -- An optional latex expression (string) to
14 use instead of `name` when converting the symbols to latex.
16 - ``domain`` -- A string representing the domain of the symbol,
17 either 'real', 'complex', or 'positive'.
21 An iterable object containing symbolic expressions.
25 The simplest use case::
27 sage: a = SymbolSequence('a')
33 Create polynomials with symbolic coefficients of arbitrary
36 sage: a = SymbolSequence('a')
37 sage: p = sum([ a[i]*x^i for i in range(0,5)])
39 a_4*x^4 + a_3*x^3 + a_2*x^2 + a_1*x + a_0
41 Using a different latex name since 'lambda' is reserved::
43 sage: l = SymbolSequence('l', '\lambda')
49 Using multiple indices::
51 sage: a = SymbolSequence('a')
56 sage: [ a[i,j] for i in range(0,2) for j in range(0,2) ]
57 [a_0_0, a_0_1, a_1_0, a_1_1]
59 You can pass slices instead of integers to obtain a list of
62 sage: a = SymbolSequence('a')
66 This even works for the second, third, etc. indices::
68 sage: a = SymbolSequence('a')
70 [a_0_0, a_0_1, a_1_0, a_1_1]
74 We shouldn't overwrite variables in the global namespace::
76 sage: a = SymbolSequence('a')
83 The symbol at a given index should always be the same, even when
84 the symbols themselves are unnamed. We store the string
85 representation and compare because the output is unpredictable::
87 sage: a = SymbolSequence()
88 sage: a0str = str(a[0])
89 sage: str(a[0]) == a0str
92 Slices and single indices work when combined::
94 sage: a = SymbolSequence('a')
102 def __init__(self
, name
=None, latex_name
=None, domain
=None):
103 # We store a dict of already-created symbols so that we don't
104 # recreate a symbol which already exists. This is especially
105 # helpful when using unnamed variables, if you want e.g. a[0]
106 # to return the same variable each time.
110 self
._latex
_name
= latex_name
111 self
._domain
= domain
114 def _create_symbol_(self
, subscript
):
116 Return a symbol with the given subscript. Creates the
117 appropriate name and latex_name before delegating to
122 sage: a = SymbolSequence('a', 'alpha', 'real')
123 sage: a_1 = a._create_symbol_(1)
130 # Allow creating unnamed symbols, for consistency with
133 if self
._name
is not None:
134 name
= '%s_%d' % (self
._name
, subscript
)
137 if self
._latex
_name
is not None:
138 latex_name
= r
'%s_{%d}' % (self
._latex
_name
, subscript
)
140 return SR
.symbol(name
, latex_name
, self
._domain
)
143 def _flatten_list_(self
, l
):
145 Recursively flatten the given list, allowing for some elements
146 to be non-iterable. This is slow, but also works, which is
147 more than can be said about some of the snappier solutions of
152 sage: a = SymbolSequence('a')
153 sage: a._flatten_list_([1,2,3])
155 sage: a._flatten_list_([1,[2,3]])
157 sage: a._flatten_list_([1,[2,[3]]])
159 sage: a._flatten_list_([[[[[1,[2,[3]]]]]]])
166 if isinstance(item
, list):
167 result
+= self
._flatten
_list
_(item
)
174 def __getitem__(self
, key
):
176 This handles individual integer arguments, slices, and
177 tuples. It just hands off the real work to
178 self._subscript_foo_().
182 An integer argument::
184 sage: a = SymbolSequence('a')
185 sage: a.__getitem__(1)
190 sage: a = SymbolSequence('a')
191 sage: a.__getitem__((1,2))
196 sage: a = SymbolSequence('a')
197 sage: a.__getitem__(slice(1,4))
201 if isinstance(key
, tuple):
202 return self
._subscript
_tuple
_(key
)
204 if isinstance(key
, slice):
205 return self
._subscript
_slice
_(key
)
207 # This is the most common case so it would make sense to have
208 # this test first. But there are too many different "integer"
209 # classes that you have to check for.
210 return self
._subscript
_integer
_(key
)
213 def _subscript_integer_(self
, n
):
215 The subscript is a single integer, or something that acts like
220 sage: a = SymbolSequence('a')
221 sage: a._subscript_integer_(123)
226 # Cowardly refuse to create a variable named "a-1".
227 raise IndexError('Indices must be nonnegative')
230 return self
._symbols
[n
]
232 self
._symbols
[n
] = self
._create
_symbol
_(n
)
233 return self
._symbols
[n
]
236 def _subscript_slice_(self
, s
):
238 We were given a slice. Clean up some of its properties
239 first. The start/step are default for lists. We make
240 copies of these because they're read-only.
244 sage: a = SymbolSequence('a')
245 sage: a._subscript_slice_(slice(1,3))
249 (start
, step
) = (s
.start
, s
.step
)
253 # Would otherwise loop forever since our "length" is
255 raise ValueError('You must supply an terminal index')
259 # If the user asks for a slice, we'll be returning a list
261 return [ self
._subscript
_integer
_(idx
)
262 for idx
in range(start
, s
.stop
, step
) ]
266 def _subscript_tuple_(self
, args
):
268 When we have more than one level of subscripts, we pick off
269 the first one and generate the rest recursively.
275 sage: a = SymbolSequence('a')
276 sage: a._subscript_tuple_((1,8))
281 sage: a._subscript_tuple_(( (1,2), (3,(4,5,6)) ))
286 # We never call this method without an argument.
288 args
= args
[1:] # Peel off the first arg, which we've called 'key'
290 # We don't know the type of 'key', but __getitem__ will figure
291 # it out and dispatch properly.
294 # There was only one element left in the tuple.
297 # At this point, we know we were given at least a two-tuple.
298 # The symbols corresponding to the first entry are already
299 # computed, in 'v'. Here we recursively compute the symbols
300 # corresponding to the second coordinate, with the first
301 # coordinate(s) fixed.
302 if isinstance(key
, slice):
303 ss
= [ SymbolSequence(w
._repr
_(), w
._latex
_(), self
._domain
)
306 # This might be nested...
307 maybe_nested_list
= [ s
._subscript
_tuple
_(args
) for s
in ss
]
308 return self
._flatten
_list
_(maybe_nested_list
)
311 # If it's not a slice, it's an integer.
312 ss
= SymbolSequence(v
._repr
_(), v
._latex
_(), self
._domain
)
313 return ss
._subscript
_tuple
_(args
)