Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/interfaces/maple.py
8814 views
1
r"""
2
Interface to Maple
3
4
AUTHORS:
5
6
- William Stein (2005): maple interface
7
8
- Gregg Musiker (2006-02-02): tutorial
9
10
- William Stein (2006-03-05): added tab completion, e.g., maple.[tab],
11
and help, e.g, maple.sin?.
12
13
You must have the optional commercial Maple interpreter installed
14
and available as the command ``maple`` in your PATH in
15
order to use this interface. You do not have to install any
16
optional Sage packages.
17
18
Type ``maple.[tab]`` for a list of all the functions
19
available from your Maple install. Type
20
``maple.[tab]?`` for Maple's help about a given
21
function. Type ``maple(...)`` to create a new Maple
22
object, and ``maple.eval(...)`` to run a string using
23
Maple (and get the result back as a string).
24
25
EXAMPLES::
26
27
sage: maple('3 * 5') # optional - maple
28
15
29
sage: maple.eval('ifactor(2005)') # optional - maple
30
'"(5)*"(401)'
31
sage: maple.ifactor(2005) # optional - maple
32
"(5)*"(401)
33
sage: maple.fsolve('x^2=cos(x)+4', 'x=0..5') # optional - maple
34
1.914020619
35
sage: maple.factor('x^5 - y^5') # optional - maple
36
(x-y)*(x^4+x^3*y+x^2*y^2+x*y^3+y^4)
37
38
If the string "error" (case insensitive) occurs in the output of
39
anything from Maple, a RuntimeError exception is raised.
40
41
Tutorial
42
--------
43
44
AUTHORS:
45
46
- Gregg Musiker (2006-02-02): initial version.
47
48
This tutorial is based on the Maple Tutorial for number theory from
49
http://www.math.mun.ca/~drideout/m3370/numtheory.html.
50
51
There are several ways to use the Maple Interface in Sage. We will
52
discuss two of those ways in this tutorial.
53
54
55
#. If you have a maple expression such as
56
57
::
58
59
factor( (x^5-1));
60
61
We can write that in sage as
62
63
::
64
65
sage: maple('factor(x^5-1)') # optional - maple
66
(x-1)*(x^4+x^3+x^2+x+1)
67
68
Notice, there is no need to use a semicolon.
69
70
#. Since Sage is written in Python, we can also import maple
71
commands and write our scripts in a Pythonic way. For example,
72
``factor()`` is a maple command, so we can also factor
73
in Sage using
74
75
::
76
77
sage: maple('(x^5-1)').factor() # optional - maple
78
(x-1)*(x^4+x^3+x^2+x+1)
79
80
where ``expression.command()`` means the same thing as
81
``command(expression)`` in Maple. We will use this
82
second type of syntax whenever possible, resorting to the first
83
when needed.
84
85
::
86
87
sage: maple('(x^12-1)/(x-1)').simplify() # optional - maple
88
x^11+x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1
89
90
91
The normal command will always reduce a rational function to the
92
lowest terms. The factor command will factor a polynomial with
93
rational coefficients into irreducible factors over the ring of
94
integers. So for example,
95
96
::
97
98
sage: maple('(x^12-1)').factor( ) # optional - maple
99
(x-1)*(x+1)*(x^2+x+1)*(x^2-x+1)*(x^2+1)*(x^4-x^2+1)
100
101
::
102
103
sage: maple('(x^28-1)').factor( ) # optional - maple
104
(x-1)*(x^6+x^5+x^4+x^3+x^2+x+1)*(x+1)*(1-x+x^2-x^3+x^4-x^5+x^6)*(x^2+1)*(x^12-x^10+x^8-x^6+x^4-x^2+1)
105
106
Another important feature of maple is its online help. We can
107
access this through sage as well. After reading the description of
108
the command, you can press q to immediately get back to your
109
original prompt.
110
111
Incidentally you can always get into a maple console by the
112
command
113
114
::
115
116
sage: maple.console() # not tested
117
sage: !maple # not tested
118
119
Note that the above two commands are slightly different, and the
120
first is preferred.
121
122
For example, for help on the maple command fibonacci, we type
123
124
::
125
126
sage: maple.help('fibonacci') # not tested, since it uses a pager
127
128
We see there are two choices. Type
129
130
::
131
132
sage: maple.help('combinat, fibonacci') # not tested, since it uses a pager
133
134
We now see how the Maple command fibonacci works under the
135
combinatorics package. Try typing in
136
137
::
138
139
sage: maple.fibonacci(10) # optional - maple
140
fibonacci(10)
141
142
You will get fibonacci(10) as output since Maple has not loaded the
143
combinatorics package yet. To rectify this type
144
145
::
146
147
sage: maple('combinat[fibonacci]')(10) # optional - maple
148
55
149
150
instead.
151
152
If you want to load the combinatorics package for future
153
calculations, in Sage this can be done as
154
155
::
156
157
sage: maple.with_package('combinat') # optional - maple
158
159
or
160
161
::
162
163
sage: maple.load('combinat') # optional - maple
164
165
Now if we type ``maple.fibonacci(10)``, we get the
166
correct output::
167
168
sage: maple.fibonacci(10) # optional - maple
169
55
170
171
Some common maple packages include ``combinat``,
172
``linalg``, and ``numtheory``. To produce
173
the first 19 Fibonacci numbers, use the sequence command.
174
175
::
176
177
sage: maple('seq(fibonacci(i),i=1..19)') # optional - maple
178
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,
179
4181
180
181
Two other useful Maple commands are ifactor and isprime. For
182
example
183
184
::
185
186
sage: maple.isprime(maple.fibonacci(27)) # optional - maple
187
false
188
sage: maple.ifactor(maple.fibonacci(27)) # optional - maple
189
"(2)*"(17)*"(53)*"(109)
190
191
Note that the isprime function that is included with Sage (which
192
uses PARI) is better than the Maple one (it is faster and gives a
193
provably correct answer, whereas Maple is sometimes wrong).
194
195
::
196
197
sage: alpha = maple('(1+sqrt(5))/2') # optional - maple
198
sage: beta = maple('(1-sqrt(5))/2') # optional - maple
199
sage: f19 = alpha^19 - beta^19/maple('sqrt(5)') # optional - maple
200
sage: f19 # optional - maple
201
(1/2+1/2*5^(1/2))^19-1/5*(1/2-1/2*5^(1/2))^19*5^(1/2)
202
sage: f19.simplify() # somewhat randomly ordered output; optional - maple
203
6765+5778/5*5^(1/2)
204
205
Let's say we want to write a maple program now that squares a
206
number if it is positive and cubes it if it is negative. In maple,
207
that would look like
208
209
::
210
211
mysqcu := proc(x)
212
if x > 0 then x^2;
213
else x^3; fi;
214
end;
215
216
In Sage, we write
217
218
::
219
220
sage: mysqcu = maple('proc(x) if x > 0 then x^2 else x^3 fi end') # optional - maple
221
sage: mysqcu(5) # optional - maple
222
25
223
sage: mysqcu(-5) # optional - maple
224
-125
225
226
More complicated programs should be put in a separate file and
227
loaded.
228
"""
229
230
#############################################################################
231
# Copyright (C) 2005 William Stein <[email protected]>
232
#
233
# Distributed under the terms of the GNU General Public License (GPL)
234
#
235
# http://www.gnu.org/licenses/
236
#############################################################################
237
238
import os
239
240
from expect import Expect, ExpectElement, ExpectFunction, FunctionElement, gc_disabled
241
242
import pexpect
243
244
from sage.misc.misc import verbose, DOT_SAGE
245
from sage.misc.pager import pager
246
247
COMMANDS_CACHE = '%s/maple_commandlist_cache.sobj'%DOT_SAGE
248
249
class Maple(Expect):
250
"""
251
Interface to the Maple interpreter.
252
253
Type ``maple.[tab]`` for a list of all the functions
254
available from your Maple install. Type
255
``maple.[tab]?`` for Maple's help about a given
256
function. Type ``maple(...)`` to create a new Maple
257
object, and ``maple.eval(...)`` to run a string using
258
Maple (and get the result back as a string).
259
"""
260
def __init__(self, maxread=100, script_subdirectory="", server=None, server_tmpdir=None, logfile=None):
261
"""
262
Create an instance of the Maple interpreter.
263
264
EXAMPLES::
265
266
sage: maple == loads(dumps(maple))
267
True
268
"""
269
Expect.__init__(self,
270
name = 'maple',
271
prompt = '#-->',
272
command = "maple -t",
273
maxread = maxread,
274
script_subdirectory = script_subdirectory,
275
restart_on_ctrlc = False,
276
server = server,
277
server_tmpdir = server_tmpdir,
278
verbose_start = False,
279
logfile = logfile,
280
eval_using_file_cutoff=1) # very important that this is 1
281
# It's very important to use file i/o for everything,
282
# since maple stupid command line interface always
283
# dumps you into the editor when an error occurs,
284
# and I can find no way to turn it off!!
285
286
def _function_class(self):
287
"""
288
EXAMPLES::
289
290
sage: maple._function_class()
291
<class 'sage.interfaces.maple.MapleFunction'>
292
293
::
294
295
sage: type(maple.diff)
296
<class 'sage.interfaces.maple.MapleFunction'>
297
"""
298
return MapleFunction
299
300
def _keyboard_interrupt(self):
301
print "Interrupting %s..."%self
302
self._expect.sendline(chr(3)) # send ctrl-c
303
self._expect.expect(self._prompt)
304
self._expect.expect(self._prompt)
305
raise RuntimeError, "Ctrl-c pressed while running %s"%self
306
307
def __reduce__(self):
308
"""
309
EXAMPLES::
310
311
sage: maple.__reduce__()
312
(<function reduce_load_Maple at 0x...>, ())
313
sage: f, args = _
314
sage: f(*args)
315
Maple
316
"""
317
return reduce_load_Maple, tuple([])
318
319
def _read_in_file_command(self, filename):
320
r"""
321
Returns the string used to read filename into Maple.
322
323
EXAMPLES::
324
325
sage: maple._read_in_file_command('test')
326
'read "test"'
327
328
::
329
330
sage: filename = tmp_filename()
331
sage: f = open(filename, 'w')
332
sage: f.write('xx := 22;\n')
333
sage: f.close()
334
sage: maple.read(filename) # optional - maple
335
sage: maple.get('xx').strip() # optional - maple
336
'22'
337
"""
338
return 'read "%s"'%filename
339
340
def _quit_string(self):
341
"""
342
EXAMPLES::
343
344
sage: maple._quit_string()
345
'quit'
346
347
::
348
349
sage: m = Maple()
350
sage: a = m(2) # optional - maple
351
sage: m.is_running() # optional - maple
352
True
353
sage: m.quit() # optional - maple
354
sage: m.is_running() # optional - maple
355
False
356
"""
357
return 'quit'
358
359
def _install_hints(self):
360
"""
361
Hints for installing Maple on your computer.
362
363
AUTHORS:
364
365
- William Stein and Justin Walker (2006-02-12).
366
367
EXAMPLES::
368
369
sage: print maple._install_hints()
370
In order...
371
"""
372
return """
373
374
In order to use the Maple interface you need to have Maple installed
375
and have a script in your PATH called "maple" that runs the
376
command-line version of Maple. Alternatively, you could use a remote
377
connection to a server running Maple; for hints, type
378
print maple._install_hints_ssh()
379
380
(1) You might have to buy Maple (http://webstore.maplesoft.com/).
381
382
(2) * LINUX: The maple script comes standard with your Maple install.
383
384
* APPLE OS X:
385
(a) create a file called maple (in your PATH), with the following contents:
386
#!/bin/sh
387
/Library/Frameworks/Maple.framework/Versions/Current/bin/maple $@
388
(b) Save the file.
389
(c) Make the file executable.
390
chmod +x maple
391
392
* WINDOWS:
393
You must install Maple-for-Linux into the VMware machine (sorry, that's
394
the only way at present).
395
"""
396
397
def expect(self):
398
"""
399
Returns the pexpect object for this Maple session.
400
401
EXAMPLES::
402
403
sage: m = Maple()
404
sage: m.expect() is None
405
True
406
sage: m._start() # optional - maple
407
sage: m.expect() # optional - maple
408
<pexpect.spawn instance at 0x...>
409
sage: m.quit() # optional - maple
410
"""
411
return self._expect
412
413
def console(self):
414
"""
415
Spawn a new Maple command-line session.
416
417
EXAMPLES::
418
419
sage: maple.console() # not tested
420
|^/| Maple 11 (IBM INTEL LINUX)
421
._|\| |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2007
422
\ MAPLE / All rights reserved. Maple is a trademark of
423
<____ ____> Waterloo Maple Inc.
424
| Type ? for help.
425
>
426
"""
427
maple_console()
428
429
## def killall(self):
430
## """
431
## Kill all running instances of the maple interpreter
432
## on this system.
433
434
## TODO: When Sage exits it doesn't correctly by default kill
435
## all running Maple interpreters, for some strange reason.
436
## Calling this function uses the kill and pidof operating system
437
## programs to find all instances of cmaple and kill them.
438
## """
439
## import os
440
## self._expect = None
441
## while True:
442
## pid = os.popen("pidof cmaple").read()[:-1]
443
## if len(pid) > 0:
444
## os.system('kill -9 %s'%pid)
445
## else:
446
## break
447
448
def completions(self, s):
449
"""
450
Return all commands that complete the command starting with the
451
string s. This is like typing s[Ctrl-T] in the maple interpreter.
452
453
EXAMPLES::
454
455
sage: c = maple.completions('di') # optional - maple
456
sage: 'divide' in c # optional - maple
457
True
458
"""
459
bs = chr(8)*len(s)
460
if self._expect is None:
461
self._start()
462
E = self._expect
463
E.sendline('%s%s%s'%(s,chr(20),bs))
464
t = E.timeout
465
E.timeout=0.3 # since some things have no completion
466
try:
467
E.expect('----')
468
except pexpect.TIMEOUT:
469
E.timeout = t
470
return []
471
E.timeout = t
472
v = E.before
473
E.expect(self._prompt)
474
E.expect(self._prompt)
475
return v.split()[2:]
476
477
def _commands(self):
478
"""
479
Return list of all commands defined in Maple.
480
481
EXAMPLES::
482
483
sage: c = maple._commands() # optional - maple
484
sage: len(c) > 100 # optional - maple
485
True
486
sage: 'dilog' in c # optional - maple
487
True
488
"""
489
try:
490
v = sum([self.completions(chr(65+n)) for n in range(26)], []) + \
491
sum([self.completions(chr(97+n)) for n in range(26)], [])
492
except RuntimeError:
493
print "\n"*3
494
print "*"*70
495
print "WARNING: You do not have a working version of Maple installed!"
496
print "*"*70
497
v = []
498
v.sort()
499
return v
500
501
def trait_names(self, verbose=True, use_disk_cache=True):
502
"""
503
Returns a list of all the commands defined in Maple and optionally
504
(per default) store them to disk.
505
506
EXAMPLES::
507
508
sage: c = maple.trait_names(use_disk_cache=False, verbose=False) # optional - maple
509
sage: len(c) > 100 # optional - maple
510
True
511
sage: 'dilog' in c # optional - maple
512
True
513
"""
514
try:
515
return self.__trait_names
516
except AttributeError:
517
import sage.misc.persist
518
if use_disk_cache:
519
try:
520
self.__trait_names = sage.misc.persist.load(COMMANDS_CACHE)
521
return self.__trait_names
522
except IOError:
523
pass
524
if verbose:
525
print "\nBuilding Maple command completion list (this takes"
526
print "a few seconds only the first time you do it)."
527
print "To force rebuild later, delete %s."%COMMANDS_CACHE
528
v = self._commands()
529
self.__trait_names = v
530
if len(v) > 200:
531
# Maple is actually installed.
532
sage.misc.persist.save(v, COMMANDS_CACHE)
533
return v
534
535
def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=False):
536
"""
537
EXAMPLES::
538
539
sage: maple._eval_line('2+2') # optional - maple
540
'4'
541
"""
542
line += ';'
543
with gc_disabled():
544
z = Expect._eval_line(self, line, allow_use_file=allow_use_file,
545
wait_for_prompt=wait_for_prompt).replace('\\\n','').strip()
546
if z.lower().find("error") != -1:
547
# The following was very tricky to figure out.
548
# When an error occurs using Maple, unfortunately,
549
# Maple also dumps one into the line where the
550
# error occurred with that line copied in. This
551
# totally messes up the pexpect interface. However,
552
# I think the following few lines successfully
553
# "clear things out", i.e., delete the text from
554
# the edit buffer and get a clean prompt.
555
e = self.expect()
556
e.sendline('%s__sage__;'%(chr(8)*len(line)))
557
e.expect('__sage__;')
558
e.expect(self._prompt)
559
raise RuntimeError, "An error occurred running a Maple command:\nINPUT:\n%s\nOUTPUT:\n%s"%(line, z)
560
return z
561
562
def cputime(self, t=None):
563
r"""
564
Returns the amount of CPU time that the Maple session has used. If
565
``t`` is not None, then it returns the difference
566
between the current CPU time and ``t``.
567
568
EXAMPLES::
569
570
sage: t = maple.cputime() # optional - maple
571
sage: t # random; optional - maple
572
0.02
573
sage: x = maple('x') # optional - maple
574
sage: maple.diff(x^2, x) # optional - maple
575
2*x
576
sage: maple.cputime(t) # random; optional - maple
577
0.0
578
"""
579
if t is None:
580
return float(self('time()'))
581
else:
582
return float(self('time() - %s'%float(t)))
583
584
def set(self, var, value):
585
"""
586
Set the variable var to the given value.
587
588
EXAMPLES::
589
590
sage: maple.set('xx', '2') # optional - maple
591
sage: maple.get('xx') # optional - maple
592
'2'
593
"""
594
cmd = '%s:=%s:'%(var,value)
595
out = self.eval(cmd)
596
if out.find("error") != -1:
597
raise TypeError, "Error executing code in Maple\nCODE:\n\t%s\nMaple ERROR:\n\t%s"%(cmd, out)
598
599
def get(self, var):
600
"""
601
Get the value of the variable var.
602
603
EXAMPLES::
604
605
sage: maple.set('xx', '2') # optional - maple
606
sage: maple.get('xx') # optional - maple
607
'2'
608
"""
609
s = self.eval('printf("%%q",%s)'%var)
610
return s
611
612
def _object_class(self):
613
"""
614
Returns the class of MapleElements.
615
616
EXAMPLES::
617
618
sage: maple._object_class()
619
<class 'sage.interfaces.maple.MapleElement'>
620
621
::
622
623
sage: m = maple(2) # optional - maple
624
sage: type(m) # optional - maple
625
<class 'sage.interfaces.maple.MapleElement'>
626
"""
627
return MapleElement
628
629
def _function_element_class(self):
630
"""
631
Returns the MapleFunctionElement class.
632
633
EXAMPLES::
634
635
sage: maple._function_element_class()
636
<class 'sage.interfaces.maple.MapleFunctionElement'>
637
638
::
639
640
sage: two = maple(2) # optional - maple
641
sage: type(two.gcd) # optional - maple
642
<class 'sage.interfaces.maple.MapleFunctionElement'>
643
"""
644
return MapleFunctionElement
645
646
def _equality_symbol(self):
647
"""
648
Returns the symbol used for equality testing in Maple.
649
650
EXAMPLES::
651
652
sage: maple._equality_symbol()
653
'='
654
655
sage: maple(2) == maple(2) # optional - maple
656
True
657
"""
658
return '='
659
660
def _true_symbol(self):
661
"""
662
Returns the symbol used for truth in Maple.
663
664
EXAMPLES::
665
666
sage: maple._true_symbol()
667
'true'
668
669
::
670
671
sage: maple(2) == maple(2) # optional - maple
672
True
673
"""
674
return 'true'
675
676
def _assign_symbol(self):
677
"""
678
Returns the symbol used for assignment in Maple.
679
680
EXAMPLES::
681
682
sage: maple._assign_symbol()
683
':='
684
"""
685
return ":="
686
687
def _source(self, s):
688
"""
689
Tries to return the source code of a Maple function str as a
690
string.
691
692
EXAMPLES::
693
694
sage: print maple._source('curry').strip() # optional - maple
695
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
696
sage: maple._source('ZZZ') # optional - maple
697
Traceback (most recent call last):
698
...
699
Exception: no source code could be found
700
"""
701
cmd = 'echo "interface(verboseproc=2): print(%s);" | maple -q'%s
702
src = os.popen(cmd).read()
703
if src.strip() == s:
704
raise RuntimeError, "no source code could be found"
705
else:
706
return src
707
708
def source(self, s):
709
"""
710
Display the Maple source (if possible) about s. This is the same as
711
returning the output produced by the following Maple commands:
712
713
interface(verboseproc=2): print(s)
714
715
INPUT:
716
717
718
- ``s`` - a string representing the function whose
719
source code you want
720
721
722
EXAMPLES::
723
724
sage: maple.source('curry') #not tested
725
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
726
"""
727
try:
728
pager()(self._source(s))
729
except Exception:
730
pager()('No source code could be found.')
731
732
def _help(self, str):
733
r"""
734
Returns the Maple help on ``str``.
735
736
EXAMPLES::
737
738
sage: maple._help('gcd') # optional - maple
739
"gcd - greatest common divisor of polynomials...
740
"""
741
return os.popen('echo "?%s" | maple -q'%str).read()
742
743
def help(self, str):
744
"""
745
Display Maple help about str. This is the same as typing "?str" in
746
the Maple console.
747
748
INPUT:
749
750
751
- ``str`` - a string to search for in the maple help
752
system
753
754
755
EXAMPLES::
756
757
sage: maple.help('digamma') #not tested
758
Psi - the Digamma and Polygamma functions
759
...
760
"""
761
pager()(self._help(str))
762
763
def with_package(self, package):
764
"""
765
Make a package of Maple procedures available in the interpreter.
766
767
INPUT:
768
769
770
- ``package`` - string
771
772
773
EXAMPLES: Some functions are unknown to Maple until you use with to
774
include the appropriate package.
775
776
::
777
778
sage: maple.quit() # reset maple; optional -- maple
779
sage: maple('partition(10)') # optional - maple
780
partition(10)
781
sage: maple('bell(10)') # optional - maple
782
bell(10)
783
sage: maple.with_package('combinat') # optional - maple
784
sage: maple('partition(10)') # optional - maple
785
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, 1, 1, 2, 2, 3], [1, 2, 2, 2, 3], [1, 1, 1, 1, 3, 3], [1, 1, 2, 3, 3], [2, 2, 3, 3], [1, 3, 3, 3], [1, 1, 1, 1, 1, 1, 4], [1, 1, 1, 1, 2, 4], [1, 1, 2, 2, 4], [2, 2, 2, 4], [1, 1, 1, 3, 4], [1, 2, 3, 4], [3, 3, 4], [1, 1, 4, 4], [2, 4, 4], [1, 1, 1, 1, 1, 5], [1, 1, 1, 2, 5], [1, 2, 2, 5], [1, 1, 3, 5], [2, 3, 5], [1, 4, 5], [5, 5], [1, 1, 1, 1, 6], [1, 1, 2, 6], [2, 2, 6], [1, 3, 6], [4, 6], [1, 1, 1, 7], [1, 2, 7], [3, 7], [1, 1, 8], [2, 8], [1, 9], [10]]
786
sage: maple('bell(10)') # optional - maple
787
115975
788
sage: maple('fibonacci(10)') # optional - maple
789
55
790
"""
791
self.eval('with(%s)'%package)
792
793
load = with_package
794
795
def clear(self, var):
796
"""
797
Clear the variable named var.
798
799
Unfortunately, Maple does not have a clear command. The next best
800
thing is to set equal to the constant 0, so that memory will be
801
freed.
802
803
EXAMPLES::
804
805
sage: maple.set('xx', '2') # optional - maple
806
sage: maple.get('xx') # optional - maple
807
'2'
808
sage: maple.clear('xx') # optional - maple
809
sage: maple.get('xx') # optional - maple
810
'0'
811
"""
812
self.set(var, '0')
813
814
class MapleFunction(ExpectFunction):
815
def _sage_doc_(self):
816
"""
817
Returns the Maple help for this function. This gets called when
818
doing "?" on self.
819
820
EXAMPLES::
821
822
sage: maple.gcd._sage_doc_() # optional - maple
823
"gcd - greatest common divisor of polynomials...
824
"""
825
M = self._parent
826
return M._help(self._name)
827
828
def _sage_src_(self):
829
"""
830
Returns the source code of self. This is the function that
831
eventually gets called when doing maple.gcd?? for example.
832
833
EXAMPLES::
834
835
sage: print maple.curry._sage_src_().strip() # optional - maple
836
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
837
sage: maple.ZZZ._sage_src_() # optional - maple
838
Traceback (most recent call last):
839
...
840
Exception: no source code could be found
841
"""
842
M = self._parent
843
return M._source(self._name)
844
845
class MapleFunctionElement(FunctionElement):
846
def _sage_doc_(self):
847
"""
848
Returns the Maple help for this function. This gets called when
849
doing "?" on self.
850
851
EXAMPLES::
852
853
sage: two = maple(2) # optional - maple
854
sage: two.gcd._sage_doc_() # optional - maple
855
"gcd - greatest common divisor of polynomials...
856
"""
857
return self._obj.parent()._help(self._name)
858
859
def _sage_src_(self):
860
"""
861
Returns the source code of self.
862
863
EXAMPLES::
864
865
sage: g = maple('gcd') # optional - maple
866
sage: print g.curry._sage_src_().strip() # optional - maple
867
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
868
sage: m = maple('2') # optional - maple
869
sage: m.ZZZ._sage_src_() # optional - maple
870
Traceback (most recent call last):
871
...
872
Exception: no source code could be found
873
"""
874
return self._obj.parent()._source(self._name)
875
876
class MapleElement(ExpectElement):
877
def __float__(self):
878
"""
879
Returns a floating point version of self.
880
881
EXAMPLES::
882
883
sage: float(maple(1/2)) # optional - maple
884
0.5
885
sage: type(_) # optional - maple
886
<type 'float'>
887
"""
888
M = self.parent()
889
return float(maple.eval('evalf(%s)'%self.name()))
890
891
def __hash__(self):
892
"""
893
Returns a 64-bit integer representing the hash of self. Since
894
Python uses 32-bit hashes, it will automatically convert the result
895
of this to a 32-bit hash.
896
897
These examples are optional, and require Maple to be installed. You
898
don't need to install any Sage packages for this.
899
900
EXAMPLES::
901
902
sage: m = maple('x^2+y^2') # optional - maple
903
sage: m.__hash__() # optional - maple
904
188724254834261060184983038723355865733L
905
sage: hash(m) # optional - maple
906
5035731711831192733
907
sage: m = maple('x^2+y^3') # optional - maple
908
sage: m.__hash__() # optional - maple
909
264835029579301191531663246434344770556L
910
sage: hash(m) # optional - maple
911
-2187277978252104690
912
"""
913
return int(maple.eval('StringTools:-Hash(convert(%s, string));'%self.name())[1:-1],16)
914
915
def __cmp__(self, other):
916
"""
917
Compare equality between self and other, using maple.
918
919
These examples are optional, and require Maple to be installed. You
920
don't need to install any Sage packages for this.
921
922
EXAMPLES::
923
924
sage: a = maple(5) # optional - maple
925
sage: b = maple(5) # optional - maple
926
sage: a == b # optional - maple
927
True
928
sage: a == 5 # optional - maple
929
True
930
931
::
932
933
sage: c = maple(3) # optional - maple
934
sage: a == c # optional - maple
935
False
936
sage: a < c # optional - maple
937
False
938
sage: a < 6 # optional - maple
939
True
940
sage: c <= a # optional - maple
941
True
942
943
::
944
945
sage: M = matrix(ZZ, 2, range(1,5)) # optional - maple
946
sage: Mm = maple(M) # optional - maple
947
sage: Mm == Mm # optional - maple
948
True
949
sage: Mm < 5 # optional - maple
950
True
951
sage: (Mm < 5) == (M < 5) # optional - maple
952
True
953
sage: 5 < Mm # optional - maple
954
False
955
956
TESTS::
957
958
sage: x = var('x')
959
sage: t = maple((x+1)^2) # optional - maple
960
sage: u = maple(x^2+2*x+1) # optional - maple
961
sage: u == t # todo: not implemented
962
True # returns False, should use 'testeq' in maple
963
sage: maple.eval('testeq(%s = %s)'%(t.name(),u.name())) # optional - maple
964
'true'
965
"""
966
P = self.parent()
967
if P.eval("evalb(%s %s %s)"%(self.name(), P._equality_symbol(),
968
other.name())) == P._true_symbol():
969
return 0
970
# Maple does not allow comparing objects of different types and
971
# it raises an error in this case.
972
# We catch the error, and return True for <
973
try:
974
if P.eval("evalb(%s %s %s)"%(self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol():
975
return -1
976
except RuntimeError, e:
977
msg = str(e)
978
if 'is not valid' in msg and 'to < or <=' in msg:
979
if (hash(str(self)) < hash(str(other))):
980
return -1
981
else:
982
return 1
983
else:
984
raise RuntimeError, e
985
if P.eval("evalb(%s %s %s)"%(self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol():
986
return 1
987
# everything is supposed to be comparable in Python, so we define
988
# the comparison thus when no comparable in interfaced system.
989
if (hash(self) < hash(other)):
990
return -1
991
else:
992
return 1
993
994
def _mul_(self, right):
995
"""
996
These examples are optional, and require Maple to be installed. You
997
don't need to install any Sage packages for this.
998
999
EXAMPLES::
1000
1001
sage: t = maple(5); u = maple(3) # optional - maple
1002
sage: t*u # optional - maple
1003
15
1004
sage: M = matrix(ZZ,2,range(4)) # optional - maple
1005
sage: Mm = maple(M) # optional - maple
1006
sage: Mm*Mm # optional - maple
1007
Matrix(2, 2, [[2,3],[6,11]])
1008
1009
::
1010
1011
sage: v = vector(ZZ,2,[2,3])
1012
sage: vm = maple(v) # optional - maple
1013
sage: vm*Mm # optional - maple
1014
Vector[row](2, [6,11])
1015
1016
::
1017
1018
sage: t*Mm # optional - maple
1019
Matrix(2, 2, [[0,5],[10,15]])
1020
"""
1021
P = self._check_valid()
1022
try:
1023
return P.new('%s . %s'%(self._name, right._name))
1024
except Exception, msg:
1025
raise TypeError,msg
1026
1027
def trait_names(self):
1028
"""
1029
EXAMPLES::
1030
1031
sage: a = maple(2) # optional - maple
1032
sage: 'sin' in a.trait_names() # optional - maple
1033
True
1034
"""
1035
return self.parent().trait_names()
1036
1037
def __repr__(self):
1038
"""
1039
Return a string representation of self.
1040
1041
These examples are optional, and require Maple to be installed. You
1042
don't need to install any Sage packages for this.
1043
1044
EXAMPLES::
1045
1046
sage: x = var('x')
1047
sage: maple(x) # optional - maple
1048
x
1049
sage: maple(5) # optional - maple
1050
5
1051
sage: M = matrix(QQ,2,range(4))
1052
sage: maple(M) # optional - maple
1053
Matrix(2, 2, [[0,1],[2,3]])
1054
"""
1055
self._check_valid()
1056
return self.parent().get(self._name)
1057
1058
def _latex_(self):
1059
r"""
1060
You can output Maple expressions in latex.
1061
1062
EXAMPLES::
1063
1064
sage: print latex(maple('(x^4 - y)/(y^2-3*x)')) # optional - maple
1065
{\frac {{x}^{4}-y}{{y}^{2}-3\,x}}
1066
sage: print latex(maple(pi - e^3)) # optional - maple
1067
\pi - \left( {e^{1}} \right) ^{3}
1068
1069
.. note::
1070
1071
Some expressions might require the Maple style file
1072
``maple2e.sty`` in order to latex correctly.
1073
"""
1074
return self.parent().eval('latex(%s)'%self.name())
1075
1076
def _sage_(self):
1077
r"""
1078
Convert a maple expression back to a Sage expression.
1079
1080
This currently does not implement a parser for the Maple output language,
1081
therefore only very simple expressions will convert successfully.
1082
1083
EXAMPLE::
1084
1085
sage: m = maple('x^2 + 5*y') # optional - maple
1086
sage: m.sage() # optional - maple
1087
x^2 + 5*y
1088
1089
::
1090
1091
sage: m = maple('sin(sqrt(1-x^2)) * (1 - cos(1/x))^2') # optional - maple
1092
sage: m.sage() # optional - maple
1093
(cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1))
1094
1095
"""
1096
result = repr(self)
1097
# The next few lines are a very crude excuse for a maple "parser".
1098
result = result.replace("Pi", "pi")
1099
1100
try:
1101
from sage.symbolic.all import SR
1102
return SR(result)
1103
except Exception:
1104
raise NotImplementedError, "Unable to parse Maple output: %s" % result
1105
1106
# An instance
1107
maple = Maple(script_subdirectory='user')
1108
1109
def reduce_load_Maple():
1110
"""
1111
Returns the maple object created in sage.interfaces.maple.
1112
1113
EXAMPLES::
1114
1115
sage: from sage.interfaces.maple import reduce_load_Maple
1116
sage: reduce_load_Maple()
1117
Maple
1118
"""
1119
return maple
1120
1121
1122
import os
1123
def maple_console():
1124
"""
1125
Spawn a new Maple command-line session.
1126
1127
EXAMPLES::
1128
1129
sage: maple_console() #not tested
1130
|^/| Maple 11 (IBM INTEL LINUX)
1131
._|\| |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc. 2007
1132
\ MAPLE / All rights reserved. Maple is a trademark of
1133
<____ ____> Waterloo Maple Inc.
1134
| Type ? for help.
1135
>
1136
"""
1137
os.system('maple')
1138
1139
1140
def __doctest_cleanup():
1141
"""
1142
EXAMPLES::
1143
1144
sage: from sage.interfaces.maple import __doctest_cleanup
1145
sage: m = maple(2) # optional - maple
1146
sage: maple.is_running() # optional - maple
1147
True
1148
sage: __doctest_cleanup()
1149
sage: maple.is_running()
1150
False
1151
"""
1152
import sage.interfaces.quit
1153
sage.interfaces.quit.expect_quitall()
1154
1155
1156
1157
"""
1158
The following only works in Maple >= 9, I guess, but could
1159
be useful.
1160
1161
From Jaap Spies: In addition Maple has a nice feature the function
1162
1163
> FunctionAdvisor();
1164
1165
> FunctionAdvisor(topics, quiet);
1166
[DE, analytic_extension, asymptotic_expansion, branch_cuts,
1167
branch_points, calling_sequence, class_members,
1168
classify_function, definition, describe, differentiation_rule,
1169
function_classes, identities, integral_form,
1170
known_functions, relate, series, singularities, special_values,
1171
specialize, sum_form, synonyms]
1172
1173
> FunctionAdvisor(syntax, hypergeom);
1174
hypergeom([a, b], [c], z)
1175
1176
Eventually this could be used to do an intelligent command
1177
completion.
1178
"""
1179
1180