]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/symbol_sequence.py
5 A callable object which imitates a function from ZZ^n to a
6 sequence with n subscripts.
10 - ``name`` -- The sequence name.
12 - ``latex_name`` -- An optional latex expression (string) to
13 use instead of `name` when converting the symbols to latex.
15 - ``domain`` -- A string representing the domain of the symbol,
16 either 'real', 'complex', or 'positive'.
20 A callable object returning symbolic expressions.
24 Create coefficients for polynomials of arbitrary degree::
26 sage: a = SymbolSequence('a')
27 sage: p = sum([ a(i)*x^i for i in range(0,5)])
29 a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
31 Using a different latex name since 'lambda' is reserved::
33 sage: l = SymbolSequence('l', '\lambda')
39 Using multiple indices::
41 sage: a = SymbolSequence('a')
46 sage: [ a(i,j) for i in range(0,2) for j in range(0,2) ]
49 If no index is given, an unsubscripted symbol is returned::
51 sage: a = SymbolSequence('a')
55 You can pass slice objects instead of integers to obtain a list of
58 sage: a = SymbolSequence('a')
62 This even works for the second, third, etc. indices::
64 sage: a = SymbolSequence('a')
65 sage: a(slice(0,2), slice(0,2))
68 You can also index with the list index operator::
70 sage: a = SymbolSequence('a')
74 This allows you to retrieve one-dimensional slices easily::
76 sage: a = SymbolSequence('a')
80 If for whatever reason you prefer square brackets, the following
83 sage: a = SymbolSequence('a')
89 We shouldn't overwrite variables in the global namespace::
91 sage: a = SymbolSequence('a')
98 The symbol at a given index should always be the same, even when
99 the symbols themselves are unnamed. We store the string
100 representation and compare because the output is unpredictable::
102 sage: a = SymbolSequence()
103 sage: a0str = str(a(0))
104 sage: str(a(0)) == a0str
107 Slices and single indices work when combined::
109 sage: a = SymbolSequence('a')
110 sage: a(3, slice(0,2))
112 sage: a(slice(0,2), 3)
117 def __init__(self
, name
=None, latex_name
=None, domain
=None):
118 # We store a dict of already-created symbols so that we don't
119 # recreate a symbol which already exists. This is especially
120 # helpful when using unnamed variables, if you want e.g. a(0)
121 # to return the same variable each time.
123 # The entry corresponding to None is the un-subscripted symbol
125 unsubscripted
= SR
.symbol(name
, latex_name
, domain
)
126 self
._symbols
= { None: unsubscripted }
129 self
._latex
_name
= latex_name
130 self
._domain
= domain
133 def _create_symbol_(self
, subscript
):
134 if self
._name
is None:
135 # Allow creating unnamed symbols, for consistency with
139 name
= '%s%d' % (self
._name
, subscript
)
141 if self
._latex
_name
is None:
144 latex_name
= r
'%s_{%d}' % (self
._latex
_name
, subscript
)
146 return SR
.symbol(name
, latex_name
, self
._domain
)
149 def _flatten_list_(self
, l
):
151 Recursively flatten the given list, allowing for some elements
157 if isinstance(item
, list):
158 result
+= self
._flatten
_list
_(item
)
165 def __getitem__(self
, key
):
166 if isinstance(key
, tuple):
169 if isinstance(key
, slice):
170 # We were given a slice. Clean up some of its properties
171 # first. The start/step are default for lists. We make
172 # copies of these because they're read-only.
173 (start
, step
) = (key
.start
, key
.step
)
177 # Would otherwise loop forever since our "length" is
179 raise ValueError('You must supply an terminal index')
183 # If the user asks for a slice, we'll be returning a list
185 return [ self(idx
) for idx
in range(start
, key
.stop
, step
) ]
190 def __call__(self
, *args
):
194 return self
._symbols
[None]
196 # This is safe after the len == 0 test.
198 args
= args
[1:] # Peel off the first arg, which we've called 'key'
200 if isinstance(key
, slice):
205 ss
= [ SymbolSequence(w
._repr
_(), w
._latex
_(), self
._domain
)
208 # This might be nested...
209 maybe_nested_list
= [ s(*args
) for s
in ss
]
210 return self
._flatten
_list
_(maybe_nested_list
)
213 # Cowardly refuse to create a variable named "a-1".
214 raise IndexError('Indices must be nonnegative')
217 # Base case, create a symbol and return it.
219 return self
._symbols
[key
]
221 self
._symbols
[key
] = self
._create
_symbol
_(key
)
222 return self
._symbols
[key
]
224 # If we're given more than one index, we want to create the
225 # subsequences recursively. For example, if we're asked for
226 # x(1,2), this is really SymbolSequence('x1')(2).
227 v
= self(key
) # x(1) -> x1
228 ss
= SymbolSequence(v
._repr
_(), v
._latex
_(), self
._domain
)