]>
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')
82 We shouldn't overwrite variables in the global namespace::
84 sage: a = SymbolSequence('a')
91 The symbol at a given index should always be the same, even when
92 the symbols themselves are unnamed. We store the string
93 representation and compare because the output is unpredictable::
95 sage: a = SymbolSequence()
96 sage: a0str = str(a(0))
97 sage: str(a(0)) == a0str
100 Slices and single indices work when combined::
102 sage: a = SymbolSequence('a')
103 sage: a(3, slice(0,2))
105 sage: a(slice(0,2), 3)
110 def __init__(self
, name
=None, latex_name
=None, domain
=None):
111 # We store a dict of already-created symbols so that we don't
112 # recreate a symbol which already exists. This is especially
113 # helpful when using unnamed variables, if you want e.g. a(0)
114 # to return the same variable each time.
116 # The entry corresponding to None is the un-subscripted symbol
118 unsubscripted
= SR
.symbol(name
, latex_name
, domain
)
119 self
._symbols
= { None: unsubscripted }
122 self
._latex
_name
= latex_name
123 self
._domain
= domain
126 def _create_symbol_(self
, subscript
):
127 if self
._name
is None:
128 # Allow creating unnamed symbols, for consistency with
132 name
= '%s%d' % (self
._name
, subscript
)
134 if self
._latex
_name
is None:
137 latex_name
= r
'%s_{%d}' % (self
._latex
_name
, subscript
)
139 return SR
.symbol(name
, latex_name
, self
._domain
)
142 def _flatten_list_(self
, l
):
144 Recursively flatten the given list, allowing for some elements
150 if isinstance(item
, list):
151 result
+= self
._flatten
_list
_(item
)
158 def __getitem__(self
, key
):
159 if isinstance(key
, slice):
160 # We were given a slice. Clean up some of its properties
161 # first. The start/step are default for lists. We make
162 # copies of these because they're read-only.
163 (start
, step
) = (key
.start
, key
.step
)
167 # Would otherwise loop forever since our "length" is
169 raise ValueError('You must supply an terminal index')
173 # If the user asks for a slice, we'll be returning a list
175 return [ self(idx
) for idx
in range(start
, key
.stop
, step
) ]
180 def __call__(self
, *args
):
184 return self
._symbols
[None]
186 # This is safe after the len == 0 test.
188 args
= args
[1:] # Peel off the first arg, which we've called 'key'
190 if isinstance(key
, slice):
195 ss
= [ SymbolSequence(w
._repr
_(), w
._latex
_(), self
._domain
)
198 # This might be nested...
199 maybe_nested_list
= [ s(*args
) for s
in ss
]
200 return self
._flatten
_list
_(maybe_nested_list
)
203 # Cowardly refuse to create a variable named "a-1".
204 raise IndexError('Indices must be nonnegative')
207 # Base case, create a symbol and return it.
209 return self
._symbols
[key
]
211 self
._symbols
[key
] = self
._create
_symbol
_(key
)
212 return self
._symbols
[key
]
214 # If we're given more than one index, we want to create the
215 # subsequences recursively. For example, if we're asked for
216 # x(1,2), this is really SymbolSequence('x1')(2).
217 v
= self(key
) # x(1) -> x1
218 ss
= SymbolSequence(v
._repr
_(), v
._latex
_(), self
._domain
)