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