Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/interfaces/maxima_lib.py
8814 views
1
r"""
2
Library interface to Maxima
3
4
Maxima is a free GPL'd general purpose computer algebra system whose
5
development started in 1968 at MIT. It contains symbolic manipulation
6
algorithms, as well as implementations of special functions, including
7
elliptic functions and generalized hypergeometric functions. Moreover,
8
Maxima has implementations of many functions relating to the invariant
9
theory of the symmetric group `S_n`. (However, the commands for group
10
invariants, and the corresponding Maxima documentation, are in
11
French.) For many links to Maxima documentation, see
12
http://maxima.sourceforge.net/documentation.html.
13
14
AUTHORS:
15
16
- William Stein (2005-12): Initial version
17
18
- David Joyner: Improved documentation
19
20
- William Stein (2006-01-08): Fixed bug in parsing
21
22
- William Stein (2006-02-22): comparisons (following suggestion of
23
David Joyner)
24
25
- William Stein (2006-02-24): *greatly* improved robustness by adding
26
sequence numbers to IO bracketing in _eval_line
27
28
- Robert Bradshaw, Nils Bruin, Jean-Pierre Flori (2010,2011): Binary library
29
interface
30
31
For this interface, Maxima is loaded into ECL which is itself loaded
32
as a C library in Sage. Translations between Sage and Maxima objects
33
(which are nothing but wrappers to ECL objects) is made as much as possible
34
directly, but falls back to the string based conversion used by the
35
classical Maxima Pexpect interface in case no new implementation has been made.
36
37
This interface is the one used for calculus by Sage
38
and is accessible as `maxima_calculus`::
39
40
sage: maxima_calculus
41
Maxima_lib
42
43
Only one instance of this interface can be instantiated,
44
so the user should not try to instantiate another one,
45
which is anyway set to raise an error::
46
47
sage: from sage.interfaces.maxima_lib import MaximaLib
48
sage: MaximaLib()
49
Traceback (most recent call last):
50
...
51
RuntimeError: Maxima interface in library mode can only be instantiated once
52
"""
53
54
#*****************************************************************************
55
# Copyright (C) 2005 William Stein <[email protected]>
56
#
57
# Distributed under the terms of the GNU General Public License (GPL)
58
#
59
# This code is distributed in the hope that it will be useful,
60
# but WITHOUT ANY WARRANTY; without even the implied warranty of
61
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
62
# General Public License for more details.
63
#
64
# The full text of the GPL is available at:
65
#
66
# http://www.gnu.org/licenses/
67
#*****************************************************************************
68
69
from sage.symbolic.ring import SR, var
70
71
from sage.libs.ecl import *
72
73
from maxima_abstract import (MaximaAbstract, MaximaAbstractFunction,
74
MaximaAbstractElement, MaximaAbstractFunctionElement,
75
MaximaAbstractElementFunction)
76
77
## We begin here by initializing Maxima in library mode
78
## i.e. loading it into ECL
79
ecl_eval("(setf *load-verbose* NIL)")
80
ecl_eval("(require 'maxima)")
81
ecl_eval("(in-package :maxima)")
82
ecl_eval("(setq $nolabels t))")
83
ecl_eval("(defvar *MAXIMA-LANG-SUBDIR* NIL)")
84
ecl_eval("(set-locale-subdir)")
85
ecl_eval("(set-pathnames)")
86
ecl_eval("(defun add-lineinfo (x) x)")
87
ecl_eval('(defun principal nil (cond ($noprincipal (diverg)) ((not pcprntd) (merror "Divergent Integral"))))')
88
ecl_eval("(remprop 'mfactorial 'grind)") # don't use ! for factorials (#11539)
89
ecl_eval("(setf $errormsg nil)")
90
91
# the following is a direct adaption of the definition of "retrieve"
92
# in the Maxima file macsys.lisp. This routine is normally responsible
93
# for displaying a question and returning the answer. We change it to
94
# throw an error in which the text of the question is included. We do
95
# this by running exactly the same code as in the original definition
96
# of "retrieve", but with *standard-output* redirected to a string.
97
ecl_eval(r"""
98
(defun retrieve (msg flag &aux (print? nil))
99
(declare (special msg flag print?))
100
(or (eq flag 'noprint) (setq print? t))
101
(error
102
(concatenate 'string "Maxima asks: "
103
(string-trim '(#\Newline)
104
(with-output-to-string (*standard-output*)
105
(cond ((not print?)
106
(setq print? t)
107
(princ *prompt-prefix*)
108
(princ *prompt-suffix*)
109
)
110
((null msg)
111
(princ *prompt-prefix*)
112
(princ *prompt-suffix*)
113
)
114
((atom msg)
115
(format t "~a~a~a" *prompt-prefix* msg *prompt-suffix*)
116
)
117
((eq flag t)
118
(princ *prompt-prefix*)
119
(mapc #'princ (cdr msg))
120
(princ *prompt-suffix*)
121
)
122
(t
123
(princ *prompt-prefix*)
124
(displa msg)
125
(princ *prompt-suffix*)
126
)
127
))))
128
)
129
)
130
""")
131
132
## Redirection of ECL and Maxima stdout to /dev/null
133
ecl_eval(r"""(defparameter *dev-null* (make-two-way-stream
134
(make-concatenated-stream) (make-broadcast-stream)))""")
135
ecl_eval("(setf original-standard-output *standard-output*)")
136
ecl_eval("(setf *standard-output* *dev-null*)")
137
#ecl_eval("(setf *error-output* *dev-null*)")
138
139
## Default options set in Maxima
140
# display2d -- no ascii art output
141
# keepfloat -- don't automatically convert floats to rationals
142
init_code = ['display2d : false', 'domain : complex', 'keepfloat : true',
143
'load(to_poly_solve)', 'load(simplify_sum)',
144
'load(abs_integrate)']
145
146
# Turn off the prompt labels, since computing them *very
147
# dramatically* slows down the maxima interpret after a while.
148
# See the function makelabel in suprv1.lisp.
149
# Many thanks to [email protected] and also
150
# Robert Dodier for figuring this out!
151
# See trac # 6818.
152
init_code.append('nolabels : true')
153
for l in init_code:
154
ecl_eval("#$%s$"%l)
155
## To get more debug information uncomment the next line
156
## should allow to do this through a method
157
#ecl_eval("(setf *standard-output* original-standard-output)")
158
159
## This is the main function (ECL object) used for evaluation
160
# This returns an EclObject
161
maxima_eval=ecl_eval("""
162
(defun maxima-eval( form )
163
(let ((result (catch 'macsyma-quit (cons 'maxima_eval (meval form)))))
164
;(princ (list "result=" result))
165
;(terpri)
166
;(princ (list "$error=" $error))
167
;(terpri)
168
(cond
169
((and (consp result) (eq (car result) 'maxima_eval)) (cdr result))
170
((eq result 'maxima-error)
171
(let ((the-jig (process-error-argl (cddr $error))))
172
(mapc #'set (car the-jig) (cadr the-jig))
173
(error (concatenate 'string
174
"Error executing code in Maxima: "
175
(with-output-to-string (stream)
176
(apply #'mformat stream (cadr $error)
177
(caddr the-jig)))))
178
))
179
(t
180
(let ((the-jig (process-error-argl (cddr $error))))
181
(mapc #'set (car the-jig) (cadr the-jig))
182
(error (concatenate 'string "Maxima condition. result:"
183
(princ-to-string result) "$error:"
184
(with-output-to-string (stream)
185
(apply #'mformat stream (cadr $error)
186
(caddr the-jig)))))
187
))
188
)
189
)
190
)
191
""")
192
193
## Number of instances of this interface
194
maxima_lib_instances = 0
195
196
## Here we define several useful ECL/Maxima objects
197
# The Maxima string function can change the structure of its input
198
#maxprint=EclObject("$STRING")
199
maxprint=EclObject(r"""(defun mstring-for-sage (form)
200
(coerce (mstring form) 'string))""").eval()
201
meval=EclObject("MEVAL")
202
msetq=EclObject("MSETQ")
203
mlist=EclObject("MLIST")
204
mequal=EclObject("MEQUAL")
205
cadadr=EclObject("CADADR")
206
207
max_integrate=EclObject("$INTEGRATE")
208
max_sum=EclObject("$SUM")
209
max_simplify_sum=EclObject("$SIMPLIFY_SUM")
210
max_ratsimp=EclObject("$RATSIMP")
211
max_limit=EclObject("$LIMIT")
212
max_tlimit=EclObject("$TLIMIT")
213
max_plus=EclObject("$PLUS")
214
max_minus=EclObject("$MINUS")
215
max_use_grobner=EclObject("$USE_GROBNER")
216
max_to_poly_solve=EclObject("$TO_POLY_SOLVE")
217
max_at=EclObject("%AT")
218
219
def stdout_to_string(s):
220
r"""
221
Evaluate command ``s`` and catch Maxima stdout
222
(not the result of the command!) into a string.
223
224
INPUT:
225
226
- ``s`` - string; command to evaluate
227
228
OUTPUT: string
229
230
This is currently used to implement :meth:`~MaximaLibElement.display2d`.
231
232
EXAMPLES::
233
234
sage: from sage.interfaces.maxima_lib import stdout_to_string
235
sage: stdout_to_string('1+1')
236
''
237
sage: stdout_to_string('disp(1+1)')
238
'2\n\n'
239
"""
240
return ecl_eval(r"""(with-output-to-string (*standard-output*)
241
(maxima-eval #$%s$))"""%s).python()[1:-1]
242
243
def max_to_string(s):
244
r"""
245
Return the Maxima string corresponding to this ECL object.
246
247
INPUT:
248
249
- ``s`` - ECL object
250
251
OUTPUT: string
252
253
EXAMPLES::
254
255
sage: from sage.interfaces.maxima_lib import maxima_lib, max_to_string
256
sage: ecl = maxima_lib(cos(x)).ecl()
257
sage: max_to_string(ecl)
258
'cos(x)'
259
"""
260
return maxprint(s).python()[1:-1]
261
262
my_mread=ecl_eval("""
263
(defun my-mread (cmd)
264
(caddr (mread (make-string-input-stream cmd))))
265
""")
266
267
def parse_max_string(s):
268
r"""
269
Evaluate string in Maxima without *any* further simplification.
270
271
INPUT:
272
273
- ``s`` - string
274
275
OUTPUT: ECL object
276
277
EXAMPLES::
278
279
sage: from sage.interfaces.maxima_lib import parse_max_string
280
sage: parse_max_string('1+1')
281
<ECL: ((MPLUS) 1 1)>
282
"""
283
return my_mread('"%s;"'%s)
284
285
class MaximaLib(MaximaAbstract):
286
"""
287
Interface to Maxima as a Library.
288
289
INPUT: none
290
291
OUTPUT: Maxima interface as a Library
292
293
EXAMPLES::
294
295
sage: from sage.interfaces.maxima_lib import MaximaLib, maxima_lib
296
sage: isinstance(maxima_lib,MaximaLib)
297
True
298
299
Only one such interface can be instantiated::
300
301
sage: MaximaLib()
302
Traceback (most recent call last):
303
...
304
RuntimeError: Maxima interface in library mode can only
305
be instantiated once
306
"""
307
def __init__(self):
308
"""
309
Create an instance of the Maxima interpreter.
310
See ``MaximaLib`` for full documentation.
311
312
TESTS::
313
314
sage: from sage.interfaces.maxima_lib import MaximaLib, maxima_lib
315
sage: MaximaLib == loads(dumps(MaximaLib))
316
True
317
sage: maxima_lib == loads(dumps(maxima_lib))
318
True
319
320
We make sure labels are turned off (see :trac:`6816`)::
321
322
sage: 'nolabels : true' in maxima_lib._MaximaLib__init_code
323
True
324
"""
325
global maxima_lib_instances
326
if maxima_lib_instances > 0:
327
raise RuntimeError, "Maxima interface in library mode can only be instantiated once"
328
maxima_lib_instances += 1
329
330
global init_code
331
self.__init_code = init_code
332
333
MaximaAbstract.__init__(self,"maxima_lib")
334
self.__seq = 0
335
336
def _coerce_from_special_method(self, x):
337
r"""
338
Coerce ``x`` into self trying to call a special underscore method.
339
340
INPUT:
341
342
- ``x`` - object to coerce into self
343
344
OUTPUT: Maxima element equivalent to ``x``
345
346
EXAMPLES::
347
348
sage: from sage.interfaces.maxima_lib import maxima_lib
349
sage: xmax = maxima_lib._coerce_from_special_method(x)
350
sage: type(xmax)
351
<class 'sage.interfaces.maxima_lib.MaximaLibElement'>
352
"""
353
if isinstance(x, EclObject):
354
return MaximaLibElement(self,self._create(x))
355
else:
356
return MaximaAbstract._coerce_from_special_method(self,x)
357
358
def __reduce__(self):
359
r"""
360
Implement __reduce__ for ``MaximaLib``.
361
362
INPUT: none
363
364
OUTPUT:
365
366
A couple consisting of:
367
368
- the function to call for unpickling
369
370
- a tuple of arguments for the function
371
372
EXAMPLES::
373
374
sage: from sage.interfaces.maxima_lib import maxima_lib
375
sage: maxima_lib.__reduce__()
376
(<function reduce_load_MaximaLib at 0x...>, ())
377
"""
378
return reduce_load_MaximaLib, tuple([])
379
380
# This outputs a string
381
def _eval_line(self, line, locals=None, reformat=True, **kwds):
382
r"""
383
Evaluate the line in Maxima.
384
385
INPUT:
386
387
- ``line`` - string; text to evaluate
388
389
- ``locals`` - None (ignored); this is used for compatibility with the
390
Sage notebook's generic system interface.
391
392
- ``reformat`` - boolean; whether to strip output or not
393
394
- ``**kwds`` - All other arguments are currently ignored.
395
396
OUTPUT: string representing Maxima output
397
398
EXAMPLES::
399
400
sage: from sage.interfaces.maxima_lib import maxima_lib
401
sage: maxima_lib._eval_line('1+1')
402
'2'
403
sage: maxima_lib._eval_line('1+1;')
404
'2'
405
sage: maxima_lib._eval_line('1+1$')
406
''
407
sage: maxima_lib._eval_line('randvar : cos(x)+sin(y)$')
408
''
409
sage: maxima_lib._eval_line('randvar')
410
'sin(y)+cos(x)'
411
"""
412
result = ''
413
while line:
414
ind_dollar=line.find("$")
415
ind_semi=line.find(";")
416
if ind_dollar == -1 or (ind_semi >=0 and ind_dollar > ind_semi):
417
if ind_semi == -1:
418
statement = line
419
line = ''
420
else:
421
statement = line[:ind_semi]
422
line = line[ind_semi+1:]
423
if statement: result = ((result + '\n') if result else '') + max_to_string(maxima_eval("#$%s$"%statement))
424
else:
425
statement = line[:ind_dollar]
426
line = line[ind_dollar+1:]
427
if statement: _ = maxima_eval("#$%s$"%statement)
428
if not reformat:
429
return result
430
return ''.join([x.strip() for x in result.split()])
431
432
eval = _eval_line
433
434
###########################################
435
# Direct access to underlying lisp interpreter.
436
###########################################
437
def lisp(self, cmd):
438
"""
439
Send a lisp command to maxima.
440
441
INPUT:
442
443
- ``cmd`` - string
444
445
OUTPUT: ECL object
446
447
.. note::
448
449
The output of this command is very raw - not pretty.
450
451
EXAMPLES::
452
453
sage: from sage.interfaces.maxima_lib import maxima_lib
454
sage: maxima_lib.lisp("(+ 2 17)")
455
<ECL: 19>
456
"""
457
return ecl_eval(cmd)
458
459
def set(self, var, value):
460
"""
461
Set the variable var to the given value.
462
463
INPUT:
464
465
- ``var`` - string
466
467
- ``value`` - string
468
469
OUTPUT: none
470
471
EXAMPLES::
472
473
sage: from sage.interfaces.maxima_lib import maxima_lib
474
sage: maxima_lib.set('xxxxx', '2')
475
sage: maxima_lib.get('xxxxx')
476
'2'
477
"""
478
if not isinstance(value, str):
479
raise TypeError
480
cmd = '%s : %s$'%(var, value.rstrip(';'))
481
self.eval(cmd)
482
483
def clear(self, var):
484
"""
485
Clear the variable named var.
486
487
INPUT:
488
489
- ``var`` - string
490
491
OUTPUT: none
492
493
EXAMPLES::
494
495
sage: from sage.interfaces.maxima_lib import maxima_lib
496
sage: maxima_lib.set('xxxxx', '2')
497
sage: maxima_lib.get('xxxxx')
498
'2'
499
sage: maxima_lib.clear('xxxxx')
500
sage: maxima_lib.get('xxxxx')
501
'xxxxx'
502
"""
503
try:
504
self.eval('kill(%s)$'%var)
505
except (TypeError, AttributeError):
506
pass
507
508
def get(self, var):
509
"""
510
Get the string value of the variable ``var``.
511
512
INPUT:
513
514
- ``var`` - string
515
516
OUTPUT: string
517
518
EXAMPLES::
519
520
sage: from sage.interfaces.maxima_lib import maxima_lib
521
sage: maxima_lib.set('xxxxx', '2')
522
sage: maxima_lib.get('xxxxx')
523
'2'
524
"""
525
s = self.eval('%s;'%var)
526
return s
527
528
def _create(self, value, name=None):
529
r"""
530
Create a variable with given value and name.
531
532
INPUT:
533
534
- ``value`` - string or ECL object
535
536
- ``name`` - string (default: None); name to use for the variable,
537
an automatically generated name is used if this is none
538
539
OUTPUT:
540
541
- string; the name of the created variable
542
543
EXAMPLES:
544
545
Creation from strings::
546
547
sage: from sage.interfaces.maxima_lib import maxima_lib
548
sage: maxima_lib._create('3','var3')
549
'var3'
550
sage: maxima_lib.get('var3')
551
'3'
552
sage: s = maxima_lib._create('3')
553
sage: s # random output
554
'sage9'
555
sage: s[:4] == 'sage'
556
True
557
558
And from ECL object::
559
560
sage: c = maxima_lib(x+cos(19)).ecl()
561
sage: maxima_lib._create(c,'m')
562
'm'
563
sage: maxima_lib.get('m')
564
'x+cos(19)'
565
"""
566
name = self._next_var_name() if name is None else name
567
if isinstance(value,EclObject):
568
maxima_eval([[msetq],cadadr("#$%s$#$"%name),value])
569
else:
570
self.set(name, value)
571
return name
572
573
def _function_class(self):
574
r"""
575
Return the Python class of Maxima functions.
576
577
INPUT: none
578
579
OUTPUT: type
580
581
EXAMPLES::
582
583
sage: from sage.interfaces.maxima_lib import maxima_lib
584
sage: maxima_lib._function_class()
585
<class 'sage.interfaces.maxima_lib.MaximaLibFunction'>
586
"""
587
return MaximaLibFunction
588
589
def _object_class(self):
590
r"""
591
Return the Python class of Maxima elements.
592
593
INPUT: none
594
595
OUTPUT: type
596
597
EXAMPLES::
598
599
sage: from sage.interfaces.maxima_lib import maxima_lib
600
sage: maxima_lib._object_class()
601
<class 'sage.interfaces.maxima_lib.MaximaLibElement'>
602
"""
603
return MaximaLibElement
604
605
def _function_element_class(self):
606
r"""
607
Return the Python class of Maxima functions of elements.
608
609
INPUT: none
610
611
OUTPUT: type
612
613
EXAMPLES::
614
615
sage: from sage.interfaces.maxima_lib import maxima_lib
616
sage: maxima_lib._function_element_class()
617
<class 'sage.interfaces.maxima_lib.MaximaLibFunctionElement'>
618
"""
619
return MaximaLibFunctionElement
620
621
def _object_function_class(self):
622
r"""
623
Return the Python class of Maxima user-defined functions.
624
625
INPUT: none
626
627
OUTPUT: type
628
629
EXAMPLES::
630
631
sage: from sage.interfaces.maxima_lib import maxima_lib
632
sage: maxima_lib._object_function_class()
633
<class 'sage.interfaces.maxima_lib.MaximaLibElementFunction'>
634
"""
635
return MaximaLibElementFunction
636
637
## some helper functions to wrap the calculus use of the maxima interface.
638
## these routines expect arguments living in the symbolic ring
639
## and return something that is hopefully coercible into the symbolic
640
## ring again.
641
642
def sr_integral(self,*args):
643
"""
644
Helper function to wrap calculus use of Maxima's integration.
645
646
TESTS::
647
648
sage: a,b=var('a,b')
649
sage: integrate(1/(x^3 *(a+b*x)^(1/3)),x)
650
Traceback (most recent call last):
651
...
652
ValueError: Computation failed since Maxima requested additional
653
constraints; using the 'assume' command before integral evaluation
654
*may* help (example of legal syntax is 'assume(a>0)', see
655
`assume?` for more details)
656
Is a positive or negative?
657
sage: assume(a>0)
658
sage: integrate(1/(x^3 *(a+b*x)^(1/3)),x)
659
2/9*sqrt(3)*b^2*arctan(1/3*sqrt(3)*(2*(b*x + a)^(1/3) + a^(1/3))/a^(1/3))/a^(7/3) - 1/9*b^2*log((b*x + a)^(2/3) + (b*x + a)^(1/3)*a^(1/3) + a^(2/3))/a^(7/3) + 2/9*b^2*log((b*x + a)^(1/3) - a^(1/3))/a^(7/3) + 1/6*(4*(b*x + a)^(5/3)*b^2 - 7*(b*x + a)^(2/3)*a*b^2)/((b*x + a)^2*a^2 - 2*(b*x + a)*a^3 + a^4)
660
sage: var('x, n')
661
(x, n)
662
sage: integral(x^n,x)
663
Traceback (most recent call last):
664
...
665
ValueError: Computation failed since Maxima requested additional
666
constraints; using the 'assume' command before integral evaluation
667
*may* help (example of legal syntax is 'assume(n+1>0)',
668
see `assume?` for more details)
669
Is n+1 zero or nonzero?
670
sage: assume(n+1>0)
671
sage: integral(x^n,x)
672
x^(n + 1)/(n + 1)
673
sage: forget()
674
sage: assumptions() # Check the assumptions really were forgotten
675
[]
676
677
Make sure the abs_integrate package is being used,
678
:trac:`11483`. The following are examples from the Maxima
679
abs_integrate documentation::
680
681
sage: integrate(abs(x), x)
682
1/2*x*abs(x)
683
684
::
685
686
sage: integrate(sgn(x) - sgn(1-x), x)
687
abs(x - 1) + abs(x)
688
689
::
690
691
sage: integrate(1 / (1 + abs(x-5)), x, -5, 6)
692
log(11) + log(2)
693
694
::
695
696
sage: integrate(1/(1 + abs(x)), x)
697
1/2*(log(x + 1) + log(-x + 1))*sgn(x) + 1/2*log(x + 1) - 1/2*log(-x + 1)
698
699
::
700
701
sage: integrate(cos(x + abs(x)), x)
702
-1/2*x*sgn(x) + 1/4*(sgn(x) + 1)*sin(2*x) + 1/2*x
703
704
An example from sage-support thread e641001f8b8d1129::
705
706
sage: f = e^(-x^2/2)/sqrt(2*pi) * sgn(x-1)
707
sage: integrate(f, x, -Infinity, Infinity)
708
-erf(1/2*sqrt(2))
709
710
From :trac:`8624`::
711
712
sage: integral(abs(cos(x))*sin(x),(x,pi/2,pi))
713
1/2
714
715
::
716
717
sage: integrate(sqrt(x + sqrt(x)), x).simplify_radical()
718
1/12*((8*x - 3)*x^(1/4) + 2*x^(3/4))*sqrt(sqrt(x) + 1) + 1/8*log(sqrt(sqrt(x) + 1) + x^(1/4)) - 1/8*log(sqrt(sqrt(x) + 1) - x^(1/4))
719
720
And :trac:`11594`::
721
722
sage: integrate(abs(x^2 - 1), x, -2, 2)
723
4
724
725
This definite integral returned zero (incorrectly) in at least
726
maxima-5.23. The correct answer is now given (:trac:`11591`)::
727
728
sage: f = (x^2)*exp(x) / (1+exp(x))^2
729
sage: integrate(f, (x, -infinity, infinity))
730
1/3*pi^2
731
732
"""
733
try:
734
return max_to_sr(maxima_eval(([max_integrate],[sr_to_max(SR(a)) for a in args])))
735
except RuntimeError, error:
736
s = str(error)
737
if "Divergent" in s or "divergent" in s:
738
# in pexpect interface, one looks for this - e.g. integrate(1/x^3,x,-1,3) gives a principal value
739
# if "divergent" in s or 'Principal Value' in s:
740
raise ValueError, "Integral is divergent."
741
elif "Is" in s: # Maxima asked for a condition
742
j = s.find('Is ')
743
s = s[j:]
744
k = s.find(' ',4)
745
raise ValueError, "Computation failed since Maxima requested additional constraints; using the 'assume' command before integral evaluation *may* help (example of legal syntax is 'assume(" + s[4:k] +">0)', see `assume?` for more details)\n" + s
746
else:
747
raise error
748
749
def sr_sum(self,*args):
750
"""
751
Helper function to wrap calculus use of Maxima's summation.
752
753
TESTS::
754
755
sage: x, y, k, n = var('x, y, k, n')
756
sage: sum(binomial(n,k) * x^k * y^(n-k), k, 0, n)
757
(x + y)^n
758
sage: q, a = var('q, a')
759
sage: sum(a*q^k, k, 0, oo)
760
Traceback (most recent call last):
761
...
762
ValueError: Computation failed since Maxima requested additional
763
constraints; using the 'assume' command before summation *may* help
764
(example of legal syntax is 'assume(abs(q)-1>0)', see `assume?`
765
for more details)
766
Is abs(q)-1 positive, negative, or zero?
767
sage: assume(q > 1)
768
sage: sum(a*q^k, k, 0, oo)
769
Traceback (most recent call last):
770
...
771
ValueError: Sum is divergent.
772
sage: forget()
773
sage: assume(abs(q) < 1)
774
sage: sum(a*q^k, k, 0, oo)
775
-a/(q - 1)
776
sage: forget()
777
sage: assumptions() # check the assumptions were really forgotten
778
[]
779
"""
780
try:
781
return max_to_sr(maxima_eval([[max_ratsimp],[[max_simplify_sum],([max_sum],[sr_to_max(SR(a)) for a in args])]]));
782
except RuntimeError, error:
783
s = str(error)
784
if "divergent" in s:
785
# in pexpect interface, one looks for this;
786
# could not find an example where 'Pole encountered' occurred, though
787
# if "divergent" in s or 'Pole encountered' in s:
788
raise ValueError, "Sum is divergent."
789
elif "Is" in s: # Maxima asked for a condition
790
j = s.find('Is ')
791
s = s[j:]
792
k = s.find(' ',4)
793
raise ValueError, "Computation failed since Maxima requested additional constraints; using the 'assume' command before summation *may* help (example of legal syntax is 'assume(" + s[4:k] +">0)', see `assume?` for more details)\n" + s
794
else:
795
raise error
796
797
def sr_limit(self,expr,v,a,dir=None):
798
"""
799
Helper function to wrap calculus use of Maxima's limits.
800
801
TESTS::
802
803
sage: f = (1+1/x)^x
804
sage: limit(f,x = oo)
805
e
806
sage: limit(f,x = 5)
807
7776/3125
808
sage: limit(f,x = 1.2)
809
2.06961575467...
810
sage: var('a')
811
a
812
sage: limit(x^a,x=0)
813
Traceback (most recent call last):
814
...
815
ValueError: Computation failed since Maxima requested additional
816
constraints; using the 'assume' command before limit evaluation
817
*may* help (see `assume?` for more details)
818
Is a positive, negative, or zero?
819
sage: assume(a>0)
820
sage: limit(x^a,x=0)
821
Traceback (most recent call last):
822
...
823
ValueError: Computation failed since Maxima requested additional
824
constraints; using the 'assume' command before limit evaluation
825
*may* help (see `assume?` for more details)
826
Is a an integer?
827
sage: assume(a,'integer')
828
sage: assume(a,'even') # Yes, Maxima will ask this too
829
sage: limit(x^a,x=0)
830
0
831
sage: forget()
832
sage: assumptions() # check the assumptions were really forgotten
833
[]
834
835
The second limit below was computed incorrectly prior to
836
maxima-5.24 (:trac:`10868`)::
837
838
sage: f(n) = 2 + 1/factorial(n)
839
sage: limit(f(n), n=infinity)
840
2
841
sage: limit(1/f(n), n=infinity)
842
1/2
843
844
"""
845
try:
846
L=[sr_to_max(SR(a)) for a in [expr,v,a]]
847
if dir == "plus":
848
L.append(max_plus)
849
elif dir == "minus":
850
L.append(max_minus)
851
return max_to_sr(maxima_eval(([max_limit],L)))
852
except RuntimeError, error:
853
s = str(error)
854
if "Is" in s: # Maxima asked for a condition
855
j = s.find('Is ')
856
s = s[j:]
857
raise ValueError, "Computation failed since Maxima requested additional constraints; using the 'assume' command before limit evaluation *may* help (see `assume?` for more details)\n" + s
858
else:
859
raise error
860
861
def sr_tlimit(self,expr,v,a,dir=None):
862
"""
863
Helper function to wrap calculus use of Maxima's Taylor series limits.
864
865
TESTS::
866
867
sage: f = (1+1/x)^x
868
sage: limit(f, x = I, taylor=True)
869
(-I + 1)^I
870
"""
871
L=[sr_to_max(SR(a)) for a in [expr,v,a]]
872
if dir == "plus":
873
L.append(max_plus)
874
elif dir == "minus":
875
L.append(max_minus)
876
return max_to_sr(maxima_eval(([max_tlimit],L)))
877
878
879
def is_MaximaLibElement(x):
880
r"""
881
Returns True if x is of type MaximaLibElement.
882
883
EXAMPLES::
884
885
sage: from sage.interfaces.maxima_lib import maxima_lib, is_MaximaLibElement
886
sage: m = maxima_lib(1)
887
sage: is_MaximaLibElement(m)
888
True
889
sage: is_MaximaLibElement(1)
890
False
891
"""
892
return isinstance(x, MaximaLibElement)
893
894
class MaximaLibElement(MaximaAbstractElement):
895
r"""
896
Element of Maxima through library interface.
897
898
EXAMPLES:
899
900
Elements of this class should not be created directly.
901
The targeted parent should be used instead::
902
903
sage: from sage.interfaces.maxima_lib import maxima_lib
904
sage: maxima_lib(4)
905
4
906
sage: maxima_lib(log(x))
907
log(x)
908
"""
909
910
def ecl(self):
911
r"""
912
Return the underlying ECL object of this MaximaLib object.
913
914
INPUT: none
915
916
OUTPUT: ECL object
917
918
EXAMPLES::
919
920
sage: from sage.interfaces.maxima_lib import maxima_lib
921
sage: maxima_lib(x+cos(19)).ecl()
922
<ECL: ((MPLUS SIMP) ((%COS SIMP) 19) $X)>
923
"""
924
try:
925
return self._ecl
926
except AttributeError:
927
self._ecl=maxima_eval("#$%s$"%self._name)
928
return self._ecl
929
930
def to_poly_solve(self,vars,options=""):
931
r"""
932
Use Maxima's to_poly_solver package.
933
934
INPUT:
935
936
- ``vars`` - symbolic expressions
937
938
- ``options`` - string (default="")
939
940
OUTPUT: Maxima object
941
942
EXAMPLES:
943
944
The zXXX below are names for arbitrary integers and
945
subject to change::
946
947
sage: from sage.interfaces.maxima_lib import maxima_lib
948
sage: sol = maxima_lib(sin(x) == 0).to_poly_solve(x)
949
sage: sol.sage()
950
[[x == pi + 2*pi*z60], [x == 2*pi*z62]]
951
"""
952
if options.find("use_grobner=true") != -1:
953
cmd=EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars),
954
[[mequal],max_use_grobner,True]])
955
else:
956
cmd=EclObject([[max_to_poly_solve], self.ecl(), sr_to_max(vars)])
957
return self.parent()(maxima_eval(cmd))
958
959
def display2d(self, onscreen=True):
960
r"""
961
Return the 2d representation of this Maxima object.
962
963
INPUT:
964
965
- ``onscreen`` - boolean (default: True); whether to print or return
966
967
OUTPUT:
968
969
The representation is printed if onscreen is set to True
970
and returned as a string otherwise.
971
972
EXAMPLES::
973
974
sage: from sage.interfaces.maxima_lib import maxima_lib
975
sage: F = maxima_lib('x^5 - y^5').factor()
976
sage: F.display2d()
977
4 3 2 2 3 4
978
- (y - x) (y + x y + x y + x y + x )
979
"""
980
self._check_valid()
981
P = self.parent()
982
P._eval_line('display2d : true$')
983
s = stdout_to_string('disp(%s)'%self.name())
984
#s = P._eval_line('disp(%s)$'%self.name())
985
P._eval_line('display2d : false$')
986
s = s.strip('\r\n')
987
988
# if ever want to dedent, see
989
# http://mail.python.org/pipermail/python-list/2006-December/420033.html
990
if onscreen:
991
print s
992
else:
993
return s
994
995
996
class MaximaLibFunctionElement(MaximaAbstractFunctionElement):
997
pass
998
999
1000
class MaximaLibFunction(MaximaAbstractFunction):
1001
pass
1002
1003
1004
class MaximaLibElementFunction(MaximaLibElement, MaximaAbstractElementFunction):
1005
pass
1006
1007
1008
# The (unique) instance
1009
maxima_lib = MaximaLib()
1010
maxima = maxima_lib
1011
1012
1013
def reduce_load_MaximaLib():
1014
r"""
1015
Unpickle the (unique) Maxima library interface.
1016
1017
EXAMPLES::
1018
1019
sage: from sage.interfaces.maxima_lib import reduce_load_MaximaLib
1020
sage: reduce_load_MaximaLib()
1021
Maxima_lib
1022
"""
1023
return maxima_lib
1024
1025
1026
#############################################
1027
# Smart translations between SR and Maxima
1028
#############################################
1029
1030
import sage.rings.real_double
1031
import sage.symbolic.expression
1032
import sage.functions.trig
1033
import sage.functions.log
1034
import sage.functions.other
1035
import sage.symbolic.integration.integral
1036
from sage.symbolic.operators import FDerivativeOperator
1037
1038
car=EclObject("car")
1039
cdr=EclObject("cdr")
1040
caar=EclObject("caar")
1041
cadr=EclObject("cadr")
1042
cddr=EclObject("cddr")
1043
caddr=EclObject("caddr")
1044
caaadr=EclObject("caaadr")
1045
cadadr=EclObject("cadadr")
1046
meval=EclObject("meval")
1047
NIL=EclObject("NIL")
1048
1049
## Dictionaries for standard operators
1050
sage_op_dict = {
1051
sage.symbolic.expression.operator.abs : "MABS",
1052
sage.symbolic.expression.operator.add : "MPLUS",
1053
sage.symbolic.expression.operator.div : "MQUOTIENT",
1054
sage.symbolic.expression.operator.eq : "MEQUAL",
1055
sage.symbolic.expression.operator.ge : "MGEQP",
1056
sage.symbolic.expression.operator.gt : "MGREATERP",
1057
sage.symbolic.expression.operator.le : "MLEQP",
1058
sage.symbolic.expression.operator.lt : "MLESSP",
1059
sage.symbolic.expression.operator.mul : "MTIMES",
1060
sage.symbolic.expression.operator.ne : "MNOTEQUAL",
1061
sage.symbolic.expression.operator.neg : "MMINUS",
1062
sage.symbolic.expression.operator.pow : "MEXPT",
1063
sage.symbolic.expression.operator.or_ : "MOR",
1064
sage.symbolic.expression.operator.and_ : "MAND",
1065
sage.functions.trig.acos : "%ACOS",
1066
sage.functions.trig.acot : "%ACOT",
1067
sage.functions.trig.acsc : "%ACSC",
1068
sage.functions.trig.asec : "%ASEC",
1069
sage.functions.trig.asin : "%ASIN",
1070
sage.functions.trig.atan : "%ATAN",
1071
sage.functions.trig.cos : "%COS",
1072
sage.functions.trig.cot : "%COT",
1073
sage.functions.trig.csc : "%CSC",
1074
sage.functions.trig.sec : "%SEC",
1075
sage.functions.trig.sin : "%SIN",
1076
sage.functions.trig.tan : "%TAN",
1077
sage.functions.log.exp : "%EXP",
1078
sage.functions.log.ln : "%LOG",
1079
sage.functions.log.log : "%LOG",
1080
sage.functions.log.lambert_w : "%LAMBERT_W",
1081
sage.functions.other.factorial : "MFACTORIAL",
1082
sage.functions.other.erf : "%ERF",
1083
sage.functions.other.gamma_inc : "%GAMMA_INCOMPLETE",
1084
}
1085
#we compile the dictionary
1086
sage_op_dict = dict([(k,EclObject(sage_op_dict[k])) for k in sage_op_dict])
1087
max_op_dict = dict([(sage_op_dict[k],k) for k in sage_op_dict])
1088
1089
1090
## Here we correct the dictionaries for some simple operators
1091
def add_vararg(*args):
1092
r"""
1093
Addition of a variable number of arguments.
1094
1095
INPUT:
1096
1097
- ``args`` - arguments to add
1098
1099
OUTPUT: sum of arguments
1100
1101
EXAMPLES::
1102
1103
sage: from sage.interfaces.maxima_lib import add_vararg
1104
sage: add_vararg(1,2,3,4,5,6,7)
1105
28
1106
"""
1107
S=0
1108
for a in args:
1109
S=S+a
1110
return S
1111
1112
def mul_vararg(*args):
1113
r"""
1114
Multiplication of a variable number of arguments.
1115
1116
INPUT:
1117
1118
- ``args`` - arguments to multiply
1119
1120
OUTPUT: product of arguments
1121
1122
EXAMPLES::
1123
1124
sage: from sage.interfaces.maxima_lib import mul_vararg
1125
sage: mul_vararg(9,8,7,6,5,4)
1126
60480
1127
"""
1128
P=1
1129
for a in args:
1130
P=P*a
1131
return P
1132
1133
def sage_rat(x,y):
1134
r"""
1135
Return quotient x/y.
1136
1137
INPUT:
1138
1139
- ``x`` - integer
1140
1141
- ``y`` - integer
1142
1143
OUTPUT: rational
1144
1145
EXAMPLES::
1146
1147
sage: from sage.interfaces.maxima_lib import sage_rat
1148
sage: sage_rat(1,7)
1149
1/7
1150
"""
1151
return x/y
1152
1153
mplus=EclObject("MPLUS")
1154
mtimes=EclObject("MTIMES")
1155
rat=EclObject("RAT")
1156
max_op_dict[mplus]=add_vararg
1157
max_op_dict[mtimes]=mul_vararg
1158
max_op_dict[rat]=sage_rat
1159
1160
1161
## Here we build dictionaries for operators needing special conversions.
1162
ratdisrep=EclObject("ratdisrep")
1163
mrat=EclObject("MRAT")
1164
mqapply=EclObject("MQAPPLY")
1165
max_li=EclObject("$LI")
1166
max_psi=EclObject("$PSI")
1167
max_array=EclObject("ARRAY")
1168
mdiff=EclObject("%DERIVATIVE")
1169
max_lambert_w=sage_op_dict[sage.functions.log.lambert_w]
1170
1171
def mrat_to_sage(expr):
1172
r"""
1173
Convert a Maxima MRAT expression to Sage SR.
1174
1175
INPUT:
1176
1177
- ``expr`` - ECL object; a Maxima MRAT expression
1178
1179
OUTPUT: symbolic expression
1180
1181
Maxima has an optimised representation for multivariate
1182
rational expressions. The easiest way to translate those
1183
to SR is by first asking Maxima to give the generic representation
1184
of the object. That is what RATDISREP does in Maxima.
1185
1186
EXAMPLES::
1187
1188
sage: from sage.interfaces.maxima_lib import maxima_lib, mrat_to_sage
1189
sage: var('x y z')
1190
(x, y, z)
1191
sage: c = maxima_lib((x+y^2+z^9)/x^6+z^8/y).rat()
1192
sage: c
1193
(y*z^9+x^6*z^8+y^3+x*y)/(x^6*y)
1194
sage: c.ecl()
1195
<ECL: ((MRAT SIMP ($X $Y $Z)
1196
...>
1197
sage: mrat_to_sage(c.ecl())
1198
(x^6*z^8 + y*z^9 + y^3 + x*y)/(x^6*y)
1199
"""
1200
return max_to_sr(meval(EclObject([[ratdisrep],expr])))
1201
1202
def mqapply_to_sage(expr):
1203
r"""
1204
Special conversion rule for MQAPPLY expressions.
1205
1206
INPUT:
1207
1208
- ``expr`` - ECL object; a Maxima MQAPPLY expression
1209
1210
OUTPUT: symbolic expression
1211
1212
MQAPPLY is used for function as li[x](y) and psi[x](y).
1213
1214
EXAMPLES::
1215
1216
sage: from sage.interfaces.maxima_lib import maxima_lib, mqapply_to_sage
1217
sage: c = maxima_lib('li[2](3)')
1218
sage: c.ecl()
1219
<ECL: ((MQAPPLY SIMP) (($LI SIMP ARRAY) 2) 3)>
1220
sage: mqapply_to_sage(c.ecl())
1221
polylog(2, 3)
1222
"""
1223
if caaadr(expr) == max_li:
1224
return sage.functions.log.polylog(max_to_sr(cadadr(expr)),
1225
max_to_sr(caddr(expr)))
1226
if caaadr(expr) == max_psi:
1227
return sage.functions.other.psi(max_to_sr(cadadr(expr)),
1228
max_to_sr(caddr(expr)))
1229
else:
1230
op=max_to_sr(cadr(expr))
1231
max_args=cddr(expr)
1232
args=[max_to_sr(a) for a in max_args]
1233
return op(*args)
1234
1235
def mdiff_to_sage(expr):
1236
r"""
1237
Special conversion rule for %DERIVATIVE expressions.
1238
1239
INPUT:
1240
1241
- ``expr`` - ECL object; a Maxima %DERIVATIVE expression
1242
1243
OUTPUT: symbolic expression
1244
1245
EXAMPLES::
1246
1247
sage: from sage.interfaces.maxima_lib import maxima_lib, mdiff_to_sage
1248
sage: f = maxima_lib('f(x)').diff('x',4)
1249
sage: f.ecl()
1250
<ECL: ((%DERIVATIVE SIMP) (($F SIMP) $X) $X 4)>
1251
sage: mdiff_to_sage(f.ecl())
1252
D[0, 0, 0, 0](f)(x)
1253
"""
1254
return max_to_sr(expr.cadr()).diff(*[max_to_sr(e) for e in expr.cddr()])
1255
1256
def mlist_to_sage(expr):
1257
r"""
1258
Special conversion rule for MLIST expressions.
1259
1260
INPUT:
1261
1262
- ``expr`` - ECL object; a Maxima MLIST expression (i.e., a list)
1263
1264
OUTPUT: a python list of converted expressions.
1265
1266
EXAMPLES::
1267
1268
sage: from sage.interfaces.maxima_lib import maxima_lib, mlist_to_sage
1269
sage: L=maxima_lib("[1,2,3]")
1270
sage: L.ecl()
1271
<ECL: ((MLIST SIMP) 1 2 3)>
1272
sage: mlist_to_sage(L.ecl())
1273
[1, 2, 3]
1274
"""
1275
return [max_to_sr(x) for x in expr.cdr()]
1276
1277
def max_at_to_sage(expr):
1278
r"""
1279
Special conversion rule for AT expressions.
1280
1281
INPUT:
1282
1283
- ``expr`` - ECL object; a Maxima AT expression
1284
1285
OUTPUT: symbolic expression
1286
1287
EXAMPLES::
1288
1289
sage: from sage.interfaces.maxima_lib import maxima_lib, max_at_to_sage
1290
sage: a=maxima_lib("'at(f(x,y,z),[x=1,y=2,z=3])")
1291
sage: a
1292
'at(f(x,y,z),[x=1,y=2,z=3])
1293
sage: max_at_to_sage(a.ecl())
1294
f(1, 2, 3)
1295
sage: a=maxima_lib("'at(f(x,y,z),x=1)")
1296
sage: a
1297
'at(f(x,y,z),x=1)
1298
sage: max_at_to_sage(a.ecl())
1299
f(1, y, z)
1300
"""
1301
arg=max_to_sr(expr.cadr())
1302
subsarg=caddr(expr)
1303
if caar(subsarg)==mlist:
1304
subsvalues=dict( (v.lhs(),v.rhs()) for v in max_to_sr(subsarg))
1305
else:
1306
v=max_to_sr(subsarg)
1307
subsvalues=dict([(v.lhs(),v.rhs())])
1308
return SR(arg).subs(subsvalues)
1309
1310
def dummy_integrate(expr):
1311
r"""
1312
We would like to simply tie Maxima's integrate to
1313
sage.calculus.calculus.dummy_integrate, but we're being
1314
imported there so to avoid circularity we define it here.
1315
1316
INPUT:
1317
1318
- ``expr`` - ECL object; a Maxima %INTEGRATE expression
1319
1320
OUTPUT: symbolic expression
1321
1322
EXAMPLES::
1323
1324
sage: from sage.interfaces.maxima_lib import maxima_lib, dummy_integrate
1325
sage: f = maxima_lib('f(x)').integrate('x')
1326
sage: f.ecl()
1327
<ECL: ((%INTEGRATE SIMP) (($F SIMP) $X) $X)>
1328
sage: dummy_integrate(f.ecl())
1329
integrate(f(x), x)
1330
1331
::
1332
1333
sage: f = maxima_lib('f(x)').integrate('x',0,10)
1334
sage: f.ecl()
1335
<ECL: ((%INTEGRATE SIMP) (($F SIMP) $X) $X 0 10)>
1336
sage: dummy_integrate(f.ecl())
1337
integrate(f(x), x, 0, 10)
1338
"""
1339
args=[max_to_sr(a) for a in cdr(expr)]
1340
if len(args) == 4 :
1341
return sage.symbolic.integration.integral.definite_integral(*args,
1342
hold=True)
1343
else:
1344
return sage.symbolic.integration.integral.indefinite_integral(*args,
1345
hold=True)
1346
1347
## The dictionaries
1348
special_max_to_sage={
1349
mrat : mrat_to_sage,
1350
mqapply : mqapply_to_sage,
1351
mdiff : mdiff_to_sage,
1352
EclObject("%INTEGRATE") : dummy_integrate,
1353
max_at : max_at_to_sage,
1354
mlist : mlist_to_sage
1355
}
1356
1357
special_sage_to_max={
1358
sage.functions.log.polylog : lambda N,X : [[mqapply],[[max_li, max_array],N],X],
1359
sage.functions.other.psi1 : lambda X : [[mqapply],[[max_psi, max_array],0],X],
1360
sage.functions.other.psi2 : lambda N,X : [[mqapply],[[max_psi, max_array],N],X],
1361
sage.functions.log.lambert_w : lambda N,X : [[max_lambert_w], X] if N==EclObject(0) else [[mqapply],[[max_lambert_w, max_array],N],X]
1362
}
1363
1364
1365
## Dictionaries for symbols
1366
sage_sym_dict={}
1367
max_sym_dict={}
1368
1369
1370
## Generic conversion functions
1371
1372
max_i=EclObject("$%I")
1373
def pyobject_to_max(obj):
1374
r"""
1375
Convert a (simple) Python object into a Maxima object.
1376
1377
INPUT:
1378
1379
- ``expr`` - Python object
1380
1381
OUTPUT: ECL object
1382
1383
.. note::
1384
1385
This uses functions defined in sage.libs.ecl.
1386
1387
EXAMPLES::
1388
1389
sage: from sage.interfaces.maxima_lib import pyobject_to_max
1390
sage: pyobject_to_max(4)
1391
<ECL: 4>
1392
sage: pyobject_to_max('z')
1393
<ECL: Z>
1394
sage: var('x')
1395
x
1396
sage: pyobject_to_max(x)
1397
Traceback (most recent call last):
1398
...
1399
TypeError: Unimplemented type for python_to_ecl
1400
"""
1401
if isinstance(obj,sage.rings.rational.Rational):
1402
return EclObject(obj) if (obj.denom().is_one()) else EclObject([[rat], obj.numer(),obj.denom()])
1403
elif isinstance(obj,sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic) and obj.parent().defining_polynomial().list() == [1,0,1]:
1404
re, im = obj.list()
1405
return EclObject([[mplus], pyobject_to_max(re), [[mtimes], pyobject_to_max(im), max_i]])
1406
return EclObject(obj)
1407
1408
# This goes from SR to EclObject
1409
def sr_to_max(expr):
1410
r"""
1411
Convert a symbolic expression into a Maxima object.
1412
1413
INPUT:
1414
1415
- ``expr`` - symbolic expression
1416
1417
OUTPUT: ECL object
1418
1419
EXAMPLES::
1420
1421
sage: from sage.interfaces.maxima_lib import sr_to_max
1422
sage: var('x')
1423
x
1424
sage: sr_to_max(x)
1425
<ECL: $X>
1426
sage: sr_to_max(cos(x))
1427
<ECL: ((%COS) $X)>
1428
sage: f = function('f',x)
1429
sage: sr_to_max(f.diff())
1430
<ECL: ((%DERIVATIVE) (($F) $X) $X 1)>
1431
1432
TESTS:
1433
1434
We should be able to convert derivatives evaluated at a point,
1435
:trac:`12796`::
1436
1437
sage: from sage.interfaces.maxima_lib import sr_to_max, max_to_sr
1438
sage: f = function('f')
1439
sage: f_prime = f(x).diff(x)
1440
sage: max_to_sr(sr_to_max(f_prime(x = 1)))
1441
D[0](f)(1)
1442
1443
"""
1444
global sage_op_dict, max_op_dict
1445
global sage_sym_dict, max_sym_dict
1446
if isinstance(expr,list) or isinstance(expr,tuple):
1447
return EclObject(([mlist],[sr_to_max(e) for e in expr]))
1448
op = expr.operator()
1449
if op:
1450
# Stolen from sage.symbolic.expression_conversion
1451
# Should be defined in a function and then put in special_sage_to_max
1452
# For that, we should change the API of the functions there
1453
# (we need to have access to op, not only to expr.operands()
1454
if isinstance(op, FDerivativeOperator):
1455
from sage.symbolic.ring import is_SymbolicVariable
1456
args = expr.operands()
1457
if (not all(is_SymbolicVariable(v) for v in args) or
1458
len(args) != len(set(args))):
1459
# An evaluated derivative of the form f'(1) is not a
1460
# symbolic variable, yet we would like to treat it
1461
# like one. So, we replace the argument `1` with a
1462
# temporary variable e.g. `t0` and then evaluate the
1463
# derivative f'(t0) symbolically at t0=1. See trac
1464
# #12796.
1465
temp_args=[var("t%s"%i) for i in range(len(args))]
1466
f =sr_to_max(op.function()(*temp_args))
1467
params = op.parameter_set()
1468
deriv_max = [[mdiff],f]
1469
for i in set(params):
1470
deriv_max.extend([sr_to_max(temp_args[i]), EclObject(params.count(i))])
1471
at_eval=sr_to_max([temp_args[i]==args[i] for i in range(len(args))])
1472
return EclObject([[max_at],deriv_max,at_eval])
1473
1474
f = sr_to_max(op.function()(*args))
1475
params = op.parameter_set()
1476
deriv_max = []
1477
[deriv_max.extend([sr_to_max(args[i]), EclObject(params.count(i))]) for i in set(params)]
1478
l = [[mdiff],f]
1479
l.extend(deriv_max)
1480
return EclObject(l)
1481
elif (op in special_sage_to_max):
1482
return EclObject(special_sage_to_max[op](*[sr_to_max(o) for o in expr.operands()]))
1483
elif not (op in sage_op_dict):
1484
# Maxima does some simplifications automatically by default
1485
# so calling maxima(expr) can change the structure of expr
1486
#op_max=caar(maxima(expr).ecl())
1487
# This should be safe if we treated all special operators above
1488
op_max=maxima(op).ecl()
1489
sage_op_dict[op]=op_max
1490
max_op_dict[op_max]=op
1491
return EclObject(([sage_op_dict[op]],
1492
[sr_to_max(o) for o in expr.operands()]))
1493
elif expr.is_symbol() or expr.is_constant():
1494
if not expr in sage_sym_dict:
1495
sym_max=maxima(expr).ecl()
1496
sage_sym_dict[expr]=sym_max
1497
max_sym_dict[sym_max]=expr
1498
return sage_sym_dict[expr]
1499
else:
1500
try:
1501
return pyobject_to_max(expr.pyobject())
1502
except TypeError:
1503
return maxima(expr).ecl()
1504
1505
# This goes from EclObject to SR
1506
def max_to_sr(expr):
1507
r"""
1508
Convert a Maxima object into a symbolic expression.
1509
1510
INPUT:
1511
1512
- ``expr`` - ECL object
1513
1514
OUTPUT: symbolic expression
1515
1516
EXAMPLES::
1517
1518
sage: from sage.interfaces.maxima_lib import maxima_lib, max_to_sr
1519
sage: f = maxima_lib('f(x)')
1520
sage: f.ecl()
1521
<ECL: (($F SIMP) $X)>
1522
sage: max_to_sr(f.ecl())
1523
f(x)
1524
1525
TESTS::
1526
1527
sage: from sage.interfaces.maxima_lib import sr_to_max, max_to_sr
1528
sage: f = function('f',x).diff()
1529
sage: bool(max_to_sr(sr_to_max(f)) == f)
1530
True
1531
"""
1532
if expr.consp():
1533
op_max=caar(expr)
1534
if op_max in special_max_to_sage:
1535
return special_max_to_sage[op_max](expr)
1536
if not(op_max in max_op_dict):
1537
# This could be unsafe if the conversion to SR
1538
# changes the structure of expr
1539
sage_expr=SR(maxima(expr))
1540
max_op_dict[op_max]=sage_expr.operator()
1541
sage_op_dict[sage_expr.operator()]=op_max
1542
op=max_op_dict[op_max]
1543
max_args=cdr(expr)
1544
args=[max_to_sr(a) for a in max_args]
1545
return op(*args)
1546
elif expr.symbolp():
1547
if not(expr in max_sym_dict):
1548
sage_symbol=SR(maxima(expr))
1549
sage_sym_dict[sage_symbol]=expr
1550
max_sym_dict[expr]=sage_symbol
1551
return max_sym_dict[expr]
1552
else:
1553
e=expr.python()
1554
if isinstance(e,float):
1555
return sage.rings.real_double.RealDoubleElement(e)
1556
return e
1557
1558