Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/symbolic/ring.pyx
8817 views
1
"""
2
The symbolic ring
3
"""
4
###############################################################################
5
# Sage: Open Source Mathematical Software
6
# Copyright (C) 2008 William Stein <[email protected]>
7
# Copyright (C) 2008 Burcin Erocal <[email protected]>
8
# Distributed under the terms of the GNU General Public License (GPL),
9
# version 2 or any later version. The full text of the GPL is available at:
10
# http://www.gnu.org/licenses/
11
###############################################################################
12
13
include "sage/ext/stdsage.pxi"
14
include "sage/ext/cdefs.pxi"
15
16
#################################################################
17
# Initialize the library
18
#################################################################
19
20
#initialize_ginac()
21
22
from ginac cimport *
23
24
from sage.rings.integer cimport Integer
25
from sage.rings.real_mpfr import RealNumber
26
27
from sage.symbolic.expression cimport Expression, new_Expression_from_GEx, new_Expression_from_pyobject, is_Expression
28
29
from sage.libs.pari.pari_instance cimport PariInstance
30
from sage.misc.latex import latex_variable_name
31
from sage.structure.element cimport RingElement, Element
32
from sage.structure.parent_base import ParentWithBase
33
from sage.rings.ring cimport CommutativeRing
34
from sage.categories.morphism cimport Morphism
35
36
from sage.rings.all import RR, CC
37
38
pynac_symbol_registry = {}
39
40
cdef class SymbolicRing(CommutativeRing):
41
"""
42
Symbolic Ring, parent object for all symbolic expressions.
43
"""
44
def __init__(self):
45
"""
46
Initialize the Symbolic Ring.
47
48
EXAMPLES::
49
50
sage: sage.symbolic.ring.SymbolicRing()
51
Symbolic Ring
52
"""
53
CommutativeRing.__init__(self, self)
54
self._populate_coercion_lists_(convert_method_name='_symbolic_')
55
56
def __reduce__(self):
57
"""
58
EXAMPLES::
59
60
sage: loads(dumps(SR)) == SR # indirect doctest
61
True
62
"""
63
return the_SymbolicRing, tuple([])
64
65
def __hash__(self):
66
"""
67
EXAMPLES::
68
69
sage: hash(SR) #random
70
139682705593888
71
"""
72
return hash(SymbolicRing)
73
74
def _repr_(self):
75
"""
76
Return a string representation of self.
77
78
EXAMPLES::
79
80
sage: repr(SR)
81
'Symbolic Ring'
82
"""
83
return "Symbolic Ring"
84
85
def _latex_(self):
86
"""
87
Return latex representation of the symbolic ring.
88
89
EXAMPLES::
90
91
sage: latex(SR)
92
\text{SR}
93
sage: M = MatrixSpace(SR, 2); latex(M)
94
\mathrm{Mat}_{2\times 2}(\text{SR})
95
"""
96
return r'\text{SR}'
97
98
cpdef _coerce_map_from_(self, R):
99
"""
100
EXAMPLES::
101
102
sage: SR.coerce(int(2))
103
2
104
sage: SR.coerce(-infinity)
105
-Infinity
106
sage: SR.has_coerce_map_from(ZZ['t'])
107
True
108
sage: SR.has_coerce_map_from(ZZ['t,u,v'])
109
True
110
sage: SR.has_coerce_map_from(Frac(ZZ['t,u,v']))
111
True
112
sage: SR.has_coerce_map_from(GF(5)['t'])
113
True
114
sage: SR.has_coerce_map_from(SR['t'])
115
False
116
sage: SR.has_coerce_map_from(Integers(8))
117
True
118
sage: SR.has_coerce_map_from(GF(9, 'a'))
119
True
120
121
TESTS:
122
123
Check if arithmetic with bools work #9560::
124
125
sage: SR.has_coerce_map_from(bool)
126
True
127
sage: SR(5)*True; True*SR(5)
128
5
129
5
130
sage: SR(5)+True; True+SR(5)
131
6
132
6
133
sage: SR(5)-True
134
4
135
"""
136
if isinstance(R, type):
137
if R in [int, float, long, complex, bool]:
138
return True
139
140
if 'numpy' in R.__module__:
141
import numpy
142
basic_types = [numpy.float, numpy.float32, numpy.float64,
143
numpy.complex, numpy.complex64, numpy.complex128]
144
if hasattr(numpy, 'float128'):
145
basic_types += [numpy.float128, numpy.complex256]
146
if R in basic_types:
147
return NumpyToSRMorphism(R, self)
148
149
if 'sympy' in R.__module__:
150
from sympy.core.basic import Basic
151
if issubclass(R, Basic):
152
return UnderscoreSageMorphism(R, self)
153
154
return False
155
else:
156
from sage.rings.real_mpfr import mpfr_prec_min
157
158
from sage.rings.fraction_field import is_FractionField
159
from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
160
from sage.rings.real_mpfi import is_RealIntervalField
161
from sage.rings.complex_interval_field import is_ComplexIntervalField
162
from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
163
from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing
164
165
from sage.rings.all import (ComplexField,
166
RLF, CLF, AA, QQbar, InfinityRing,
167
is_FiniteField)
168
169
from sage.interfaces.maxima import Maxima
170
171
if ComplexField(mpfr_prec_min()).has_coerce_map_from(R):
172
# Anything with a coercion into any precision of CC
173
174
# In order to have coercion from SR to AA or QQbar,
175
# we disable coercion in the reverse direction.
176
# This makes the following work:
177
# sage: QQbar(sqrt(2)) + sqrt(3)
178
# 3.146264369941973?
179
return R not in (RLF, CLF, AA, QQbar)
180
elif is_PolynomialRing(R) or is_MPolynomialRing(R) or is_FractionField(R):
181
base = R.base_ring()
182
return base is not self and self.has_coerce_map_from(base)
183
elif (R is InfinityRing
184
or is_RealIntervalField(R) or is_ComplexIntervalField(R)
185
or is_IntegerModRing(R) or is_FiniteField(R)):
186
return True
187
elif isinstance(R, (Maxima, PariInstance)):
188
return False
189
190
def _element_constructor_(self, x):
191
"""
192
Coerce `x` into the symbolic expression ring SR.
193
194
EXAMPLES::
195
196
sage: a = SR(-3/4); a
197
-3/4
198
sage: type(a)
199
<type 'sage.symbolic.expression.Expression'>
200
sage: a.parent()
201
Symbolic Ring
202
sage: K.<a> = QuadraticField(-3)
203
sage: a + sin(x)
204
I*sqrt(3) + sin(x)
205
sage: x=var('x'); y0,y1=PolynomialRing(ZZ,2,'y').gens()
206
sage: x+y0/y1
207
x + y0/y1
208
sage: x.subs(x=y0/y1)
209
y0/y1
210
sage: x + long(1)
211
x + 1L
212
213
If `a` is already in the symbolic expression ring, coercing returns
214
`a` itself (not a copy)::
215
216
sage: a = SR(-3/4); a
217
-3/4
218
sage: SR(a) is a
219
True
220
221
A Python complex number::
222
223
sage: SR(complex(2,-3))
224
(2-3j)
225
226
TESTS::
227
228
sage: SR._coerce_(int(5))
229
5
230
sage: SR._coerce_(5)
231
5
232
sage: SR._coerce_(float(5))
233
5.0
234
sage: SR._coerce_(5.0)
235
5.00000000000000
236
237
An interval arithmetic number::
238
239
sage: SR._coerce_(RIF(pi))
240
3.141592653589794?
241
242
A number modulo 7::
243
244
sage: a = SR(Mod(3,7)); a
245
3
246
sage: a^2
247
2
248
249
sage: si = SR.coerce(I)
250
sage: si^2
251
-1
252
sage: bool(si == CC.0)
253
True
254
255
"""
256
cdef GEx exp
257
258
if is_Expression(x):
259
if (<Expression>x)._parent is self:
260
return x
261
else:
262
return new_Expression_from_GEx(self, (<Expression>x)._gobj)
263
elif hasattr(x, '_symbolic_'):
264
return x._symbolic_(self)
265
elif isinstance(x, str):
266
try:
267
from sage.calculus.calculus import symbolic_expression_from_string
268
return self(symbolic_expression_from_string(x))
269
except SyntaxError, err:
270
msg, s, pos = err.args
271
raise TypeError, "%s: %s !!! %s" % (msg, s[:pos], s[pos:])
272
273
from sage.rings.infinity import (infinity, minus_infinity,
274
unsigned_infinity)
275
276
if isinstance(x, (Integer, RealNumber, float, long, complex)):
277
GEx_construct_pyobject(exp, x)
278
elif isinstance(x, int):
279
GEx_construct_long(&exp, x)
280
elif x is infinity:
281
return new_Expression_from_GEx(self, g_Infinity)
282
elif x is minus_infinity:
283
return new_Expression_from_GEx(self, g_mInfinity)
284
elif x is unsigned_infinity:
285
return new_Expression_from_GEx(self, g_UnsignedInfinity)
286
elif isinstance(x, RingElement):
287
GEx_construct_pyobject(exp, x)
288
else:
289
raise TypeError
290
291
return new_Expression_from_GEx(self, exp)
292
293
def _force_pyobject(self, x):
294
"""
295
Wrap the given Python object in a symbolic expression even if it
296
cannot be coerced to the Symbolic Ring.
297
298
EXAMPLES::
299
300
sage: t = SR._force_pyobject([3,4,5]); t
301
[3, 4, 5]
302
sage: type(t)
303
<type 'sage.symbolic.expression.Expression'>
304
"""
305
cdef GEx exp
306
GEx_construct_pyobject(exp, x)
307
return new_Expression_from_GEx(self, exp)
308
309
def wild(self, unsigned int n=0):
310
"""
311
Return the n-th wild-card for pattern matching and substitution.
312
313
INPUT:
314
315
- ``n`` - a nonnegative integer
316
317
OUTPUT:
318
319
- `n^{th}` wildcard expression
320
321
EXAMPLES::
322
323
sage: x,y = var('x,y')
324
sage: w0 = SR.wild(0); w1 = SR.wild(1)
325
sage: pattern = sin(x)*w0*w1^2; pattern
326
$1^2*$0*sin(x)
327
sage: f = atan(sin(x)*3*x^2); f
328
arctan(3*x^2*sin(x))
329
sage: f.has(pattern)
330
True
331
sage: f.subs(pattern == x^2)
332
arctan(x^2)
333
"""
334
return new_Expression_from_GEx(self, g_wild(n))
335
336
def __cmp__(self, other):
337
"""
338
Compare two symbolic expression rings. They are equal if and only
339
if they have the same type. Otherwise their types are compared.
340
341
EXAMPLES::
342
343
sage: from sage.symbolic.ring import SymbolicRing
344
sage: cmp(SR, RR) #random
345
1
346
sage: cmp(RR, SymbolicRing()) #random
347
-1
348
sage: cmp(SR, SymbolicRing())
349
0
350
"""
351
return cmp(type(self), type(other))
352
353
def __contains__(self, x):
354
r"""
355
True if there is an element of the symbolic ring that is equal to x
356
under ``==``.
357
358
EXAMPLES:
359
360
The symbolic variable x is in the symbolic ring.::
361
362
sage: x.parent()
363
Symbolic Ring
364
sage: x in SR
365
True
366
367
2 is also in the symbolic ring since it is equal to something in
368
SR, even though 2's parent is not SR.
369
370
::
371
372
sage: 2 in SR
373
True
374
sage: parent(2)
375
Integer Ring
376
sage: 1/3 in SR
377
True
378
"""
379
try:
380
x2 = self(x)
381
return bool(x2 == x)
382
except TypeError:
383
return False
384
385
def characteristic(self):
386
"""
387
Return the characteristic of the symbolic ring, which is 0.
388
389
OUTPUT:
390
391
- a Sage integer
392
393
EXAMPLES::
394
395
sage: c = SR.characteristic(); c
396
0
397
sage: type(c)
398
<type 'sage.rings.integer.Integer'>
399
"""
400
return Integer(0)
401
402
def _an_element_(self):
403
"""
404
Return an element of the symbolic ring, which is used by the
405
coercion model.
406
407
EXAMPLES::
408
409
sage: SR._an_element_()
410
some_variable
411
"""
412
return self.var('some_variable')
413
414
def is_field(self, proof = True):
415
"""
416
Returns True, since the symbolic expression ring is (for the most
417
part) a field.
418
419
EXAMPLES::
420
421
sage: SR.is_field()
422
True
423
"""
424
return True
425
426
cpdef bint is_exact(self) except -2:
427
"""
428
Return False, because there are approximate elements in the
429
symbolic ring.
430
431
EXAMPLES::
432
433
sage: SR.is_exact()
434
False
435
436
Here is an inexact element.
437
438
::
439
440
sage: SR(1.9393)
441
1.93930000000000
442
"""
443
return False
444
445
def pi(self):
446
"""
447
EXAMPLES::
448
449
sage: SR.pi() is pi
450
True
451
"""
452
from sage.symbolic.constants import pi
453
return self(pi)
454
455
cpdef symbol(self, name=None, latex_name=None, domain=None):
456
"""
457
EXAMPLES::
458
459
sage: t0 = SR.symbol("t0")
460
sage: t0.conjugate()
461
conjugate(t0)
462
463
sage: t1 = SR.symbol("t1", domain='real')
464
sage: t1.conjugate()
465
t1
466
467
sage: t0.abs()
468
abs(t0)
469
470
sage: t0_2 = SR.symbol("t0", domain='positive')
471
sage: t0_2.abs()
472
t0
473
sage: bool(t0_2 == t0)
474
True
475
sage: t0.conjugate()
476
t0
477
478
sage: SR.symbol() # temporary variable
479
symbol...
480
"""
481
cdef GSymbol symb
482
cdef Expression e
483
484
# check if there is already a symbol with same name
485
e = pynac_symbol_registry.get(name)
486
487
# fast path to get an already existing variable
488
if e is not None:
489
if domain is None:
490
if latex_name is None:
491
return e
492
493
# get symbol
494
symb = ex_to_symbol(e._gobj)
495
if latex_name is not None:
496
symb.set_texname(latex_name)
497
if domain is not None:
498
symb.set_domain(sage_domain_to_ginac(domain))
499
GEx_construct_symbol(&e._gobj, symb)
500
501
return e
502
503
else: # initialize a new symbol
504
# Construct expression
505
e = <Expression>PY_NEW(Expression)
506
e._parent = SR
507
508
if name is None: # Check if we need a temporary anonymous new symbol
509
symb = ginac_new_symbol()
510
if domain is not None:
511
symb.set_domain(sage_domain_to_ginac(domain))
512
else:
513
if latex_name is None:
514
latex_name = latex_variable_name(name)
515
if domain is not None:
516
domain = sage_domain_to_ginac(domain)
517
else:
518
domain = domain_complex
519
symb = ginac_symbol(name, latex_name, domain)
520
pynac_symbol_registry[name] = e
521
522
GEx_construct_symbol(&e._gobj, symb)
523
return e
524
525
cpdef var(self, name, latex_name=None, domain=None):
526
"""
527
Return the symbolic variable defined by x as an element of the
528
symbolic ring.
529
530
EXAMPLES::
531
532
sage: zz = SR.var('zz'); zz
533
zz
534
sage: type(zz)
535
<type 'sage.symbolic.expression.Expression'>
536
sage: t = SR.var('theta2'); t
537
theta2
538
539
TESTS::
540
541
sage: var(' x y z ')
542
(x, y, z)
543
sage: var(' x , y , z ')
544
(x, y, z)
545
sage: var(' ')
546
Traceback (most recent call last):
547
...
548
ValueError: You need to specify the name of the new variable.
549
550
var(['x', 'y ', ' z '])
551
(x, y, z)
552
var(['x,y'])
553
Traceback (most recent call last):
554
...
555
ValueError: The name "x,y" is not a valid Python identifier.
556
"""
557
if is_Expression(name):
558
return name
559
if not isinstance(name, (basestring,list,tuple)):
560
name = repr(name)
561
562
if isinstance(name, (list,tuple)):
563
names_list = [s.strip() for s in name]
564
elif ',' in name:
565
names_list = [s.strip() for s in name.split(',' )]
566
elif ' ' in name:
567
names_list = [s.strip() for s in name.split()]
568
else:
569
names_list = [name]
570
571
for s in names_list:
572
if not isidentifier(s):
573
raise ValueError('The name "'+s+'" is not a valid Python identifier.')
574
575
if len(names_list) == 0:
576
raise ValueError('You need to specify the name of the new variable.')
577
if len(names_list) == 1:
578
return self.symbol(name, latex_name=latex_name, domain=domain)
579
if len(names_list) > 1:
580
if latex_name:
581
raise ValueError, "cannot specify latex_name for multiple symbol names"
582
return tuple([self.symbol(s, domain=domain) for s in names_list])
583
584
def _repr_element_(self, Expression x):
585
"""
586
Returns the string representation of the element x. This is
587
used so that subclasses of the SymbolicRing (such the a
588
CallableSymbolicExpressionRing) can provide their own
589
implementations of how to print Expressions.
590
591
EXAMPLES::
592
593
sage: SR._repr_element_(x+2)
594
'x + 2'
595
"""
596
return GEx_to_str(&x._gobj)
597
598
def _latex_element_(self, Expression x):
599
"""
600
Returns the standard LaTeX version of the expression *x*.
601
602
EXAMPLES::
603
604
sage: latex(sin(x+2))
605
\sin\left(x + 2\right)
606
sage: latex(var('theta') + 2)
607
\theta + 2
608
"""
609
return GEx_to_str_latex(&x._gobj)
610
611
def _call_element_(self, _the_element, *args, **kwds):
612
"""
613
EXAMPLES::
614
615
sage: x,y=var('x,y')
616
sage: f = x+y
617
sage: f.variables()
618
(x, y)
619
sage: f()
620
x + y
621
sage: f(3)
622
doctest:...: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)
623
See http://trac.sagemath.org/5930 for details.
624
y + 3
625
sage: f(x=3)
626
y + 3
627
sage: f(3,4)
628
7
629
sage: f(x=3,y=4)
630
7
631
sage: f(2,3,4)
632
Traceback (most recent call last):
633
...
634
ValueError: the number of arguments must be less than or equal to 2
635
sage: f(x=2,y=3,z=4)
636
5
637
638
::
639
640
sage: f({x:3})
641
y + 3
642
sage: f({x:3,y:4})
643
7
644
sage: f(x=3)
645
y + 3
646
sage: f(x=3,y=4)
647
7
648
649
::
650
651
sage: a = (2^(8/9))
652
sage: a(4)
653
Traceback (most recent call last):
654
...
655
ValueError: the number of arguments must be less than or equal to 0
656
657
658
Note that you make get unexpected results when calling
659
symbolic expressions and not explicitly giving the variables::
660
661
sage: f = function('Gamma', var('z'), var('w')); f
662
Gamma(z, w)
663
sage: f(2)
664
Gamma(z, 2)
665
sage: f(2,5)
666
Gamma(5, 2)
667
668
Thus, it is better to be explicit::
669
670
sage: f(z=2)
671
Gamma(2, w)
672
"""
673
if len(args) == 0:
674
d = None
675
elif len(args) == 1 and isinstance(args[0], dict):
676
d = args[0]
677
else:
678
from sage.misc.superseded import deprecation
679
vars = _the_element.operands()
680
deprecation(5930, "Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)")
681
d = {}
682
683
vars = _the_element.variables()
684
for i, arg in enumerate(args):
685
try:
686
d[ vars[i] ] = arg
687
except IndexError:
688
raise ValueError, "the number of arguments must be less than or equal to %s"%len(vars)
689
690
return _the_element.subs(d, **kwds)
691
692
SR = SymbolicRing()
693
694
cdef unsigned sage_domain_to_ginac(object domain) except +:
695
# convert the domain argument to something easy to parse
696
if domain is RR or domain is 'real':
697
return domain_real
698
elif domain is 'positive':
699
return domain_positive
700
elif domain is CC or domain is 'complex':
701
return domain_complex
702
else:
703
raise ValueError, "domain must be one of 'complex', 'real' or 'positive'"
704
705
cdef class NumpyToSRMorphism(Morphism):
706
def __init__(self, numpy_type, R):
707
"""
708
A Morphism which constructs Expressions from NumPy floats and
709
complexes by converting them to elements of either RDF or CDF.
710
711
EXAMPLES::
712
713
sage: import numpy
714
sage: from sage.symbolic.ring import NumpyToSRMorphism
715
sage: f = NumpyToSRMorphism(numpy.float64, SR)
716
sage: f(numpy.float64('2.0'))
717
2.0
718
sage: _.parent()
719
Symbolic Ring
720
"""
721
import sage.categories.homset
722
from sage.structure.parent import Set_PythonType
723
Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(numpy_type), R))
724
725
cpdef Element _call_(self, a):
726
"""
727
EXAMPLES:
728
729
This should be called when coercing or converting a NumPy
730
float or complex to the Symbolic Ring::
731
732
sage: import numpy
733
sage: SR(numpy.float64('2.0')).pyobject().parent()
734
Real Double Field
735
"""
736
from sage.rings.all import RDF, CDF
737
numpy_type = self._domain.object()
738
if 'complex' in numpy_type.__name__:
739
res = CDF(a)
740
else:
741
res = RDF(a)
742
743
return new_Expression_from_pyobject(self._codomain, res)
744
745
cdef class UnderscoreSageMorphism(Morphism):
746
def __init__(self, t, R):
747
"""
748
A Morphism which constructs Expressions from an arbitrary Python
749
object by calling the :meth:`_sage_` method on the object.
750
751
EXAMPLES::
752
753
sage: import sympy
754
sage: from sage.symbolic.ring import UnderscoreSageMorphism
755
sage: b = sympy.var('b')
756
sage: f = UnderscoreSageMorphism(type(b), SR)
757
sage: f(b)
758
b
759
sage: _.parent()
760
Symbolic Ring
761
"""
762
import sage.categories.homset
763
from sage.structure.parent import Set_PythonType
764
Morphism.__init__(self, sage.categories.homset.Hom(Set_PythonType(t), R))
765
766
cpdef Element _call_(self, a):
767
"""
768
EXAMPLES:
769
770
This should be called when coercing or converting a SymPy
771
object to the Symbolic Ring::
772
773
sage: import sympy
774
sage: b = sympy.var('b')
775
sage: bool(SR(b) == SR(b._sage_()))
776
True
777
"""
778
return self._codomain(a._sage_())
779
780
781
def the_SymbolicRing():
782
"""
783
Return the unique symbolic ring object.
784
785
(This is mainly used for unpickling.)
786
787
EXAMPLES::
788
789
sage: sage.symbolic.ring.the_SymbolicRing()
790
Symbolic Ring
791
sage: sage.symbolic.ring.the_SymbolicRing() is sage.symbolic.ring.the_SymbolicRing()
792
True
793
sage: sage.symbolic.ring.the_SymbolicRing() is SR
794
True
795
"""
796
return SR
797
798
def is_SymbolicExpressionRing(R):
799
"""
800
Returns True if *R* is the symbolic expression ring.
801
802
EXAMPLES::
803
804
sage: from sage.symbolic.ring import is_SymbolicExpressionRing
805
sage: is_SymbolicExpressionRing(ZZ)
806
False
807
sage: is_SymbolicExpressionRing(SR)
808
True
809
"""
810
return R is SR
811
812
def var(name, **kwds):
813
"""
814
EXAMPLES::
815
816
sage: from sage.symbolic.ring import var
817
sage: var("x y z")
818
(x, y, z)
819
sage: var("x,y,z")
820
(x, y, z)
821
sage: var("x , y , z")
822
(x, y, z)
823
sage: var("z")
824
z
825
826
TESTS:
827
828
These examples test that variables can only be made from
829
valid identifiers. See Trac 7496 (and 9724) for details::
830
831
sage: var(' ')
832
Traceback (most recent call last):
833
...
834
ValueError: You need to specify the name of the new variable.
835
sage: var('3')
836
Traceback (most recent call last):
837
...
838
ValueError: The name "3" is not a valid Python identifier.
839
"""
840
return SR.var(name, **kwds)
841
842
def is_SymbolicVariable(x):
843
"""
844
Returns True if x is a variable.
845
846
EXAMPLES::
847
848
sage: from sage.symbolic.ring import is_SymbolicVariable
849
sage: is_SymbolicVariable(x)
850
True
851
sage: is_SymbolicVariable(x+2)
852
False
853
854
TESTS::
855
856
sage: ZZ[x]
857
Univariate Polynomial Ring in x over Integer Ring
858
"""
859
return is_Expression(x) and is_a_symbol((<Expression>x)._gobj)
860
861
def isidentifier(x):
862
"""
863
Return whether ``x`` is a valid identifier.
864
865
When we switch to Python 3 this function can be replaced by the
866
official Python function of the same name.
867
868
INPUT:
869
870
- ``x`` -- a string.
871
872
OUTPUT:
873
874
Boolean. Whether the string ``x`` can be used as a variable name.
875
876
EXAMPLES::
877
878
sage: from sage.symbolic.ring import isidentifier
879
sage: isidentifier('x')
880
True
881
sage: isidentifier(' x') # can't start with space
882
False
883
sage: isidentifier('ceci_n_est_pas_une_pipe')
884
True
885
sage: isidentifier('1 + x')
886
False
887
sage: isidentifier('2good')
888
False
889
sage: isidentifier('good2')
890
True
891
sage: isidentifier('lambda s:s+1')
892
False
893
"""
894
import parser
895
try:
896
code = parser.expr(x).compile()
897
except (MemoryError, OverflowError, SyntaxError, SystemError, parser.ParserError), msg:
898
return False
899
return len(code.co_names)==1 and code.co_names[0]==x
900
901
902
903