Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/interfaces/axiom.py
4058 views
1
r"""
2
Interface to Axiom
3
4
TODO:
5
6
- Evaluation using a file is not done. Any input line with more than a
7
few thousand characters would hang the system, so currently it
8
automatically raises an exception.
9
10
- All completions of a given command.
11
12
- Interactive help.
13
14
Axiom is a free GPL-compatible (modified BSD license) general
15
purpose computer algebra system whose development started in 1973
16
at IBM. It contains symbolic manipulation algorithms, as well as
17
implementations of special functions, including elliptic functions
18
and generalized hypergeometric functions. Moreover, Axiom has
19
implementations of many functions relating to the invariant theory
20
of the symmetric group `S_n.` For many links to Axiom
21
documentation see http://wiki.axiom-developer.org.
22
23
AUTHORS:
24
25
- Bill Page (2006-10): Created this (based on Maxima interface)
26
27
28
.. note::
29
30
Bill Page put a huge amount of effort into the Sage Axiom
31
interface over several days during the Sage Days 2 coding
32
sprint. This is contribution is greatly appreciated.
33
34
- William Stein (2006-10): misc touchup.
35
36
- Bill Page (2007-08): Minor modifications to support axiom4sage-0.3
37
38
.. note::
39
40
The axiom4sage-0.3.spkg is based on an experimental version of the
41
FriCAS fork of the Axiom project by Waldek Hebisch that uses
42
pre-compiled cached Lisp code to build Axiom very quickly with
43
clisp.
44
45
If the string "error" (case insensitive) occurs in the output of
46
anything from axiom, a RuntimeError exception is raised.
47
48
EXAMPLES: We evaluate a very simple expression in axiom.
49
50
::
51
52
sage: axiom('3 * 5') #optional - axiom
53
15
54
sage: a = axiom(3) * axiom(5); a #optional - axiom
55
15
56
57
The type of a is AxiomElement, i.e., an element of the axiom
58
interpreter.
59
60
::
61
62
sage: type(a) #optional - axiom
63
<class 'sage.interfaces.axiom.AxiomElement'>
64
sage: parent(a) #optional - axiom
65
Axiom
66
67
The underlying Axiom type of a is also available, via the type
68
method::
69
70
sage: a.type() #optional - axiom
71
PositiveInteger
72
73
We factor `x^5 - y^5` in Axiom in several different ways.
74
The first way yields a Axiom object.
75
76
::
77
78
sage: F = axiom.factor('x^5 - y^5'); F #optional - axiom
79
4 3 2 2 3 4
80
- (y - x)(y + x y + x y + x y + x )
81
sage: type(F) #optional - axiom
82
<class 'sage.interfaces.axiom.AxiomElement'>
83
sage: F.type() #optional - axiom
84
Factored Polynomial Integer
85
86
Note that Axiom objects are normally displayed using "ASCII art".
87
88
::
89
90
sage: a = axiom(2/3); a #optional - axiom
91
2
92
-
93
3
94
sage: a = axiom('x^2 + 3/7'); a #optional - axiom
95
2 3
96
x + -
97
7
98
99
The ``axiom.eval`` command evaluates an expression in
100
axiom and returns the result as a string. This is exact as if we
101
typed in the given line of code to axiom; the return value is what
102
Axiom would print out.
103
104
::
105
106
sage: print axiom.eval('factor(x^5 - y^5)') #optional - axiom
107
4 3 2 2 3 4
108
- (y - x)(y + x y + x y + x y + x )
109
Type: Factored Polynomial Integer
110
111
We can create the polynomial `f` as a Axiom polynomial,
112
then call the factor method on it. Notice that the notation
113
``f.factor()`` is consistent with how the rest of Sage
114
works.
115
116
::
117
118
sage: f = axiom('x^5 - y^5') #optional - axiom
119
sage: f^2 #optional - axiom
120
10 5 5 10
121
y - 2x y + x
122
sage: f.factor() #optional - axiom
123
4 3 2 2 3 4
124
- (y - x)(y + x y + x y + x y + x )
125
126
Control-C interruption works well with the axiom interface, because
127
of the excellent implementation of axiom. For example, try the
128
following sum but with a much bigger range, and hit control-C.
129
130
::
131
132
sage: f = axiom('(x^5 - y^5)^10000') # not tested
133
Interrupting Axiom...
134
...
135
<type 'exceptions.TypeError'>: Ctrl-c pressed while running Axiom
136
137
::
138
139
sage: axiom('1/100 + 1/101') #optional - axiom
140
201
141
-----
142
10100
143
sage: a = axiom('(1 + sqrt(2))^5'); a #optional - axiom
144
+-+
145
29\|2 + 41
146
147
TESTS: We check to make sure the subst method works with keyword
148
arguments.
149
150
::
151
152
sage: a = axiom(x+2); a #optional - axiom
153
x + 2
154
sage: a.subst(x=3) #optional - axiom
155
5
156
157
We verify that Axiom floating point numbers can be converted to
158
Python floats.
159
160
::
161
162
sage: float(axiom(2)) #optional - axiom
163
2.0
164
"""
165
166
###########################################################################
167
# Copyright (C) 2008 Mike Hansen <[email protected]>
168
# 2007 Bill Page
169
# 2006 William Stein <[email protected]>
170
#
171
# Distributed under the terms of the GNU General Public License (GPL)
172
# The full text of the GPL is available at:
173
#
174
# http://www.gnu.org/licenses/
175
###########################################################################
176
177
import os, re
178
179
from expect import Expect, ExpectElement, FunctionElement, ExpectFunction
180
from sage.misc.misc import verbose, DOT_SAGE
181
from pexpect import EOF
182
from sage.misc.multireplace import multiple_replace
183
184
# The Axiom commands ")what thing det" ")show Matrix" and ")display
185
# op det" commands, gives a list of all identifiers that begin in
186
# a certain way. This could maybe be useful somehow... (?) Also
187
# axiom has a lot a lot of ways for getting documentation from the
188
# system -- this could also be useful.
189
190
class PanAxiom(Expect):
191
"""
192
Interface to a PanAxiom interpreter.
193
"""
194
def __init__(self, name='axiom', command='axiom -nox -noclef',
195
script_subdirectory=None, logfile=None,
196
server=None, server_tmpdir=None,
197
init_code=[')lisp (si::readline-off)']):
198
"""
199
Create an instance of the Axiom interpreter.
200
201
TESTS::
202
203
sage: axiom == loads(dumps(axiom))
204
True
205
"""
206
eval_using_file_cutoff = 200
207
self.__eval_using_file_cutoff = eval_using_file_cutoff
208
self._COMMANDS_CACHE = '%s/%s_commandlist_cache.sobj'%(DOT_SAGE, name)
209
Expect.__init__(self,
210
name = name,
211
prompt = '\([0-9]+\) -> ',
212
command = command,
213
maxread = 10,
214
script_subdirectory = script_subdirectory,
215
server=server,
216
server_tmpdir=server_tmpdir,
217
restart_on_ctrlc = False,
218
verbose_start = False,
219
init_code = init_code,
220
logfile = logfile,
221
eval_using_file_cutoff=eval_using_file_cutoff)
222
self._prompt_wait = self._prompt
223
224
def _start(self):
225
"""
226
Start the Axiom interpreter.
227
228
EXAMPLES::
229
230
sage: a = Axiom()
231
sage: a.is_running()
232
False
233
sage: a._start() #optional - axiom
234
sage: a.is_running() #optional - axiom
235
True
236
sage: a.quit() #optional - axiom
237
"""
238
Expect._start(self)
239
out = self._eval_line(')set functions compile on', reformat=False)
240
out = self._eval_line(')set output length 245', reformat=False)
241
out = self._eval_line(')set message autoload off', reformat=False)
242
243
def _read_in_file_command(self, filename):
244
r"""
245
EXAMPLES::
246
247
sage: axiom._read_in_file_command('test.input')
248
')read test.input \n'
249
sage: axiom._read_in_file_command('test')
250
Traceback (most recent call last):
251
...
252
ValueError: the filename must end with .input
253
254
::
255
256
sage: filename = tmp_filename()+'.input'
257
sage: f = open(filename, 'w')
258
sage: f.write('xx := 22;\n')
259
sage: f.close()
260
sage: axiom.read(filename) #optional -- requires Axiom
261
sage: axiom.get('xx') #optional
262
'22'
263
"""
264
if not filename.endswith('.input'):
265
raise ValueError, "the filename must end with .input"
266
267
# For some reason this trivial comp
268
# keeps certain random freezes from occurring. Do not remove this.
269
# The space before the \n is also important.
270
return ')read %s \n'%filename
271
272
273
def _quit_string(self):
274
"""
275
Returns the string used to quit Axiom.
276
277
EXAMPLES::
278
279
sage: axiom._quit_string()
280
')lisp (quit)'
281
sage: a = Axiom()
282
sage: a.is_running()
283
False
284
sage: a._start() #optional - axiom
285
sage: a.is_running() #optional - axiom
286
True
287
sage: a.quit() #optional - axiom
288
sage: a.is_running() #optional - axiom
289
False
290
"""
291
return ')lisp (quit)'
292
293
def _commands(self):
294
"""
295
Returns a list of commands available. This is done by parsing the
296
result of the first section of the output of ')what things'.
297
298
EXAMPLES::
299
300
sage: cmds = axiom._commands() #optional - axiom
301
sage: len(cmds) > 100 #optional - axiom
302
True
303
sage: '<' in cmds #optional - axiom
304
True
305
sage: 'factor' in cmds #optional - axiom
306
True
307
"""
308
s = self.eval(")what things")
309
start = '\r\n\r\n#'
310
i = s.find(start)
311
end = "To get more information about"
312
j = s.find(end)
313
s = s[i+len(start):j].split()
314
return s
315
316
317
def trait_names(self, verbose=True, use_disk_cache=True):
318
"""
319
Returns a list of all the commands defined in Axiom and optionally
320
(per default) store them to disk.
321
322
EXAMPLES::
323
324
sage: c = axiom.trait_names(use_disk_cache=False, verbose=False) #optional - axiom
325
sage: len(c) > 100 #optional - axiom
326
True
327
sage: 'factor' in c #optional - axiom
328
True
329
sage: '**' in c #optional - axiom
330
False
331
sage: 'upperCase?' in c #optional - axiom
332
False
333
sage: 'upperCase_q' in c #optional - axiom
334
True
335
sage: 'upperCase_e' in c #optional - axiom
336
True
337
"""
338
try:
339
return self.__trait_names
340
except AttributeError:
341
import sage.misc.persist
342
if use_disk_cache:
343
try:
344
self.__trait_names = sage.misc.persist.load(self._COMMANDS_CACHE)
345
return self.__trait_names
346
except IOError:
347
pass
348
if verbose:
349
print "\nBuilding %s command completion list (this takes"%(self)
350
print "a few seconds only the first time you do it)."
351
print "To force rebuild later, delete %s."%self._COMMANDS_CACHE
352
v = self._commands()
353
354
#Process we now need process the commands to strip out things which
355
#are not valid Python identifiers.
356
import re
357
valid = re.compile('[^a-zA-Z0-9_]+')
358
names = [x for x in v if valid.search(x) is None]
359
360
#Change everything that ends with ? to _q and
361
#everything that ends with ! to _e
362
names += [x[:-1]+"_q" for x in v if x.endswith("?")]
363
names += [x[:-1]+"_e" for x in v if x.endswith("!")]
364
365
self.__trait_names = names
366
if len(v) > 200:
367
# Axiom is actually installed.
368
sage.misc.persist.save(v, self._COMMANDS_CACHE)
369
return names
370
371
def set(self, var, value):
372
"""
373
Set the variable var to the given value.
374
375
EXAMPLES::
376
377
sage: axiom.set('xx', '2') #optional - axiom
378
sage: axiom.get('xx') #optional - axiom
379
'2'
380
381
sage: fricas.set('xx', '2') #optional - fricas
382
sage: fricas.get('xx') #optional - fricas
383
'2'
384
385
"""
386
cmd = '%s := %s'%(var, value)
387
out = self._eval_line(cmd, reformat=False)
388
389
if out.find("error") != -1:
390
raise TypeError, "Error executing code in Axiom\nCODE:\n\t%s\nAxiom ERROR:\n\t%s"%(cmd, out)
391
392
393
def get(self, var):
394
r"""
395
Get the string value of the Axiom variable var.
396
397
EXAMPLES::
398
399
sage: axiom.set('xx', '2') #optional - axiom
400
sage: axiom.get('xx') #optional - axiom
401
'2'
402
sage: a = axiom('(1 + sqrt(2))^5') #optional - axiom
403
sage: axiom.get(a.name()) #optional - axiom
404
' +-+\r\r\n 29\\|2 + 41'
405
"""
406
s = self._eval_line(str(var))
407
i = s.rfind('Type:')
408
s = s[:i].rstrip().lstrip("\n")
409
if '\n' not in s:
410
s = s.strip()
411
return s
412
413
def _eval_line(self, line, reformat=True, allow_use_file=False,
414
wait_for_prompt=True, restart_if_needed=False):
415
"""
416
EXAMPLES::
417
418
sage: print axiom._eval_line('2+2') #optional - axiom
419
4
420
Type: PositiveInteger
421
"""
422
if not wait_for_prompt:
423
return Expect._eval_line(self, line)
424
line = line.rstrip().rstrip(';')
425
if line == '':
426
return ''
427
if len(line) > 3000:
428
raise NotImplementedError, "evaluation of long input lines (>3000 characters) in Axiom not yet implemented."
429
if self._expect is None:
430
self._start()
431
if allow_use_file and self.__eval_using_file_cutoff and \
432
len(line) > self.__eval_using_file_cutoff:
433
return self._eval_line_using_file(line)
434
try:
435
E = self._expect
436
# debug
437
self._synchronize(cmd='1+%s\n')
438
verbose("in = '%s'"%line,level=3)
439
E.sendline(line)
440
self._expect.expect(self._prompt)
441
out = self._expect.before
442
# debug
443
verbose("out = '%s'"%out,level=3)
444
except EOF:
445
if self._quit_string() in line:
446
return ''
447
except KeyboardInterrupt:
448
self._keyboard_interrupt()
449
450
if '>> Error detected within library code:' in out or \
451
'Cannot find a definition or applicable library operation named' in out:
452
raise RuntimeError, out
453
454
if not reformat:
455
return out
456
if 'error' in out:
457
return out
458
#out = out.lstrip()
459
i = out.find('\n')
460
out = out[i+1:]
461
outs = out.split("\n")
462
i = 0
463
outline = ''
464
for line in outs:
465
line = line.rstrip()
466
# print "'%s'"%line
467
if line[:4] == ' (':
468
i = line.find('(')
469
i += line[i:].find(')')
470
if line[i+1:] == "":
471
i = 0
472
outs = outs[1:]
473
break;
474
out = "\n".join(line[i+1:] for line in outs[1:])
475
return out
476
477
# define relational operators
478
def _equality_symbol(self):
479
"""equality symbol
480
481
EXAMPLES::
482
483
sage: a = axiom(x==6); a #optional axiom
484
x= 6
485
sage: a = fricas(x==6); a #optional fricas
486
x= 6
487
"""
488
return "="
489
490
491
class Axiom(PanAxiom):
492
def __reduce__(self):
493
"""
494
EXAMPLES::
495
496
sage: axiom.__reduce__()
497
(<function reduce_load_Axiom at 0x...>, ())
498
sage: f, args = _
499
sage: f(*args)
500
Axiom
501
"""
502
return reduce_load_Axiom, tuple([])
503
504
def _function_class(self):
505
"""
506
Return the AxiomExpectFunction class.
507
508
EXAMPLES::
509
510
sage: axiom._function_class()
511
<class 'sage.interfaces.axiom.AxiomExpectFunction'>
512
sage: type(axiom.gcd)
513
<class 'sage.interfaces.axiom.AxiomExpectFunction'>
514
"""
515
return AxiomExpectFunction
516
517
def _object_class(self):
518
"""
519
EXAMPLES::
520
521
sage: axiom._object_class()
522
<class 'sage.interfaces.axiom.AxiomElement'>
523
sage: type(axiom(2)) #optional - axiom
524
<class 'sage.interfaces.axiom.AxiomElement'>
525
"""
526
return AxiomElement
527
528
def _function_element_class(self):
529
"""
530
Returns the Axiom function element class.
531
532
EXAMPLES::
533
534
sage: axiom._function_element_class()
535
<class 'sage.interfaces.axiom.AxiomFunctionElement'>
536
sage: type(axiom(2).gcd) #optional - axiom
537
<class 'sage.interfaces.axiom.AxiomFunctionElement'>
538
"""
539
return AxiomFunctionElement
540
541
def console(self):
542
"""
543
Spawn a new Axiom command-line session.
544
545
EXAMPLES::
546
547
sage: axiom.console() #not tested
548
AXIOM Computer Algebra System
549
Version: Axiom (January 2009)
550
Timestamp: Sunday January 25, 2009 at 07:08:54
551
-----------------------------------------------------------------------------
552
Issue )copyright to view copyright notices.
553
Issue )summary for a summary of useful system commands.
554
Issue )quit to leave AXIOM and return to shell.
555
-----------------------------------------------------------------------------
556
"""
557
axiom_console()
558
559
class PanAxiomElement(ExpectElement):
560
def __call__(self, x):
561
"""
562
EXAMPLES::
563
564
sage: f = axiom(x+2) #optional - axiom
565
sage: f(2) #optional - axiom
566
4
567
"""
568
self._check_valid()
569
P = self.parent()
570
return P('%s(%s)'%(self.name(), x))
571
572
def __cmp__(self, other):
573
"""
574
EXAMPLES::
575
576
sage: two = axiom(2) #optional - axiom
577
sage: two == 2 #optional - axiom
578
True
579
sage: two == 3 #optional - axiom
580
False
581
sage: two < 3 #optional - axiom
582
True
583
sage: two > 1 #optional - axiom
584
True
585
586
sage: a = axiom(1); b = axiom(2) #optional - axiom
587
sage: a == b #optional - axiom
588
False
589
sage: a < b #optional - axiom
590
True
591
sage: a > b #optional - axiom
592
False
593
sage: b < a #optional - axiom
594
False
595
sage: b > a #optional - axiom
596
True
597
598
We can also compare more complicated object such as functions::
599
600
sage: f = axiom('sin(x)'); g = axiom('cos(x)') #optional - axiom
601
sage: f == g #optional - axiom
602
False
603
604
"""
605
P = self.parent()
606
if 'true' in P.eval("(%s = %s) :: Boolean"%(self.name(),other.name())):
607
return 0
608
elif 'true' in P.eval("(%s < %s) :: Boolean"%(self.name(), other.name())):
609
return -1
610
elif 'true' in P.eval("(%s > %s) :: Boolean"%(self.name(),other.name())):
611
return 1
612
613
# everything is supposed to be comparable in Python, so we define
614
# the comparison thus when no comparable in interfaced system.
615
if (hash(self) < hash(other)):
616
return -1
617
else:
618
return 1
619
620
def type(self):
621
"""
622
Returns the type of an AxiomElement.
623
624
EXAMPLES::
625
626
sage: axiom(x+2).type() #optional - axiom
627
Polynomial Integer
628
"""
629
P = self._check_valid()
630
s = P._eval_line(self.name())
631
i = s.rfind('Type:')
632
return P(s[i+5:].strip())
633
634
def __len__(self):
635
"""
636
Return the length of a list.
637
638
EXAMPLES::
639
640
sage: v = axiom('[x^i for i in 0..5]') # optional - axiom
641
sage: len(v) # optional - axiom
642
6
643
"""
644
P = self._check_valid()
645
s = P.eval('# %s '%self.name())
646
i = s.rfind('Type')
647
return int(s[:i-1])
648
649
def __getitem__(self, n):
650
r"""
651
Return the n-th element of this list.
652
653
.. note::
654
655
Lists are 1-based.
656
657
EXAMPLES::
658
659
sage: v = axiom('[i*x^i for i in 0..5]'); v # optional - axiom
660
2 3 4 5
661
[0,x,2x ,3x ,4x ,5x ]
662
sage: v[4] # optional - axiom
663
3
664
3x
665
sage: v[1] # optional - axiom
666
0
667
sage: v[10] # optional - axiom
668
Traceback (most recent call last):
669
...
670
IndexError: index out of range
671
"""
672
n = int(n)
673
if n <= 0 or n > len(self):
674
raise IndexError, "index out of range"
675
P = self._check_valid()
676
if not isinstance(n, tuple):
677
return P.new('%s(%s)'%(self._name, n))
678
else:
679
return P.new('%s(%s)'%(self._name, str(n)[1:-1]))
680
681
def comma(self, *args):
682
"""
683
Returns a Axiom tuple from self and args.
684
685
EXAMPLES::
686
687
sage: two = axiom(2) #optional - axiom
688
sage: two.comma(3) #optional - axiom
689
[2,3]
690
sage: two.comma(3,4) #optional - axiom
691
[2,3,4]
692
sage: _.type() #optional - axiom
693
Tuple PositiveInteger
694
695
sage: two = fricas(2) #optional - fricas
696
sage: two.comma(3) #optional - fricas
697
[2,3]
698
sage: two.comma(3,4) #optional - fricas
699
[2,3,4]
700
sage: _.type() #optional - fricas
701
Tuple(PositiveInteger)
702
703
"""
704
P = self._check_valid()
705
args = list(args)
706
for i, arg in enumerate(args):
707
if not isinstance(arg, AxiomElement) or arg.parent() is not P:
708
args[i] = P(arg)
709
cmd = "(" + ",".join([x.name() for x in [self]+args]) + ")"
710
return P(cmd)
711
712
def _latex_(self):
713
r"""
714
EXAMPLES::
715
716
sage: a = axiom(1/2) #optional - axiom
717
sage: latex(a) #optional - axiom
718
\frac{1}{2}
719
720
sage: a = fricas(1/2) #optional - fricas
721
sage: latex(a) #optional - fricas
722
1 \over 2
723
"""
724
self._check_valid()
725
P = self.parent()
726
s = P._eval_line('outputAsTex(%s)'%self.name(), reformat=False)
727
if not '$$' in s:
728
raise RuntimeError, "Error texing axiom object."
729
i = s.find('$$')
730
j = s.rfind('$$')
731
s = s[i+2:j]
732
s = multiple_replace({'\r':'', '\n':' ',
733
' \\sp ':'^',
734
'\\arcsin ':'\\sin^{-1} ',
735
'\\arccos ':'\\cos^{-1} ',
736
'\\arctan ':'\\tan^{-1} '},
737
re.sub(r'\\leqno\(.*?\)','',s)) # no eq number!
738
return s
739
740
def as_type(self, type):
741
"""
742
Returns self as type.
743
744
EXAMPLES::
745
746
sage: a = axiom(1.2); a #optional - axiom
747
1.2
748
sage: a.as_type(axiom.DoubleFloat) #optional - axiom
749
1.2
750
sage: _.type() #optional - axiom
751
DoubleFloat
752
753
::
754
755
sage: a = fricas(1.2); a #optional - fricas
756
1.2
757
sage: a.as_type(fricas.DoubleFloat) #optional - fricas
758
1.2
759
sage: _.type() #optional - fricas
760
DoubleFloat
761
762
"""
763
P = self._check_valid()
764
type = P(type)
765
return P.new("%s :: %s"%(self.name(), type.name()))
766
767
def unparsed_input_form(self):
768
"""
769
Get the linear string representation of this object, if possible
770
(often it isn't).
771
772
EXAMPLES::
773
774
sage: a = axiom(x^2+1); a #optional - axiom
775
2
776
x + 1
777
sage: a.unparsed_input_form() #optional - axiom
778
'x*x+1'
779
780
sage: a = fricas(x^2+1) #optional - fricas
781
sage: a.unparsed_input_form() #optional - fricas
782
'x^2+1'
783
"""
784
P = self._check_valid()
785
s = P.eval('unparse(%s::InputForm)'%self._name)
786
if 'translation error' in s or 'Cannot convert' in s:
787
raise NotImplementedError
788
s = multiple_replace({'\r\n':'', # fix stupid Fortran-ish
789
'DSIN(':'sin(',
790
'DCOS(':'cos(',
791
'DTAN(':'tan(',
792
'DSINH(':'sinh('}, s)
793
r = re.search(r'"(.*)"',s)
794
if r:
795
return r.groups(0)[0]
796
else:
797
return s
798
799
800
def _sage_(self):
801
"""
802
Convert self to a Sage object.
803
804
EXAMPLES::
805
806
sage: a = axiom(1/2); a #optional - axiom
807
1
808
-
809
2
810
sage: a.sage() #optional - axiom
811
1/2
812
sage: _.parent() #optional - axiom
813
Rational Field
814
815
sage: gp(axiom(1/2)) #optional - axiom
816
1/2
817
818
sage: fricas(1/2).sage() #optional - fricas
819
1/2
820
821
DoubleFloat's in Axiom are converted to be in RDF in Sage.
822
823
::
824
825
sage: axiom(2.0).as_type('DoubleFloat').sage() #optional - axiom
826
2.0
827
sage: _.parent() #optional - axiom
828
Real Double Field
829
830
831
sage: axiom(2.1234)._sage_() #optional - axiom
832
2.12340000000000
833
sage: _.parent() #optional - axiom
834
Real Field with 53 bits of precision
835
sage: a = RealField(100)(pi)
836
sage: axiom(a)._sage_() #optional - axiom
837
3.1415926535897932384626433833
838
sage: _.parent() #optional - axiom
839
Real Field with 100 bits of precision
840
sage: axiom(a)._sage_() == a #optional - axiom
841
True
842
sage: axiom(2.0)._sage_() #optional - axiom
843
2.00000000000000
844
sage: _.parent() #optional - axiom
845
Real Field with 53 bits of precision
846
847
848
We can also convert Axiom's polynomials to Sage polynomials.
849
sage: a = axiom(x^2 + 1) #optional - axiom
850
sage: a.type() #optional - axiom
851
Polynomial Integer
852
sage: a.sage() #optional - axiom
853
x^2 + 1
854
sage: _.parent() #optional - axiom
855
Univariate Polynomial Ring in x over Integer Ring
856
sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom
857
y^2 + x^2 + 1/2
858
sage: _.parent() #optional - axiom
859
Multivariate Polynomial Ring in y, x over Rational Field
860
861
862
"""
863
P = self._check_valid()
864
type = str(self.type())
865
866
if type in ["Type", "Domain"]:
867
return self._sage_domain()
868
869
if type == "Float":
870
from sage.rings.all import RealField, ZZ
871
prec = max(self.mantissa().length()._sage_(), 53)
872
R = RealField(prec)
873
x,e,b = self.unparsed_input_form().lstrip('float(').rstrip(')').split(',')
874
return R(ZZ(x)*ZZ(b)**ZZ(e))
875
elif type == "DoubleFloat":
876
from sage.rings.all import RDF
877
return RDF(repr(self))
878
elif type.startswith('Polynomial'):
879
from sage.rings.all import PolynomialRing
880
base_ring = P(type.lstrip('Polynomial '))._sage_domain()
881
vars = str(self.variables())[1:-1]
882
R = PolynomialRing(base_ring, vars)
883
return R(self.unparsed_input_form())
884
885
#If all else fails, try using the unparsed input form
886
try:
887
import sage.misc.sage_eval
888
return sage.misc.sage_eval.sage_eval(self.unparsed_input_form())
889
except:
890
raise NotImplementedError
891
892
893
def _sage_domain(self):
894
"""
895
A helper function for converting Axiom domains to the corresponding
896
Sage object.
897
898
EXAMPLES::
899
900
sage: axiom('Integer').sage() #optional - axiom
901
Integer Ring
902
sage: fricas('Integer').sage() #optional - fricas
903
Integer Ring
904
905
sage: axiom('Fraction Integer').sage() #optional - axiom
906
Rational Field
907
sage: fricas('Fraction Integer').sage() #optional - fricas
908
Rational Field
909
910
sage: axiom('DoubleFloat').sage() #optional - axiom
911
Real Double Field
912
sage: fricas('DoubleFloat').sage() #optional - fricas
913
Real Double Field
914
915
"""
916
P = self._check_valid()
917
name = str(self)
918
if name == 'Integer':
919
from sage.rings.all import ZZ
920
return ZZ
921
elif name == 'DoubleFloat':
922
from sage.rings.all import RDF
923
return RDF
924
elif name.startswith('Fraction '):
925
return P(name.lstrip('Fraction '))._sage_domain().fraction_field()
926
927
raise NotImplementedError
928
929
930
931
class AxiomElement(PanAxiomElement):
932
pass
933
934
class PanAxiomFunctionElement(FunctionElement):
935
def __init__(self, object, name):
936
"""
937
TESTS::
938
939
sage: a = axiom('"Hello"') #optional - axiom
940
sage: a.upperCase_q #optional - axiom
941
upperCase?
942
sage: a.upperCase_e #optional - axiom
943
upperCase!
944
sage: a.upperCase_e() #optional - axiom
945
"HELLO"
946
"""
947
if name.endswith("_q"):
948
name = name[:-2] + "?"
949
elif name.endswith("_e"):
950
name = name[:-2] + "!"
951
FunctionElement.__init__(self, object, name)
952
953
class AxiomFunctionElement(PanAxiomFunctionElement):
954
pass
955
956
class PanAxiomExpectFunction(ExpectFunction):
957
def __init__(self, parent, name):
958
"""
959
TESTS::
960
961
sage: axiom.upperCase_q
962
upperCase?
963
sage: axiom.upperCase_e
964
upperCase!
965
"""
966
if name.endswith("_q"):
967
name = name[:-2] + "?"
968
elif name.endswith("_e"):
969
name = name[:-2] + "!"
970
ExpectFunction.__init__(self, parent, name)
971
972
class AxiomExpectFunction(PanAxiomExpectFunction):
973
pass
974
975
def is_AxiomElement(x):
976
"""
977
Returns True of x is of type AxiomElement.
978
979
EXAMPLES::
980
981
sage: from sage.interfaces.axiom import is_AxiomElement
982
sage: is_AxiomElement(axiom(2)) #optional - axiom
983
True
984
sage: is_AxiomElement(2)
985
False
986
"""
987
return isinstance(x, AxiomElement)
988
989
#Instances
990
axiom = Axiom(name='axiom')
991
992
def reduce_load_Axiom():
993
"""
994
Returns the Axiom interface object defined in
995
sage.interfaces.axiom.
996
997
EXAMPLES::
998
999
sage: from sage.interfaces.axiom import reduce_load_Axiom
1000
sage: reduce_load_Axiom()
1001
Axiom
1002
"""
1003
return axiom
1004
1005
import os
1006
def axiom_console():
1007
"""
1008
Spawn a new Axiom command-line session.
1009
1010
EXAMPLES::
1011
1012
sage: axiom_console() #not tested
1013
AXIOM Computer Algebra System
1014
Version: Axiom (January 2009)
1015
Timestamp: Sunday January 25, 2009 at 07:08:54
1016
-----------------------------------------------------------------------------
1017
Issue )copyright to view copyright notices.
1018
Issue )summary for a summary of useful system commands.
1019
Issue )quit to leave AXIOM and return to shell.
1020
-----------------------------------------------------------------------------
1021
1022
"""
1023
os.system('axiom -nox')
1024
1025
1026