]>
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 `x0`, `x1`,...
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 coefficients for polynomials of arbitrary degree::
35 sage: a = SymbolSequence('a')
36 sage: p = sum([ a[i]*x^i for i in range(0,5)])
38 a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
40 Using a different latex name since 'lambda' is reserved::
42 sage: l = SymbolSequence('l', '\lambda')
48 Using multiple indices::
50 sage: a = SymbolSequence('a')
55 sage: [ a[i,j] for i in range(0,2) for j in range(0,2) ]
58 You can pass slice objects instead of integers to obtain a list of
61 sage: a = SymbolSequence('a')
65 This even works for the second, third, etc. indices::
67 sage: a = SymbolSequence('a')
73 We shouldn't overwrite variables in the global namespace::
75 sage: a = SymbolSequence('a')
82 The symbol at a given index should always be the same, even when
83 the symbols themselves are unnamed. We store the string
84 representation and compare because the output is unpredictable::
86 sage: a = SymbolSequence()
87 sage: a0str = str(a[0])
88 sage: str(a(0)) == a0str
91 Slices and single indices work when combined::
93 sage: a = SymbolSequence('a')
101 def __init__(self
, name
=None, latex_name
=None, domain
=None):
102 # We store a dict of already-created symbols so that we don't
103 # recreate a symbol which already exists. This is especially
104 # helpful when using unnamed variables, if you want e.g. a(0)
105 # to return the same variable each time.
107 # The entry corresponding to None is the un-subscripted symbol
109 unsubscripted
= SR
.symbol(name
, latex_name
, domain
)
110 self
._symbols
= { None: unsubscripted }
113 self
._latex
_name
= latex_name
114 self
._domain
= domain
117 def _create_symbol_(self
, subscript
):
118 if self
._name
is None:
119 # Allow creating unnamed symbols, for consistency with
123 name
= '%s%d' % (self
._name
, subscript
)
125 if self
._latex
_name
is None:
128 latex_name
= r
'%s_{%d}' % (self
._latex
_name
, subscript
)
130 return SR
.symbol(name
, latex_name
, self
._domain
)
133 def _flatten_list_(self
, l
):
135 Recursively flatten the given list, allowing for some elements
141 if isinstance(item
, list):
142 result
+= self
._flatten
_list
_(item
)
149 def __getitem__(self
, key
):
150 if isinstance(key
, tuple):
153 if isinstance(key
, slice):
154 # We were given a slice. Clean up some of its properties
155 # first. The start/step are default for lists. We make
156 # copies of these because they're read-only.
157 (start
, step
) = (key
.start
, key
.step
)
161 # Would otherwise loop forever since our "length" is
163 raise ValueError('You must supply an terminal index')
167 # If the user asks for a slice, we'll be returning a list
169 return [ self(idx
) for idx
in range(start
, key
.stop
, step
) ]
174 def __call__(self
, *args
):
178 return self
._symbols
[None]
180 # This is safe after the len == 0 test.
182 args
= args
[1:] # Peel off the first arg, which we've called 'key'
184 if isinstance(key
, slice):
189 ss
= [ SymbolSequence(w
._repr
_(), w
._latex
_(), self
._domain
)
192 # This might be nested...
193 maybe_nested_list
= [ s(*args
) for s
in ss
]
194 return self
._flatten
_list
_(maybe_nested_list
)
197 # Cowardly refuse to create a variable named "a-1".
198 raise IndexError('Indices must be nonnegative')
201 # Base case, create a symbol and return it.
203 return self
._symbols
[key
]
205 self
._symbols
[key
] = self
._create
_symbol
_(key
)
206 return self
._symbols
[key
]
208 # If we're given more than one index, we want to create the
209 # subsequences recursively. For example, if we're asked for
210 # x(1,2), this is really SymbolSequence('x1')(2).
211 v
= self(key
) # x(1) -> x1
212 ss
= SymbolSequence(v
._repr
_(), v
._latex
_(), self
._domain
)