Add files using upload-large-folder tool
Browse files- lib/python3.12/site-packages/sympy/printing/pretty/stringpict.py +537 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_aesaracode.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_c.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_codeprinter.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_conventions.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cupy.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cxx.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_dot.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_fortran.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_glsl.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_gtk.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jax.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jscode.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_julia.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_lambdarepr.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_llvmjit.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_maple.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_mathematica.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_numpy.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_octave.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_precedence.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_preview.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_pycode.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_python.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rcode.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_repr.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rust.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_smtlib.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_str.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tableform.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tensorflow.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_theanocode.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tree.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_conventions.py +116 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_gtk.py +18 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_jax.py +370 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_jscode.py +396 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_julia.py +386 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_latex.py +0 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_llvmjit.py +224 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_maple.py +381 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_mathematica.py +287 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_octave.py +515 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_preview.py +38 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_pycode.py +429 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_repr.py +382 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_smtlib.py +553 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_str.py +1199 -0
- lib/python3.12/site-packages/sympy/printing/tests/test_tree.py +196 -0
lib/python3.12/site-packages/sympy/printing/pretty/stringpict.py
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Prettyprinter by Jurjen Bos.
|
| 2 |
+
(I hate spammers: mail me at pietjepuk314 at the reverse of ku.oc.oohay).
|
| 3 |
+
All objects have a method that create a "stringPict",
|
| 4 |
+
that can be used in the str method for pretty printing.
|
| 5 |
+
|
| 6 |
+
Updates by Jason Gedge (email <my last name> at cs mun ca)
|
| 7 |
+
- terminal_string() method
|
| 8 |
+
- minor fixes and changes (mostly to prettyForm)
|
| 9 |
+
|
| 10 |
+
TODO:
|
| 11 |
+
- Allow left/center/right alignment options for above/below and
|
| 12 |
+
top/center/bottom alignment options for left/right
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import shutil
|
| 16 |
+
|
| 17 |
+
from .pretty_symbology import hobj, vobj, xsym, xobj, pretty_use_unicode, line_width, center
|
| 18 |
+
from sympy.utilities.exceptions import sympy_deprecation_warning
|
| 19 |
+
|
| 20 |
+
_GLOBAL_WRAP_LINE = None
|
| 21 |
+
|
| 22 |
+
class stringPict:
|
| 23 |
+
"""An ASCII picture.
|
| 24 |
+
The pictures are represented as a list of equal length strings.
|
| 25 |
+
"""
|
| 26 |
+
#special value for stringPict.below
|
| 27 |
+
LINE = 'line'
|
| 28 |
+
|
| 29 |
+
def __init__(self, s, baseline=0):
|
| 30 |
+
"""Initialize from string.
|
| 31 |
+
Multiline strings are centered.
|
| 32 |
+
"""
|
| 33 |
+
self.s = s
|
| 34 |
+
#picture is a string that just can be printed
|
| 35 |
+
self.picture = stringPict.equalLengths(s.splitlines())
|
| 36 |
+
#baseline is the line number of the "base line"
|
| 37 |
+
self.baseline = baseline
|
| 38 |
+
self.binding = None
|
| 39 |
+
|
| 40 |
+
@staticmethod
|
| 41 |
+
def equalLengths(lines):
|
| 42 |
+
# empty lines
|
| 43 |
+
if not lines:
|
| 44 |
+
return ['']
|
| 45 |
+
|
| 46 |
+
width = max(line_width(line) for line in lines)
|
| 47 |
+
return [center(line, width) for line in lines]
|
| 48 |
+
|
| 49 |
+
def height(self):
|
| 50 |
+
"""The height of the picture in characters."""
|
| 51 |
+
return len(self.picture)
|
| 52 |
+
|
| 53 |
+
def width(self):
|
| 54 |
+
"""The width of the picture in characters."""
|
| 55 |
+
return line_width(self.picture[0])
|
| 56 |
+
|
| 57 |
+
@staticmethod
|
| 58 |
+
def next(*args):
|
| 59 |
+
"""Put a string of stringPicts next to each other.
|
| 60 |
+
Returns string, baseline arguments for stringPict.
|
| 61 |
+
"""
|
| 62 |
+
#convert everything to stringPicts
|
| 63 |
+
objects = []
|
| 64 |
+
for arg in args:
|
| 65 |
+
if isinstance(arg, str):
|
| 66 |
+
arg = stringPict(arg)
|
| 67 |
+
objects.append(arg)
|
| 68 |
+
|
| 69 |
+
#make a list of pictures, with equal height and baseline
|
| 70 |
+
newBaseline = max(obj.baseline for obj in objects)
|
| 71 |
+
newHeightBelowBaseline = max(
|
| 72 |
+
obj.height() - obj.baseline
|
| 73 |
+
for obj in objects)
|
| 74 |
+
newHeight = newBaseline + newHeightBelowBaseline
|
| 75 |
+
|
| 76 |
+
pictures = []
|
| 77 |
+
for obj in objects:
|
| 78 |
+
oneEmptyLine = [' '*obj.width()]
|
| 79 |
+
basePadding = newBaseline - obj.baseline
|
| 80 |
+
totalPadding = newHeight - obj.height()
|
| 81 |
+
pictures.append(
|
| 82 |
+
oneEmptyLine * basePadding +
|
| 83 |
+
obj.picture +
|
| 84 |
+
oneEmptyLine * (totalPadding - basePadding))
|
| 85 |
+
|
| 86 |
+
result = [''.join(lines) for lines in zip(*pictures)]
|
| 87 |
+
return '\n'.join(result), newBaseline
|
| 88 |
+
|
| 89 |
+
def right(self, *args):
|
| 90 |
+
r"""Put pictures next to this one.
|
| 91 |
+
Returns string, baseline arguments for stringPict.
|
| 92 |
+
(Multiline) strings are allowed, and are given a baseline of 0.
|
| 93 |
+
|
| 94 |
+
Examples
|
| 95 |
+
========
|
| 96 |
+
|
| 97 |
+
>>> from sympy.printing.pretty.stringpict import stringPict
|
| 98 |
+
>>> print(stringPict("10").right(" + ",stringPict("1\r-\r2",1))[0])
|
| 99 |
+
1
|
| 100 |
+
10 + -
|
| 101 |
+
2
|
| 102 |
+
|
| 103 |
+
"""
|
| 104 |
+
return stringPict.next(self, *args)
|
| 105 |
+
|
| 106 |
+
def left(self, *args):
|
| 107 |
+
"""Put pictures (left to right) at left.
|
| 108 |
+
Returns string, baseline arguments for stringPict.
|
| 109 |
+
"""
|
| 110 |
+
return stringPict.next(*(args + (self,)))
|
| 111 |
+
|
| 112 |
+
@staticmethod
|
| 113 |
+
def stack(*args):
|
| 114 |
+
"""Put pictures on top of each other,
|
| 115 |
+
from top to bottom.
|
| 116 |
+
Returns string, baseline arguments for stringPict.
|
| 117 |
+
The baseline is the baseline of the second picture.
|
| 118 |
+
Everything is centered.
|
| 119 |
+
Baseline is the baseline of the second picture.
|
| 120 |
+
Strings are allowed.
|
| 121 |
+
The special value stringPict.LINE is a row of '-' extended to the width.
|
| 122 |
+
"""
|
| 123 |
+
#convert everything to stringPicts; keep LINE
|
| 124 |
+
objects = []
|
| 125 |
+
for arg in args:
|
| 126 |
+
if arg is not stringPict.LINE and isinstance(arg, str):
|
| 127 |
+
arg = stringPict(arg)
|
| 128 |
+
objects.append(arg)
|
| 129 |
+
|
| 130 |
+
#compute new width
|
| 131 |
+
newWidth = max(
|
| 132 |
+
obj.width()
|
| 133 |
+
for obj in objects
|
| 134 |
+
if obj is not stringPict.LINE)
|
| 135 |
+
|
| 136 |
+
lineObj = stringPict(hobj('-', newWidth))
|
| 137 |
+
|
| 138 |
+
#replace LINE with proper lines
|
| 139 |
+
for i, obj in enumerate(objects):
|
| 140 |
+
if obj is stringPict.LINE:
|
| 141 |
+
objects[i] = lineObj
|
| 142 |
+
|
| 143 |
+
#stack the pictures, and center the result
|
| 144 |
+
newPicture = [center(line, newWidth) for obj in objects for line in obj.picture]
|
| 145 |
+
newBaseline = objects[0].height() + objects[1].baseline
|
| 146 |
+
return '\n'.join(newPicture), newBaseline
|
| 147 |
+
|
| 148 |
+
def below(self, *args):
|
| 149 |
+
"""Put pictures under this picture.
|
| 150 |
+
Returns string, baseline arguments for stringPict.
|
| 151 |
+
Baseline is baseline of top picture
|
| 152 |
+
|
| 153 |
+
Examples
|
| 154 |
+
========
|
| 155 |
+
|
| 156 |
+
>>> from sympy.printing.pretty.stringpict import stringPict
|
| 157 |
+
>>> print(stringPict("x+3").below(
|
| 158 |
+
... stringPict.LINE, '3')[0]) #doctest: +NORMALIZE_WHITESPACE
|
| 159 |
+
x+3
|
| 160 |
+
---
|
| 161 |
+
3
|
| 162 |
+
|
| 163 |
+
"""
|
| 164 |
+
s, baseline = stringPict.stack(self, *args)
|
| 165 |
+
return s, self.baseline
|
| 166 |
+
|
| 167 |
+
def above(self, *args):
|
| 168 |
+
"""Put pictures above this picture.
|
| 169 |
+
Returns string, baseline arguments for stringPict.
|
| 170 |
+
Baseline is baseline of bottom picture.
|
| 171 |
+
"""
|
| 172 |
+
string, baseline = stringPict.stack(*(args + (self,)))
|
| 173 |
+
baseline = len(string.splitlines()) - self.height() + self.baseline
|
| 174 |
+
return string, baseline
|
| 175 |
+
|
| 176 |
+
def parens(self, left='(', right=')', ifascii_nougly=False):
|
| 177 |
+
"""Put parentheses around self.
|
| 178 |
+
Returns string, baseline arguments for stringPict.
|
| 179 |
+
|
| 180 |
+
left or right can be None or empty string which means 'no paren from
|
| 181 |
+
that side'
|
| 182 |
+
"""
|
| 183 |
+
h = self.height()
|
| 184 |
+
b = self.baseline
|
| 185 |
+
|
| 186 |
+
# XXX this is a hack -- ascii parens are ugly!
|
| 187 |
+
if ifascii_nougly and not pretty_use_unicode():
|
| 188 |
+
h = 1
|
| 189 |
+
b = 0
|
| 190 |
+
|
| 191 |
+
res = self
|
| 192 |
+
|
| 193 |
+
if left:
|
| 194 |
+
lparen = stringPict(vobj(left, h), baseline=b)
|
| 195 |
+
res = stringPict(*lparen.right(self))
|
| 196 |
+
if right:
|
| 197 |
+
rparen = stringPict(vobj(right, h), baseline=b)
|
| 198 |
+
res = stringPict(*res.right(rparen))
|
| 199 |
+
|
| 200 |
+
return ('\n'.join(res.picture), res.baseline)
|
| 201 |
+
|
| 202 |
+
def leftslash(self):
|
| 203 |
+
"""Precede object by a slash of the proper size.
|
| 204 |
+
"""
|
| 205 |
+
# XXX not used anywhere ?
|
| 206 |
+
height = max(
|
| 207 |
+
self.baseline,
|
| 208 |
+
self.height() - 1 - self.baseline)*2 + 1
|
| 209 |
+
slash = '\n'.join(
|
| 210 |
+
' '*(height - i - 1) + xobj('/', 1) + ' '*i
|
| 211 |
+
for i in range(height)
|
| 212 |
+
)
|
| 213 |
+
return self.left(stringPict(slash, height//2))
|
| 214 |
+
|
| 215 |
+
def root(self, n=None):
|
| 216 |
+
"""Produce a nice root symbol.
|
| 217 |
+
Produces ugly results for big n inserts.
|
| 218 |
+
"""
|
| 219 |
+
# XXX not used anywhere
|
| 220 |
+
# XXX duplicate of root drawing in pretty.py
|
| 221 |
+
#put line over expression
|
| 222 |
+
result = self.above('_'*self.width())
|
| 223 |
+
#construct right half of root symbol
|
| 224 |
+
height = self.height()
|
| 225 |
+
slash = '\n'.join(
|
| 226 |
+
' ' * (height - i - 1) + '/' + ' ' * i
|
| 227 |
+
for i in range(height)
|
| 228 |
+
)
|
| 229 |
+
slash = stringPict(slash, height - 1)
|
| 230 |
+
#left half of root symbol
|
| 231 |
+
if height > 2:
|
| 232 |
+
downline = stringPict('\\ \n \\', 1)
|
| 233 |
+
else:
|
| 234 |
+
downline = stringPict('\\')
|
| 235 |
+
#put n on top, as low as possible
|
| 236 |
+
if n is not None and n.width() > downline.width():
|
| 237 |
+
downline = downline.left(' '*(n.width() - downline.width()))
|
| 238 |
+
downline = downline.above(n)
|
| 239 |
+
#build root symbol
|
| 240 |
+
root = downline.right(slash)
|
| 241 |
+
#glue it on at the proper height
|
| 242 |
+
#normally, the root symbel is as high as self
|
| 243 |
+
#which is one less than result
|
| 244 |
+
#this moves the root symbol one down
|
| 245 |
+
#if the root became higher, the baseline has to grow too
|
| 246 |
+
root.baseline = result.baseline - result.height() + root.height()
|
| 247 |
+
return result.left(root)
|
| 248 |
+
|
| 249 |
+
def render(self, * args, **kwargs):
|
| 250 |
+
"""Return the string form of self.
|
| 251 |
+
|
| 252 |
+
Unless the argument line_break is set to False, it will
|
| 253 |
+
break the expression in a form that can be printed
|
| 254 |
+
on the terminal without being broken up.
|
| 255 |
+
"""
|
| 256 |
+
if _GLOBAL_WRAP_LINE is not None:
|
| 257 |
+
kwargs["wrap_line"] = _GLOBAL_WRAP_LINE
|
| 258 |
+
|
| 259 |
+
if kwargs["wrap_line"] is False:
|
| 260 |
+
return "\n".join(self.picture)
|
| 261 |
+
|
| 262 |
+
if kwargs["num_columns"] is not None:
|
| 263 |
+
# Read the argument num_columns if it is not None
|
| 264 |
+
ncols = kwargs["num_columns"]
|
| 265 |
+
else:
|
| 266 |
+
# Attempt to get a terminal width
|
| 267 |
+
ncols = self.terminal_width()
|
| 268 |
+
|
| 269 |
+
if ncols <= 0:
|
| 270 |
+
ncols = 80
|
| 271 |
+
|
| 272 |
+
# If smaller than the terminal width, no need to correct
|
| 273 |
+
if self.width() <= ncols:
|
| 274 |
+
return type(self.picture[0])(self)
|
| 275 |
+
|
| 276 |
+
"""
|
| 277 |
+
Break long-lines in a visually pleasing format.
|
| 278 |
+
without overflow indicators | with overflow indicators
|
| 279 |
+
| 2 2 3 | | 2 2 3 ↪|
|
| 280 |
+
|6*x *y + 4*x*y + | |6*x *y + 4*x*y + ↪|
|
| 281 |
+
| | | |
|
| 282 |
+
| 3 4 4 | |↪ 3 4 4 |
|
| 283 |
+
|4*y*x + x + y | |↪ 4*y*x + x + y |
|
| 284 |
+
|a*c*e + a*c*f + a*d | |a*c*e + a*c*f + a*d ↪|
|
| 285 |
+
|*e + a*d*f + b*c*e | | |
|
| 286 |
+
|+ b*c*f + b*d*e + b | |↪ *e + a*d*f + b*c* ↪|
|
| 287 |
+
|*d*f | | |
|
| 288 |
+
| | |↪ e + b*c*f + b*d*e ↪|
|
| 289 |
+
| | | |
|
| 290 |
+
| | |↪ + b*d*f |
|
| 291 |
+
"""
|
| 292 |
+
|
| 293 |
+
overflow_first = ""
|
| 294 |
+
if kwargs["use_unicode"] or pretty_use_unicode():
|
| 295 |
+
overflow_start = "\N{RIGHTWARDS ARROW WITH HOOK} "
|
| 296 |
+
overflow_end = " \N{RIGHTWARDS ARROW WITH HOOK}"
|
| 297 |
+
else:
|
| 298 |
+
overflow_start = "> "
|
| 299 |
+
overflow_end = " >"
|
| 300 |
+
|
| 301 |
+
def chunks(line):
|
| 302 |
+
"""Yields consecutive chunks of line_width ncols"""
|
| 303 |
+
prefix = overflow_first
|
| 304 |
+
width, start = line_width(prefix + overflow_end), 0
|
| 305 |
+
for i, x in enumerate(line):
|
| 306 |
+
wx = line_width(x)
|
| 307 |
+
# Only flush the screen when the current character overflows.
|
| 308 |
+
# This way, combining marks can be appended even when width == ncols.
|
| 309 |
+
if width + wx > ncols:
|
| 310 |
+
yield prefix + line[start:i] + overflow_end
|
| 311 |
+
prefix = overflow_start
|
| 312 |
+
width, start = line_width(prefix + overflow_end), i
|
| 313 |
+
width += wx
|
| 314 |
+
yield prefix + line[start:]
|
| 315 |
+
|
| 316 |
+
# Concurrently assemble chunks of all lines into individual screens
|
| 317 |
+
pictures = zip(*map(chunks, self.picture))
|
| 318 |
+
|
| 319 |
+
# Join lines of each screen into sub-pictures
|
| 320 |
+
pictures = ["\n".join(picture) for picture in pictures]
|
| 321 |
+
|
| 322 |
+
# Add spacers between sub-pictures
|
| 323 |
+
return "\n\n".join(pictures)
|
| 324 |
+
|
| 325 |
+
def terminal_width(self):
|
| 326 |
+
"""Return the terminal width if possible, otherwise return 0.
|
| 327 |
+
"""
|
| 328 |
+
size = shutil.get_terminal_size(fallback=(0, 0))
|
| 329 |
+
return size.columns
|
| 330 |
+
|
| 331 |
+
def __eq__(self, o):
|
| 332 |
+
if isinstance(o, str):
|
| 333 |
+
return '\n'.join(self.picture) == o
|
| 334 |
+
elif isinstance(o, stringPict):
|
| 335 |
+
return o.picture == self.picture
|
| 336 |
+
return False
|
| 337 |
+
|
| 338 |
+
def __hash__(self):
|
| 339 |
+
return super().__hash__()
|
| 340 |
+
|
| 341 |
+
def __str__(self):
|
| 342 |
+
return '\n'.join(self.picture)
|
| 343 |
+
|
| 344 |
+
def __repr__(self):
|
| 345 |
+
return "stringPict(%r,%d)" % ('\n'.join(self.picture), self.baseline)
|
| 346 |
+
|
| 347 |
+
def __getitem__(self, index):
|
| 348 |
+
return self.picture[index]
|
| 349 |
+
|
| 350 |
+
def __len__(self):
|
| 351 |
+
return len(self.s)
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
class prettyForm(stringPict):
|
| 355 |
+
"""
|
| 356 |
+
Extension of the stringPict class that knows about basic math applications,
|
| 357 |
+
optimizing double minus signs.
|
| 358 |
+
|
| 359 |
+
"Binding" is interpreted as follows::
|
| 360 |
+
|
| 361 |
+
ATOM this is an atom: never needs to be parenthesized
|
| 362 |
+
FUNC this is a function application: parenthesize if added (?)
|
| 363 |
+
DIV this is a division: make wider division if divided
|
| 364 |
+
POW this is a power: only parenthesize if exponent
|
| 365 |
+
MUL this is a multiplication: parenthesize if powered
|
| 366 |
+
ADD this is an addition: parenthesize if multiplied or powered
|
| 367 |
+
NEG this is a negative number: optimize if added, parenthesize if
|
| 368 |
+
multiplied or powered
|
| 369 |
+
OPEN this is an open object: parenthesize if added, multiplied, or
|
| 370 |
+
powered (example: Piecewise)
|
| 371 |
+
"""
|
| 372 |
+
ATOM, FUNC, DIV, POW, MUL, ADD, NEG, OPEN = range(8)
|
| 373 |
+
|
| 374 |
+
def __init__(self, s, baseline=0, binding=0, unicode=None):
|
| 375 |
+
"""Initialize from stringPict and binding power."""
|
| 376 |
+
stringPict.__init__(self, s, baseline)
|
| 377 |
+
self.binding = binding
|
| 378 |
+
if unicode is not None:
|
| 379 |
+
sympy_deprecation_warning(
|
| 380 |
+
"""
|
| 381 |
+
The unicode argument to prettyForm is deprecated. Only the s
|
| 382 |
+
argument (the first positional argument) should be passed.
|
| 383 |
+
""",
|
| 384 |
+
deprecated_since_version="1.7",
|
| 385 |
+
active_deprecations_target="deprecated-pretty-printing-functions")
|
| 386 |
+
self._unicode = unicode or s
|
| 387 |
+
|
| 388 |
+
@property
|
| 389 |
+
def unicode(self):
|
| 390 |
+
sympy_deprecation_warning(
|
| 391 |
+
"""
|
| 392 |
+
The prettyForm.unicode attribute is deprecated. Use the
|
| 393 |
+
prettyForm.s attribute instead.
|
| 394 |
+
""",
|
| 395 |
+
deprecated_since_version="1.7",
|
| 396 |
+
active_deprecations_target="deprecated-pretty-printing-functions")
|
| 397 |
+
return self._unicode
|
| 398 |
+
|
| 399 |
+
# Note: code to handle subtraction is in _print_Add
|
| 400 |
+
|
| 401 |
+
def __add__(self, *others):
|
| 402 |
+
"""Make a pretty addition.
|
| 403 |
+
Addition of negative numbers is simplified.
|
| 404 |
+
"""
|
| 405 |
+
arg = self
|
| 406 |
+
if arg.binding > prettyForm.NEG:
|
| 407 |
+
arg = stringPict(*arg.parens())
|
| 408 |
+
result = [arg]
|
| 409 |
+
for arg in others:
|
| 410 |
+
#add parentheses for weak binders
|
| 411 |
+
if arg.binding > prettyForm.NEG:
|
| 412 |
+
arg = stringPict(*arg.parens())
|
| 413 |
+
#use existing minus sign if available
|
| 414 |
+
if arg.binding != prettyForm.NEG:
|
| 415 |
+
result.append(' + ')
|
| 416 |
+
result.append(arg)
|
| 417 |
+
return prettyForm(binding=prettyForm.ADD, *stringPict.next(*result))
|
| 418 |
+
|
| 419 |
+
def __truediv__(self, den, slashed=False):
|
| 420 |
+
"""Make a pretty division; stacked or slashed.
|
| 421 |
+
"""
|
| 422 |
+
if slashed:
|
| 423 |
+
raise NotImplementedError("Can't do slashed fraction yet")
|
| 424 |
+
num = self
|
| 425 |
+
if num.binding == prettyForm.DIV:
|
| 426 |
+
num = stringPict(*num.parens())
|
| 427 |
+
if den.binding == prettyForm.DIV:
|
| 428 |
+
den = stringPict(*den.parens())
|
| 429 |
+
|
| 430 |
+
if num.binding==prettyForm.NEG:
|
| 431 |
+
num = num.right(" ")[0]
|
| 432 |
+
|
| 433 |
+
return prettyForm(binding=prettyForm.DIV, *stringPict.stack(
|
| 434 |
+
num,
|
| 435 |
+
stringPict.LINE,
|
| 436 |
+
den))
|
| 437 |
+
|
| 438 |
+
def __mul__(self, *others):
|
| 439 |
+
"""Make a pretty multiplication.
|
| 440 |
+
Parentheses are needed around +, - and neg.
|
| 441 |
+
"""
|
| 442 |
+
quantity = {
|
| 443 |
+
'degree': "\N{DEGREE SIGN}"
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
if len(others) == 0:
|
| 447 |
+
return self # We aren't actually multiplying... So nothing to do here.
|
| 448 |
+
|
| 449 |
+
# add parens on args that need them
|
| 450 |
+
arg = self
|
| 451 |
+
if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG:
|
| 452 |
+
arg = stringPict(*arg.parens())
|
| 453 |
+
result = [arg]
|
| 454 |
+
for arg in others:
|
| 455 |
+
if arg.picture[0] not in quantity.values():
|
| 456 |
+
result.append(xsym('*'))
|
| 457 |
+
#add parentheses for weak binders
|
| 458 |
+
if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG:
|
| 459 |
+
arg = stringPict(*arg.parens())
|
| 460 |
+
result.append(arg)
|
| 461 |
+
|
| 462 |
+
len_res = len(result)
|
| 463 |
+
for i in range(len_res):
|
| 464 |
+
if i < len_res - 1 and result[i] == '-1' and result[i + 1] == xsym('*'):
|
| 465 |
+
# substitute -1 by -, like in -1*x -> -x
|
| 466 |
+
result.pop(i)
|
| 467 |
+
result.pop(i)
|
| 468 |
+
result.insert(i, '-')
|
| 469 |
+
if result[0][0] == '-':
|
| 470 |
+
# if there is a - sign in front of all
|
| 471 |
+
# This test was failing to catch a prettyForm.__mul__(prettyForm("-1", 0, 6)) being negative
|
| 472 |
+
bin = prettyForm.NEG
|
| 473 |
+
if result[0] == '-':
|
| 474 |
+
right = result[1]
|
| 475 |
+
if right.picture[right.baseline][0] == '-':
|
| 476 |
+
result[0] = '- '
|
| 477 |
+
else:
|
| 478 |
+
bin = prettyForm.MUL
|
| 479 |
+
return prettyForm(binding=bin, *stringPict.next(*result))
|
| 480 |
+
|
| 481 |
+
def __repr__(self):
|
| 482 |
+
return "prettyForm(%r,%d,%d)" % (
|
| 483 |
+
'\n'.join(self.picture),
|
| 484 |
+
self.baseline,
|
| 485 |
+
self.binding)
|
| 486 |
+
|
| 487 |
+
def __pow__(self, b):
|
| 488 |
+
"""Make a pretty power.
|
| 489 |
+
"""
|
| 490 |
+
a = self
|
| 491 |
+
use_inline_func_form = False
|
| 492 |
+
if b.binding == prettyForm.POW:
|
| 493 |
+
b = stringPict(*b.parens())
|
| 494 |
+
if a.binding > prettyForm.FUNC:
|
| 495 |
+
a = stringPict(*a.parens())
|
| 496 |
+
elif a.binding == prettyForm.FUNC:
|
| 497 |
+
# heuristic for when to use inline power
|
| 498 |
+
if b.height() > 1:
|
| 499 |
+
a = stringPict(*a.parens())
|
| 500 |
+
else:
|
| 501 |
+
use_inline_func_form = True
|
| 502 |
+
|
| 503 |
+
if use_inline_func_form:
|
| 504 |
+
# 2
|
| 505 |
+
# sin + + (x)
|
| 506 |
+
b.baseline = a.prettyFunc.baseline + b.height()
|
| 507 |
+
func = stringPict(*a.prettyFunc.right(b))
|
| 508 |
+
return prettyForm(*func.right(a.prettyArgs))
|
| 509 |
+
else:
|
| 510 |
+
# 2 <-- top
|
| 511 |
+
# (x+y) <-- bot
|
| 512 |
+
top = stringPict(*b.left(' '*a.width()))
|
| 513 |
+
bot = stringPict(*a.right(' '*b.width()))
|
| 514 |
+
|
| 515 |
+
return prettyForm(binding=prettyForm.POW, *bot.above(top))
|
| 516 |
+
|
| 517 |
+
simpleFunctions = ["sin", "cos", "tan"]
|
| 518 |
+
|
| 519 |
+
@staticmethod
|
| 520 |
+
def apply(function, *args):
|
| 521 |
+
"""Functions of one or more variables.
|
| 522 |
+
"""
|
| 523 |
+
if function in prettyForm.simpleFunctions:
|
| 524 |
+
#simple function: use only space if possible
|
| 525 |
+
assert len(
|
| 526 |
+
args) == 1, "Simple function %s must have 1 argument" % function
|
| 527 |
+
arg = args[0].__pretty__()
|
| 528 |
+
if arg.binding <= prettyForm.DIV:
|
| 529 |
+
#optimization: no parentheses necessary
|
| 530 |
+
return prettyForm(binding=prettyForm.FUNC, *arg.left(function + ' '))
|
| 531 |
+
argumentList = []
|
| 532 |
+
for arg in args:
|
| 533 |
+
argumentList.append(',')
|
| 534 |
+
argumentList.append(arg.__pretty__())
|
| 535 |
+
argumentList = stringPict(*stringPict.next(*argumentList[1:]))
|
| 536 |
+
argumentList = stringPict(*argumentList.parens())
|
| 537 |
+
return prettyForm(binding=prettyForm.ATOM, *argumentList.left(function))
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (199 Bytes). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_aesaracode.cpython-312.pyc
ADDED
|
Binary file (37.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_c.cpython-312.pyc
ADDED
|
Binary file (54.9 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_codeprinter.cpython-312.pyc
ADDED
|
Binary file (3.19 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_conventions.cpython-312.pyc
ADDED
|
Binary file (7.16 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cupy.cpython-312.pyc
ADDED
|
Binary file (4.18 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cxx.cpython-312.pyc
ADDED
|
Binary file (7.06 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_dot.cpython-312.pyc
ADDED
|
Binary file (9.11 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_fortran.cpython-312.pyc
ADDED
|
Binary file (52.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_glsl.cpython-312.pyc
ADDED
|
Binary file (39.8 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_gtk.cpython-312.pyc
ADDED
|
Binary file (1.1 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jax.cpython-312.pyc
ADDED
|
Binary file (22.2 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jscode.cpython-312.pyc
ADDED
|
Binary file (20.6 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_julia.cpython-312.pyc
ADDED
|
Binary file (26.1 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_lambdarepr.cpython-312.pyc
ADDED
|
Binary file (11.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_llvmjit.cpython-312.pyc
ADDED
|
Binary file (12.5 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_maple.cpython-312.pyc
ADDED
|
Binary file (25.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_mathematica.cpython-312.pyc
ADDED
|
Binary file (19.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_numpy.cpython-312.pyc
ADDED
|
Binary file (21.6 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_octave.cpython-312.pyc
ADDED
|
Binary file (37.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_precedence.cpython-312.pyc
ADDED
|
Binary file (6.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_preview.cpython-312.pyc
ADDED
|
Binary file (1.57 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_pycode.cpython-312.pyc
ADDED
|
Binary file (29.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_python.cpython-312.pyc
ADDED
|
Binary file (13.1 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rcode.cpython-312.pyc
ADDED
|
Binary file (25.3 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_repr.cpython-312.pyc
ADDED
|
Binary file (24.2 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rust.cpython-312.pyc
ADDED
|
Binary file (21.8 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_smtlib.cpython-312.pyc
ADDED
|
Binary file (32.4 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_str.cpython-312.pyc
ADDED
|
Binary file (88.2 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tableform.cpython-312.pyc
ADDED
|
Binary file (6.92 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tensorflow.cpython-312.pyc
ADDED
|
Binary file (28.6 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_theanocode.cpython-312.pyc
ADDED
|
Binary file (38.9 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tree.cpython-312.pyc
ADDED
|
Binary file (4.73 kB). View file
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/test_conventions.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
|
| 3 |
+
from sympy.core.function import (Derivative, Function)
|
| 4 |
+
from sympy.core.numbers import oo
|
| 5 |
+
from sympy.core.symbol import symbols
|
| 6 |
+
from sympy.functions.elementary.exponential import exp
|
| 7 |
+
from sympy.functions.elementary.trigonometric import cos
|
| 8 |
+
from sympy.integrals.integrals import Integral
|
| 9 |
+
from sympy.functions.special.bessel import besselj
|
| 10 |
+
from sympy.functions.special.polynomials import legendre
|
| 11 |
+
from sympy.functions.combinatorial.numbers import bell
|
| 12 |
+
from sympy.printing.conventions import split_super_sub, requires_partial
|
| 13 |
+
from sympy.testing.pytest import XFAIL
|
| 14 |
+
|
| 15 |
+
def test_super_sub():
|
| 16 |
+
assert split_super_sub("beta_13_2") == ("beta", [], ["13", "2"])
|
| 17 |
+
assert split_super_sub("beta_132_20") == ("beta", [], ["132", "20"])
|
| 18 |
+
assert split_super_sub("beta_13") == ("beta", [], ["13"])
|
| 19 |
+
assert split_super_sub("x_a_b") == ("x", [], ["a", "b"])
|
| 20 |
+
assert split_super_sub("x_1_2_3") == ("x", [], ["1", "2", "3"])
|
| 21 |
+
assert split_super_sub("x_a_b1") == ("x", [], ["a", "b1"])
|
| 22 |
+
assert split_super_sub("x_a_1") == ("x", [], ["a", "1"])
|
| 23 |
+
assert split_super_sub("x_1_a") == ("x", [], ["1", "a"])
|
| 24 |
+
assert split_super_sub("x_1^aa") == ("x", ["aa"], ["1"])
|
| 25 |
+
assert split_super_sub("x_1__aa") == ("x", ["aa"], ["1"])
|
| 26 |
+
assert split_super_sub("x_11^a") == ("x", ["a"], ["11"])
|
| 27 |
+
assert split_super_sub("x_11__a") == ("x", ["a"], ["11"])
|
| 28 |
+
assert split_super_sub("x_a_b_c_d") == ("x", [], ["a", "b", "c", "d"])
|
| 29 |
+
assert split_super_sub("x_a_b^c^d") == ("x", ["c", "d"], ["a", "b"])
|
| 30 |
+
assert split_super_sub("x_a_b__c__d") == ("x", ["c", "d"], ["a", "b"])
|
| 31 |
+
assert split_super_sub("x_a^b_c^d") == ("x", ["b", "d"], ["a", "c"])
|
| 32 |
+
assert split_super_sub("x_a__b_c__d") == ("x", ["b", "d"], ["a", "c"])
|
| 33 |
+
assert split_super_sub("x^a^b_c_d") == ("x", ["a", "b"], ["c", "d"])
|
| 34 |
+
assert split_super_sub("x__a__b_c_d") == ("x", ["a", "b"], ["c", "d"])
|
| 35 |
+
assert split_super_sub("x^a^b^c^d") == ("x", ["a", "b", "c", "d"], [])
|
| 36 |
+
assert split_super_sub("x__a__b__c__d") == ("x", ["a", "b", "c", "d"], [])
|
| 37 |
+
assert split_super_sub("alpha_11") == ("alpha", [], ["11"])
|
| 38 |
+
assert split_super_sub("alpha_11_11") == ("alpha", [], ["11", "11"])
|
| 39 |
+
assert split_super_sub("w1") == ("w", [], ["1"])
|
| 40 |
+
assert split_super_sub("w𝟙") == ("w", [], ["𝟙"])
|
| 41 |
+
assert split_super_sub("w11") == ("w", [], ["11"])
|
| 42 |
+
assert split_super_sub("w𝟙𝟙") == ("w", [], ["𝟙𝟙"])
|
| 43 |
+
assert split_super_sub("w𝟙2𝟙") == ("w", [], ["𝟙2𝟙"])
|
| 44 |
+
assert split_super_sub("w1^a") == ("w", ["a"], ["1"])
|
| 45 |
+
assert split_super_sub("ω1") == ("ω", [], ["1"])
|
| 46 |
+
assert split_super_sub("ω11") == ("ω", [], ["11"])
|
| 47 |
+
assert split_super_sub("ω1^a") == ("ω", ["a"], ["1"])
|
| 48 |
+
assert split_super_sub("ω𝟙^α") == ("ω", ["α"], ["𝟙"])
|
| 49 |
+
assert split_super_sub("ω𝟙2^3α") == ("ω", ["3α"], ["𝟙2"])
|
| 50 |
+
assert split_super_sub("") == ("", [], [])
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def test_requires_partial():
|
| 54 |
+
x, y, z, t, nu = symbols('x y z t nu')
|
| 55 |
+
n = symbols('n', integer=True)
|
| 56 |
+
|
| 57 |
+
f = x * y
|
| 58 |
+
assert requires_partial(Derivative(f, x)) is True
|
| 59 |
+
assert requires_partial(Derivative(f, y)) is True
|
| 60 |
+
|
| 61 |
+
## integrating out one of the variables
|
| 62 |
+
assert requires_partial(Derivative(Integral(exp(-x * y), (x, 0, oo)), y, evaluate=False)) is False
|
| 63 |
+
|
| 64 |
+
## bessel function with smooth parameter
|
| 65 |
+
f = besselj(nu, x)
|
| 66 |
+
assert requires_partial(Derivative(f, x)) is True
|
| 67 |
+
assert requires_partial(Derivative(f, nu)) is True
|
| 68 |
+
|
| 69 |
+
## bessel function with integer parameter
|
| 70 |
+
f = besselj(n, x)
|
| 71 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 72 |
+
# this is not really valid (differentiating with respect to an integer)
|
| 73 |
+
# but there's no reason to use the partial derivative symbol there. make
|
| 74 |
+
# sure we don't throw an exception here, though
|
| 75 |
+
assert requires_partial(Derivative(f, n)) is False
|
| 76 |
+
|
| 77 |
+
## bell polynomial
|
| 78 |
+
f = bell(n, x)
|
| 79 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 80 |
+
# again, invalid
|
| 81 |
+
assert requires_partial(Derivative(f, n)) is False
|
| 82 |
+
|
| 83 |
+
## legendre polynomial
|
| 84 |
+
f = legendre(0, x)
|
| 85 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 86 |
+
|
| 87 |
+
f = legendre(n, x)
|
| 88 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 89 |
+
# again, invalid
|
| 90 |
+
assert requires_partial(Derivative(f, n)) is False
|
| 91 |
+
|
| 92 |
+
f = x ** n
|
| 93 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 94 |
+
|
| 95 |
+
assert requires_partial(Derivative(Integral((x*y) ** n * exp(-x * y), (x, 0, oo)), y, evaluate=False)) is False
|
| 96 |
+
|
| 97 |
+
# parametric equation
|
| 98 |
+
f = (exp(t), cos(t))
|
| 99 |
+
g = sum(f)
|
| 100 |
+
assert requires_partial(Derivative(g, t)) is False
|
| 101 |
+
|
| 102 |
+
f = symbols('f', cls=Function)
|
| 103 |
+
assert requires_partial(Derivative(f(x), x)) is False
|
| 104 |
+
assert requires_partial(Derivative(f(x), y)) is False
|
| 105 |
+
assert requires_partial(Derivative(f(x, y), x)) is True
|
| 106 |
+
assert requires_partial(Derivative(f(x, y), y)) is True
|
| 107 |
+
assert requires_partial(Derivative(f(x, y), z)) is True
|
| 108 |
+
assert requires_partial(Derivative(f(x, y), x, y)) is True
|
| 109 |
+
|
| 110 |
+
@XFAIL
|
| 111 |
+
def test_requires_partial_unspecified_variables():
|
| 112 |
+
x, y = symbols('x y')
|
| 113 |
+
# function of unspecified variables
|
| 114 |
+
f = symbols('f', cls=Function)
|
| 115 |
+
assert requires_partial(Derivative(f, x)) is False
|
| 116 |
+
assert requires_partial(Derivative(f, x, y)) is True
|
lib/python3.12/site-packages/sympy/printing/tests/test_gtk.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.functions.elementary.trigonometric import sin
|
| 2 |
+
from sympy.printing.gtk import print_gtk
|
| 3 |
+
from sympy.testing.pytest import XFAIL, raises
|
| 4 |
+
|
| 5 |
+
# this test fails if python-lxml isn't installed. We don't want to depend on
|
| 6 |
+
# anything with SymPy
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
@XFAIL
|
| 10 |
+
def test_1():
|
| 11 |
+
from sympy.abc import x
|
| 12 |
+
print_gtk(x**2, start_viewer=False)
|
| 13 |
+
print_gtk(x**2 + sin(x)/4, start_viewer=False)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_settings():
|
| 17 |
+
from sympy.abc import x
|
| 18 |
+
raises(TypeError, lambda: print_gtk(x, method="garbage"))
|
lib/python3.12/site-packages/sympy/printing/tests/test_jax.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.mod import Mod
|
| 3 |
+
from sympy.core.relational import (Equality, Unequality)
|
| 4 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 5 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 6 |
+
from sympy.matrices.expressions.blockmatrix import BlockMatrix
|
| 7 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 8 |
+
from sympy.matrices.expressions.special import Identity
|
| 9 |
+
from sympy.utilities.lambdify import lambdify
|
| 10 |
+
|
| 11 |
+
from sympy.abc import x, i, j, a, b, c, d
|
| 12 |
+
from sympy.core import Function, Pow, Symbol
|
| 13 |
+
from sympy.codegen.matrix_nodes import MatrixSolve
|
| 14 |
+
from sympy.codegen.numpy_nodes import logaddexp, logaddexp2
|
| 15 |
+
from sympy.codegen.cfunctions import log1p, expm1, hypot, log10, exp2, log2, Sqrt
|
| 16 |
+
from sympy.tensor.array import Array
|
| 17 |
+
from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \
|
| 18 |
+
PermuteDims, ArrayDiagonal
|
| 19 |
+
from sympy.printing.numpy import JaxPrinter, _jax_known_constants, _jax_known_functions
|
| 20 |
+
from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array
|
| 21 |
+
|
| 22 |
+
from sympy.testing.pytest import skip, raises
|
| 23 |
+
from sympy.external import import_module
|
| 24 |
+
|
| 25 |
+
# Unlike NumPy which will aggressively promote operands to double precision,
|
| 26 |
+
# jax always uses single precision. Double precision in jax can be
|
| 27 |
+
# configured before the call to `import jax`, however this must be explicitly
|
| 28 |
+
# configured and is not fully supported. Thus, the tests here have been modified
|
| 29 |
+
# from the tests in test_numpy.py, only in the fact that they assert lambdify
|
| 30 |
+
# function accuracy to only single precision accuracy.
|
| 31 |
+
# https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#double-64bit-precision
|
| 32 |
+
|
| 33 |
+
jax = import_module('jax')
|
| 34 |
+
|
| 35 |
+
if jax:
|
| 36 |
+
deafult_float_info = jax.numpy.finfo(jax.numpy.array([]).dtype)
|
| 37 |
+
JAX_DEFAULT_EPSILON = deafult_float_info.eps
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def test_jax_piecewise_regression():
|
| 41 |
+
"""
|
| 42 |
+
NumPyPrinter needs to print Piecewise()'s choicelist as a list to avoid
|
| 43 |
+
breaking compatibility with numpy 1.8. This is not necessary in numpy 1.9+.
|
| 44 |
+
See gh-9747 and gh-9749 for details.
|
| 45 |
+
"""
|
| 46 |
+
printer = JaxPrinter()
|
| 47 |
+
p = Piecewise((1, x < 0), (0, True))
|
| 48 |
+
assert printer.doprint(p) == \
|
| 49 |
+
'jax.numpy.select([jax.numpy.less(x, 0),True], [1,0], default=jax.numpy.nan)'
|
| 50 |
+
assert printer.module_imports == {'jax.numpy': {'select', 'less', 'nan'}}
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def test_jax_logaddexp():
|
| 54 |
+
lae = logaddexp(a, b)
|
| 55 |
+
assert JaxPrinter().doprint(lae) == 'jax.numpy.logaddexp(a, b)'
|
| 56 |
+
lae2 = logaddexp2(a, b)
|
| 57 |
+
assert JaxPrinter().doprint(lae2) == 'jax.numpy.logaddexp2(a, b)'
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_jax_sum():
|
| 61 |
+
if not jax:
|
| 62 |
+
skip("JAX not installed")
|
| 63 |
+
|
| 64 |
+
s = Sum(x ** i, (i, a, b))
|
| 65 |
+
f = lambdify((a, b, x), s, 'jax')
|
| 66 |
+
|
| 67 |
+
a_, b_ = 0, 10
|
| 68 |
+
x_ = jax.numpy.linspace(-1, +1, 10)
|
| 69 |
+
assert jax.numpy.allclose(f(a_, b_, x_), sum(x_ ** i_ for i_ in range(a_, b_ + 1)))
|
| 70 |
+
|
| 71 |
+
s = Sum(i * x, (i, a, b))
|
| 72 |
+
f = lambdify((a, b, x), s, 'jax')
|
| 73 |
+
|
| 74 |
+
a_, b_ = 0, 10
|
| 75 |
+
x_ = jax.numpy.linspace(-1, +1, 10)
|
| 76 |
+
assert jax.numpy.allclose(f(a_, b_, x_), sum(i_ * x_ for i_ in range(a_, b_ + 1)))
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def test_jax_multiple_sums():
|
| 80 |
+
if not jax:
|
| 81 |
+
skip("JAX not installed")
|
| 82 |
+
|
| 83 |
+
s = Sum((x + j) * i, (i, a, b), (j, c, d))
|
| 84 |
+
f = lambdify((a, b, c, d, x), s, 'jax')
|
| 85 |
+
|
| 86 |
+
a_, b_ = 0, 10
|
| 87 |
+
c_, d_ = 11, 21
|
| 88 |
+
x_ = jax.numpy.linspace(-1, +1, 10)
|
| 89 |
+
assert jax.numpy.allclose(f(a_, b_, c_, d_, x_),
|
| 90 |
+
sum((x_ + j_) * i_ for i_ in range(a_, b_ + 1) for j_ in range(c_, d_ + 1)))
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def test_jax_codegen_einsum():
|
| 94 |
+
if not jax:
|
| 95 |
+
skip("JAX not installed")
|
| 96 |
+
|
| 97 |
+
M = MatrixSymbol("M", 2, 2)
|
| 98 |
+
N = MatrixSymbol("N", 2, 2)
|
| 99 |
+
|
| 100 |
+
cg = convert_matrix_to_array(M * N)
|
| 101 |
+
f = lambdify((M, N), cg, 'jax')
|
| 102 |
+
|
| 103 |
+
ma = jax.numpy.array([[1, 2], [3, 4]])
|
| 104 |
+
mb = jax.numpy.array([[1,-2], [-1, 3]])
|
| 105 |
+
assert (f(ma, mb) == jax.numpy.matmul(ma, mb)).all()
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def test_jax_codegen_extra():
|
| 109 |
+
if not jax:
|
| 110 |
+
skip("JAX not installed")
|
| 111 |
+
|
| 112 |
+
M = MatrixSymbol("M", 2, 2)
|
| 113 |
+
N = MatrixSymbol("N", 2, 2)
|
| 114 |
+
P = MatrixSymbol("P", 2, 2)
|
| 115 |
+
Q = MatrixSymbol("Q", 2, 2)
|
| 116 |
+
ma = jax.numpy.array([[1, 2], [3, 4]])
|
| 117 |
+
mb = jax.numpy.array([[1,-2], [-1, 3]])
|
| 118 |
+
mc = jax.numpy.array([[2, 0], [1, 2]])
|
| 119 |
+
md = jax.numpy.array([[1,-1], [4, 7]])
|
| 120 |
+
|
| 121 |
+
cg = ArrayTensorProduct(M, N)
|
| 122 |
+
f = lambdify((M, N), cg, 'jax')
|
| 123 |
+
assert (f(ma, mb) == jax.numpy.einsum(ma, [0, 1], mb, [2, 3])).all()
|
| 124 |
+
|
| 125 |
+
cg = ArrayAdd(M, N)
|
| 126 |
+
f = lambdify((M, N), cg, 'jax')
|
| 127 |
+
assert (f(ma, mb) == ma+mb).all()
|
| 128 |
+
|
| 129 |
+
cg = ArrayAdd(M, N, P)
|
| 130 |
+
f = lambdify((M, N, P), cg, 'jax')
|
| 131 |
+
assert (f(ma, mb, mc) == ma+mb+mc).all()
|
| 132 |
+
|
| 133 |
+
cg = ArrayAdd(M, N, P, Q)
|
| 134 |
+
f = lambdify((M, N, P, Q), cg, 'jax')
|
| 135 |
+
assert (f(ma, mb, mc, md) == ma+mb+mc+md).all()
|
| 136 |
+
|
| 137 |
+
cg = PermuteDims(M, [1, 0])
|
| 138 |
+
f = lambdify((M,), cg, 'jax')
|
| 139 |
+
assert (f(ma) == ma.T).all()
|
| 140 |
+
|
| 141 |
+
cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0])
|
| 142 |
+
f = lambdify((M, N), cg, 'jax')
|
| 143 |
+
assert (f(ma, mb) == jax.numpy.transpose(jax.numpy.einsum(ma, [0, 1], mb, [2, 3]), (1, 2, 3, 0))).all()
|
| 144 |
+
|
| 145 |
+
cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2))
|
| 146 |
+
f = lambdify((M, N), cg, 'jax')
|
| 147 |
+
assert (f(ma, mb) == jax.numpy.diagonal(jax.numpy.einsum(ma, [0, 1], mb, [2, 3]), axis1=1, axis2=2)).all()
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test_jax_relational():
|
| 151 |
+
if not jax:
|
| 152 |
+
skip("JAX not installed")
|
| 153 |
+
|
| 154 |
+
e = Equality(x, 1)
|
| 155 |
+
|
| 156 |
+
f = lambdify((x,), e, 'jax')
|
| 157 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 158 |
+
assert jax.numpy.array_equal(f(x_), [False, True, False])
|
| 159 |
+
|
| 160 |
+
e = Unequality(x, 1)
|
| 161 |
+
|
| 162 |
+
f = lambdify((x,), e, 'jax')
|
| 163 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 164 |
+
assert jax.numpy.array_equal(f(x_), [True, False, True])
|
| 165 |
+
|
| 166 |
+
e = (x < 1)
|
| 167 |
+
|
| 168 |
+
f = lambdify((x,), e, 'jax')
|
| 169 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 170 |
+
assert jax.numpy.array_equal(f(x_), [True, False, False])
|
| 171 |
+
|
| 172 |
+
e = (x <= 1)
|
| 173 |
+
|
| 174 |
+
f = lambdify((x,), e, 'jax')
|
| 175 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 176 |
+
assert jax.numpy.array_equal(f(x_), [True, True, False])
|
| 177 |
+
|
| 178 |
+
e = (x > 1)
|
| 179 |
+
|
| 180 |
+
f = lambdify((x,), e, 'jax')
|
| 181 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 182 |
+
assert jax.numpy.array_equal(f(x_), [False, False, True])
|
| 183 |
+
|
| 184 |
+
e = (x >= 1)
|
| 185 |
+
|
| 186 |
+
f = lambdify((x,), e, 'jax')
|
| 187 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 188 |
+
assert jax.numpy.array_equal(f(x_), [False, True, True])
|
| 189 |
+
|
| 190 |
+
# Multi-condition expressions
|
| 191 |
+
e = (x >= 1) & (x < 2)
|
| 192 |
+
f = lambdify((x,), e, 'jax')
|
| 193 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 194 |
+
assert jax.numpy.array_equal(f(x_), [False, True, False])
|
| 195 |
+
|
| 196 |
+
e = (x >= 1) | (x < 2)
|
| 197 |
+
f = lambdify((x,), e, 'jax')
|
| 198 |
+
x_ = jax.numpy.array([0, 1, 2])
|
| 199 |
+
assert jax.numpy.array_equal(f(x_), [True, True, True])
|
| 200 |
+
|
| 201 |
+
def test_jax_mod():
|
| 202 |
+
if not jax:
|
| 203 |
+
skip("JAX not installed")
|
| 204 |
+
|
| 205 |
+
e = Mod(a, b)
|
| 206 |
+
f = lambdify((a, b), e, 'jax')
|
| 207 |
+
|
| 208 |
+
a_ = jax.numpy.array([0, 1, 2, 3])
|
| 209 |
+
b_ = 2
|
| 210 |
+
assert jax.numpy.array_equal(f(a_, b_), [0, 1, 0, 1])
|
| 211 |
+
|
| 212 |
+
a_ = jax.numpy.array([0, 1, 2, 3])
|
| 213 |
+
b_ = jax.numpy.array([2, 2, 2, 2])
|
| 214 |
+
assert jax.numpy.array_equal(f(a_, b_), [0, 1, 0, 1])
|
| 215 |
+
|
| 216 |
+
a_ = jax.numpy.array([2, 3, 4, 5])
|
| 217 |
+
b_ = jax.numpy.array([2, 3, 4, 5])
|
| 218 |
+
assert jax.numpy.array_equal(f(a_, b_), [0, 0, 0, 0])
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def test_jax_pow():
|
| 222 |
+
if not jax:
|
| 223 |
+
skip('JAX not installed')
|
| 224 |
+
|
| 225 |
+
expr = Pow(2, -1, evaluate=False)
|
| 226 |
+
f = lambdify([], expr, 'jax')
|
| 227 |
+
assert f() == 0.5
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def test_jax_expm1():
|
| 231 |
+
if not jax:
|
| 232 |
+
skip("JAX not installed")
|
| 233 |
+
|
| 234 |
+
f = lambdify((a,), expm1(a), 'jax')
|
| 235 |
+
assert abs(f(1e-10) - 1e-10 - 5e-21) <= 1e-10 * JAX_DEFAULT_EPSILON
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
def test_jax_log1p():
|
| 239 |
+
if not jax:
|
| 240 |
+
skip("JAX not installed")
|
| 241 |
+
|
| 242 |
+
f = lambdify((a,), log1p(a), 'jax')
|
| 243 |
+
assert abs(f(1e-99) - 1e-99) <= 1e-99 * JAX_DEFAULT_EPSILON
|
| 244 |
+
|
| 245 |
+
def test_jax_hypot():
|
| 246 |
+
if not jax:
|
| 247 |
+
skip("JAX not installed")
|
| 248 |
+
assert abs(lambdify((a, b), hypot(a, b), 'jax')(3, 4) - 5) <= JAX_DEFAULT_EPSILON
|
| 249 |
+
|
| 250 |
+
def test_jax_log10():
|
| 251 |
+
if not jax:
|
| 252 |
+
skip("JAX not installed")
|
| 253 |
+
|
| 254 |
+
assert abs(lambdify((a,), log10(a), 'jax')(100) - 2) <= JAX_DEFAULT_EPSILON
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def test_jax_exp2():
|
| 258 |
+
if not jax:
|
| 259 |
+
skip("JAX not installed")
|
| 260 |
+
assert abs(lambdify((a,), exp2(a), 'jax')(5) - 32) <= JAX_DEFAULT_EPSILON
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def test_jax_log2():
|
| 264 |
+
if not jax:
|
| 265 |
+
skip("JAX not installed")
|
| 266 |
+
assert abs(lambdify((a,), log2(a), 'jax')(256) - 8) <= JAX_DEFAULT_EPSILON
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
def test_jax_Sqrt():
|
| 270 |
+
if not jax:
|
| 271 |
+
skip("JAX not installed")
|
| 272 |
+
assert abs(lambdify((a,), Sqrt(a), 'jax')(4) - 2) <= JAX_DEFAULT_EPSILON
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def test_jax_sqrt():
|
| 276 |
+
if not jax:
|
| 277 |
+
skip("JAX not installed")
|
| 278 |
+
assert abs(lambdify((a,), sqrt(a), 'jax')(4) - 2) <= JAX_DEFAULT_EPSILON
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
def test_jax_matsolve():
|
| 282 |
+
if not jax:
|
| 283 |
+
skip("JAX not installed")
|
| 284 |
+
|
| 285 |
+
M = MatrixSymbol("M", 3, 3)
|
| 286 |
+
x = MatrixSymbol("x", 3, 1)
|
| 287 |
+
|
| 288 |
+
expr = M**(-1) * x + x
|
| 289 |
+
matsolve_expr = MatrixSolve(M, x) + x
|
| 290 |
+
|
| 291 |
+
f = lambdify((M, x), expr, 'jax')
|
| 292 |
+
f_matsolve = lambdify((M, x), matsolve_expr, 'jax')
|
| 293 |
+
|
| 294 |
+
m0 = jax.numpy.array([[1, 2, 3], [3, 2, 5], [5, 6, 7]])
|
| 295 |
+
assert jax.numpy.linalg.matrix_rank(m0) == 3
|
| 296 |
+
|
| 297 |
+
x0 = jax.numpy.array([3, 4, 5])
|
| 298 |
+
|
| 299 |
+
assert jax.numpy.allclose(f_matsolve(m0, x0), f(m0, x0))
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def test_16857():
|
| 303 |
+
if not jax:
|
| 304 |
+
skip("JAX not installed")
|
| 305 |
+
|
| 306 |
+
a_1 = MatrixSymbol('a_1', 10, 3)
|
| 307 |
+
a_2 = MatrixSymbol('a_2', 10, 3)
|
| 308 |
+
a_3 = MatrixSymbol('a_3', 10, 3)
|
| 309 |
+
a_4 = MatrixSymbol('a_4', 10, 3)
|
| 310 |
+
A = BlockMatrix([[a_1, a_2], [a_3, a_4]])
|
| 311 |
+
assert A.shape == (20, 6)
|
| 312 |
+
|
| 313 |
+
printer = JaxPrinter()
|
| 314 |
+
assert printer.doprint(A) == 'jax.numpy.block([[a_1, a_2], [a_3, a_4]])'
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def test_issue_17006():
|
| 318 |
+
if not jax:
|
| 319 |
+
skip("JAX not installed")
|
| 320 |
+
|
| 321 |
+
M = MatrixSymbol("M", 2, 2)
|
| 322 |
+
|
| 323 |
+
f = lambdify(M, M + Identity(2), 'jax')
|
| 324 |
+
ma = jax.numpy.array([[1, 2], [3, 4]])
|
| 325 |
+
mr = jax.numpy.array([[2, 2], [3, 5]])
|
| 326 |
+
|
| 327 |
+
assert (f(ma) == mr).all()
|
| 328 |
+
|
| 329 |
+
from sympy.core.symbol import symbols
|
| 330 |
+
n = symbols('n', integer=True)
|
| 331 |
+
N = MatrixSymbol("M", n, n)
|
| 332 |
+
raises(NotImplementedError, lambda: lambdify(N, N + Identity(n), 'jax'))
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
def test_jax_array():
|
| 336 |
+
assert JaxPrinter().doprint(Array(((1, 2), (3, 5)))) == 'jax.numpy.array([[1, 2], [3, 5]])'
|
| 337 |
+
assert JaxPrinter().doprint(Array((1, 2))) == 'jax.numpy.array((1, 2))'
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
def test_jax_known_funcs_consts():
|
| 341 |
+
assert _jax_known_constants['NaN'] == 'jax.numpy.nan'
|
| 342 |
+
assert _jax_known_constants['EulerGamma'] == 'jax.numpy.euler_gamma'
|
| 343 |
+
|
| 344 |
+
assert _jax_known_functions['acos'] == 'jax.numpy.arccos'
|
| 345 |
+
assert _jax_known_functions['log'] == 'jax.numpy.log'
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def test_jax_print_methods():
|
| 349 |
+
prntr = JaxPrinter()
|
| 350 |
+
assert hasattr(prntr, '_print_acos')
|
| 351 |
+
assert hasattr(prntr, '_print_log')
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
def test_jax_printmethod():
|
| 355 |
+
printer = JaxPrinter()
|
| 356 |
+
assert hasattr(printer, 'printmethod')
|
| 357 |
+
assert printer.printmethod == '_jaxcode'
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
def test_jax_custom_print_method():
|
| 361 |
+
|
| 362 |
+
class expm1(Function):
|
| 363 |
+
|
| 364 |
+
def _jaxcode(self, printer):
|
| 365 |
+
x, = self.args
|
| 366 |
+
function = f'expm1({printer._print(x)})'
|
| 367 |
+
return printer._module_format(printer._module + '.' + function)
|
| 368 |
+
|
| 369 |
+
printer = JaxPrinter()
|
| 370 |
+
assert printer.doprint(expm1(Symbol('x'))) == 'jax.numpy.expm1(x)'
|
lib/python3.12/site-packages/sympy/printing/tests/test_jscode.py
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import (pi, oo, symbols, Rational, Integer, GoldenRatio,
|
| 2 |
+
EulerGamma, Catalan, Lambda, Dummy, S, Eq, Ne, Le,
|
| 3 |
+
Lt, Gt, Ge, Mod)
|
| 4 |
+
from sympy.functions import (Piecewise, sin, cos, Abs, exp, ceiling, sqrt,
|
| 5 |
+
sinh, cosh, tanh, asin, acos, acosh, Max, Min)
|
| 6 |
+
from sympy.testing.pytest import raises
|
| 7 |
+
from sympy.printing.jscode import JavascriptCodePrinter
|
| 8 |
+
from sympy.utilities.lambdify import implemented_function
|
| 9 |
+
from sympy.tensor import IndexedBase, Idx
|
| 10 |
+
from sympy.matrices import Matrix, MatrixSymbol
|
| 11 |
+
|
| 12 |
+
from sympy.printing.jscode import jscode
|
| 13 |
+
|
| 14 |
+
x, y, z = symbols('x,y,z')
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def test_printmethod():
|
| 18 |
+
assert jscode(Abs(x)) == "Math.abs(x)"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_jscode_sqrt():
|
| 22 |
+
assert jscode(sqrt(x)) == "Math.sqrt(x)"
|
| 23 |
+
assert jscode(x**0.5) == "Math.sqrt(x)"
|
| 24 |
+
assert jscode(x**(S.One/3)) == "Math.cbrt(x)"
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def test_jscode_Pow():
|
| 28 |
+
g = implemented_function('g', Lambda(x, 2*x))
|
| 29 |
+
assert jscode(x**3) == "Math.pow(x, 3)"
|
| 30 |
+
assert jscode(x**(y**3)) == "Math.pow(x, Math.pow(y, 3))"
|
| 31 |
+
assert jscode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \
|
| 32 |
+
"Math.pow(3.5*2*x, -x + Math.pow(y, x))/(Math.pow(x, 2) + y)"
|
| 33 |
+
assert jscode(x**-1.0) == '1/x'
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def test_jscode_constants_mathh():
|
| 37 |
+
assert jscode(exp(1)) == "Math.E"
|
| 38 |
+
assert jscode(pi) == "Math.PI"
|
| 39 |
+
assert jscode(oo) == "Number.POSITIVE_INFINITY"
|
| 40 |
+
assert jscode(-oo) == "Number.NEGATIVE_INFINITY"
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def test_jscode_constants_other():
|
| 44 |
+
assert jscode(
|
| 45 |
+
2*GoldenRatio) == "var GoldenRatio = %s;\n2*GoldenRatio" % GoldenRatio.evalf(17)
|
| 46 |
+
assert jscode(2*Catalan) == "var Catalan = %s;\n2*Catalan" % Catalan.evalf(17)
|
| 47 |
+
assert jscode(
|
| 48 |
+
2*EulerGamma) == "var EulerGamma = %s;\n2*EulerGamma" % EulerGamma.evalf(17)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def test_jscode_Rational():
|
| 52 |
+
assert jscode(Rational(3, 7)) == "3/7"
|
| 53 |
+
assert jscode(Rational(18, 9)) == "2"
|
| 54 |
+
assert jscode(Rational(3, -7)) == "-3/7"
|
| 55 |
+
assert jscode(Rational(-3, -7)) == "3/7"
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def test_Relational():
|
| 59 |
+
assert jscode(Eq(x, y)) == "x == y"
|
| 60 |
+
assert jscode(Ne(x, y)) == "x != y"
|
| 61 |
+
assert jscode(Le(x, y)) == "x <= y"
|
| 62 |
+
assert jscode(Lt(x, y)) == "x < y"
|
| 63 |
+
assert jscode(Gt(x, y)) == "x > y"
|
| 64 |
+
assert jscode(Ge(x, y)) == "x >= y"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_Mod():
|
| 68 |
+
assert jscode(Mod(x, y)) == '((x % y) + y) % y'
|
| 69 |
+
assert jscode(Mod(x, x + y)) == '((x % (x + y)) + (x + y)) % (x + y)'
|
| 70 |
+
p1, p2 = symbols('p1 p2', positive=True)
|
| 71 |
+
assert jscode(Mod(p1, p2)) == 'p1 % p2'
|
| 72 |
+
assert jscode(Mod(p1, p2 + 3)) == 'p1 % (p2 + 3)'
|
| 73 |
+
assert jscode(Mod(-3, -7, evaluate=False)) == '(-3) % (-7)'
|
| 74 |
+
assert jscode(-Mod(p1, p2)) == '-(p1 % p2)'
|
| 75 |
+
assert jscode(x*Mod(p1, p2)) == 'x*(p1 % p2)'
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def test_jscode_Integer():
|
| 79 |
+
assert jscode(Integer(67)) == "67"
|
| 80 |
+
assert jscode(Integer(-1)) == "-1"
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def test_jscode_functions():
|
| 84 |
+
assert jscode(sin(x) ** cos(x)) == "Math.pow(Math.sin(x), Math.cos(x))"
|
| 85 |
+
assert jscode(sinh(x) * cosh(x)) == "Math.sinh(x)*Math.cosh(x)"
|
| 86 |
+
assert jscode(Max(x, y) + Min(x, y)) == "Math.max(x, y) + Math.min(x, y)"
|
| 87 |
+
assert jscode(tanh(x)*acosh(y)) == "Math.tanh(x)*Math.acosh(y)"
|
| 88 |
+
assert jscode(asin(x)-acos(y)) == "-Math.acos(y) + Math.asin(x)"
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def test_jscode_inline_function():
|
| 92 |
+
x = symbols('x')
|
| 93 |
+
g = implemented_function('g', Lambda(x, 2*x))
|
| 94 |
+
assert jscode(g(x)) == "2*x"
|
| 95 |
+
g = implemented_function('g', Lambda(x, 2*x/Catalan))
|
| 96 |
+
assert jscode(g(x)) == "var Catalan = %s;\n2*x/Catalan" % Catalan.evalf(17)
|
| 97 |
+
A = IndexedBase('A')
|
| 98 |
+
i = Idx('i', symbols('n', integer=True))
|
| 99 |
+
g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x)))
|
| 100 |
+
assert jscode(g(A[i]), assign_to=A[i]) == (
|
| 101 |
+
"for (var i=0; i<n; i++){\n"
|
| 102 |
+
" A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n"
|
| 103 |
+
"}"
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def test_jscode_exceptions():
|
| 108 |
+
assert jscode(ceiling(x)) == "Math.ceil(x)"
|
| 109 |
+
assert jscode(Abs(x)) == "Math.abs(x)"
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def test_jscode_boolean():
|
| 113 |
+
assert jscode(x & y) == "x && y"
|
| 114 |
+
assert jscode(x | y) == "x || y"
|
| 115 |
+
assert jscode(~x) == "!x"
|
| 116 |
+
assert jscode(x & y & z) == "x && y && z"
|
| 117 |
+
assert jscode(x | y | z) == "x || y || z"
|
| 118 |
+
assert jscode((x & y) | z) == "z || x && y"
|
| 119 |
+
assert jscode((x | y) & z) == "z && (x || y)"
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def test_jscode_Piecewise():
|
| 123 |
+
expr = Piecewise((x, x < 1), (x**2, True))
|
| 124 |
+
p = jscode(expr)
|
| 125 |
+
s = \
|
| 126 |
+
"""\
|
| 127 |
+
((x < 1) ? (
|
| 128 |
+
x
|
| 129 |
+
)
|
| 130 |
+
: (
|
| 131 |
+
Math.pow(x, 2)
|
| 132 |
+
))\
|
| 133 |
+
"""
|
| 134 |
+
assert p == s
|
| 135 |
+
assert jscode(expr, assign_to="c") == (
|
| 136 |
+
"if (x < 1) {\n"
|
| 137 |
+
" c = x;\n"
|
| 138 |
+
"}\n"
|
| 139 |
+
"else {\n"
|
| 140 |
+
" c = Math.pow(x, 2);\n"
|
| 141 |
+
"}")
|
| 142 |
+
# Check that Piecewise without a True (default) condition error
|
| 143 |
+
expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0))
|
| 144 |
+
raises(ValueError, lambda: jscode(expr))
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def test_jscode_Piecewise_deep():
|
| 148 |
+
p = jscode(2*Piecewise((x, x < 1), (x**2, True)))
|
| 149 |
+
s = \
|
| 150 |
+
"""\
|
| 151 |
+
2*((x < 1) ? (
|
| 152 |
+
x
|
| 153 |
+
)
|
| 154 |
+
: (
|
| 155 |
+
Math.pow(x, 2)
|
| 156 |
+
))\
|
| 157 |
+
"""
|
| 158 |
+
assert p == s
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def test_jscode_settings():
|
| 162 |
+
raises(TypeError, lambda: jscode(sin(x), method="garbage"))
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
def test_jscode_Indexed():
|
| 166 |
+
n, m, o = symbols('n m o', integer=True)
|
| 167 |
+
i, j, k = Idx('i', n), Idx('j', m), Idx('k', o)
|
| 168 |
+
p = JavascriptCodePrinter()
|
| 169 |
+
p._not_c = set()
|
| 170 |
+
|
| 171 |
+
x = IndexedBase('x')[j]
|
| 172 |
+
assert p._print_Indexed(x) == 'x[j]'
|
| 173 |
+
A = IndexedBase('A')[i, j]
|
| 174 |
+
assert p._print_Indexed(A) == 'A[%s]' % (m*i+j)
|
| 175 |
+
B = IndexedBase('B')[i, j, k]
|
| 176 |
+
assert p._print_Indexed(B) == 'B[%s]' % (i*o*m+j*o+k)
|
| 177 |
+
|
| 178 |
+
assert p._not_c == set()
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def test_jscode_loops_matrix_vector():
|
| 182 |
+
n, m = symbols('n m', integer=True)
|
| 183 |
+
A = IndexedBase('A')
|
| 184 |
+
x = IndexedBase('x')
|
| 185 |
+
y = IndexedBase('y')
|
| 186 |
+
i = Idx('i', m)
|
| 187 |
+
j = Idx('j', n)
|
| 188 |
+
|
| 189 |
+
s = (
|
| 190 |
+
'for (var i=0; i<m; i++){\n'
|
| 191 |
+
' y[i] = 0;\n'
|
| 192 |
+
'}\n'
|
| 193 |
+
'for (var i=0; i<m; i++){\n'
|
| 194 |
+
' for (var j=0; j<n; j++){\n'
|
| 195 |
+
' y[i] = A[n*i + j]*x[j] + y[i];\n'
|
| 196 |
+
' }\n'
|
| 197 |
+
'}'
|
| 198 |
+
)
|
| 199 |
+
c = jscode(A[i, j]*x[j], assign_to=y[i])
|
| 200 |
+
assert c == s
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def test_dummy_loops():
|
| 204 |
+
i, m = symbols('i m', integer=True, cls=Dummy)
|
| 205 |
+
x = IndexedBase('x')
|
| 206 |
+
y = IndexedBase('y')
|
| 207 |
+
i = Idx(i, m)
|
| 208 |
+
|
| 209 |
+
expected = (
|
| 210 |
+
'for (var i_%(icount)i=0; i_%(icount)i<m_%(mcount)i; i_%(icount)i++){\n'
|
| 211 |
+
' y[i_%(icount)i] = x[i_%(icount)i];\n'
|
| 212 |
+
'}'
|
| 213 |
+
) % {'icount': i.label.dummy_index, 'mcount': m.dummy_index}
|
| 214 |
+
code = jscode(x[i], assign_to=y[i])
|
| 215 |
+
assert code == expected
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
def test_jscode_loops_add():
|
| 219 |
+
n, m = symbols('n m', integer=True)
|
| 220 |
+
A = IndexedBase('A')
|
| 221 |
+
x = IndexedBase('x')
|
| 222 |
+
y = IndexedBase('y')
|
| 223 |
+
z = IndexedBase('z')
|
| 224 |
+
i = Idx('i', m)
|
| 225 |
+
j = Idx('j', n)
|
| 226 |
+
|
| 227 |
+
s = (
|
| 228 |
+
'for (var i=0; i<m; i++){\n'
|
| 229 |
+
' y[i] = x[i] + z[i];\n'
|
| 230 |
+
'}\n'
|
| 231 |
+
'for (var i=0; i<m; i++){\n'
|
| 232 |
+
' for (var j=0; j<n; j++){\n'
|
| 233 |
+
' y[i] = A[n*i + j]*x[j] + y[i];\n'
|
| 234 |
+
' }\n'
|
| 235 |
+
'}'
|
| 236 |
+
)
|
| 237 |
+
c = jscode(A[i, j]*x[j] + x[i] + z[i], assign_to=y[i])
|
| 238 |
+
assert c == s
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def test_jscode_loops_multiple_contractions():
|
| 242 |
+
n, m, o, p = symbols('n m o p', integer=True)
|
| 243 |
+
a = IndexedBase('a')
|
| 244 |
+
b = IndexedBase('b')
|
| 245 |
+
y = IndexedBase('y')
|
| 246 |
+
i = Idx('i', m)
|
| 247 |
+
j = Idx('j', n)
|
| 248 |
+
k = Idx('k', o)
|
| 249 |
+
l = Idx('l', p)
|
| 250 |
+
|
| 251 |
+
s = (
|
| 252 |
+
'for (var i=0; i<m; i++){\n'
|
| 253 |
+
' y[i] = 0;\n'
|
| 254 |
+
'}\n'
|
| 255 |
+
'for (var i=0; i<m; i++){\n'
|
| 256 |
+
' for (var j=0; j<n; j++){\n'
|
| 257 |
+
' for (var k=0; k<o; k++){\n'
|
| 258 |
+
' for (var l=0; l<p; l++){\n'
|
| 259 |
+
' y[i] = a[%s]*b[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\
|
| 260 |
+
' }\n'
|
| 261 |
+
' }\n'
|
| 262 |
+
' }\n'
|
| 263 |
+
'}'
|
| 264 |
+
)
|
| 265 |
+
c = jscode(b[j, k, l]*a[i, j, k, l], assign_to=y[i])
|
| 266 |
+
assert c == s
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
def test_jscode_loops_addfactor():
|
| 270 |
+
n, m, o, p = symbols('n m o p', integer=True)
|
| 271 |
+
a = IndexedBase('a')
|
| 272 |
+
b = IndexedBase('b')
|
| 273 |
+
c = IndexedBase('c')
|
| 274 |
+
y = IndexedBase('y')
|
| 275 |
+
i = Idx('i', m)
|
| 276 |
+
j = Idx('j', n)
|
| 277 |
+
k = Idx('k', o)
|
| 278 |
+
l = Idx('l', p)
|
| 279 |
+
|
| 280 |
+
s = (
|
| 281 |
+
'for (var i=0; i<m; i++){\n'
|
| 282 |
+
' y[i] = 0;\n'
|
| 283 |
+
'}\n'
|
| 284 |
+
'for (var i=0; i<m; i++){\n'
|
| 285 |
+
' for (var j=0; j<n; j++){\n'
|
| 286 |
+
' for (var k=0; k<o; k++){\n'
|
| 287 |
+
' for (var l=0; l<p; l++){\n'
|
| 288 |
+
' y[i] = (a[%s] + b[%s])*c[%s] + y[i];\n' % (i*n*o*p + j*o*p + k*p + l, i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\
|
| 289 |
+
' }\n'
|
| 290 |
+
' }\n'
|
| 291 |
+
' }\n'
|
| 292 |
+
'}'
|
| 293 |
+
)
|
| 294 |
+
c = jscode((a[i, j, k, l] + b[i, j, k, l])*c[j, k, l], assign_to=y[i])
|
| 295 |
+
assert c == s
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
def test_jscode_loops_multiple_terms():
|
| 299 |
+
n, m, o, p = symbols('n m o p', integer=True)
|
| 300 |
+
a = IndexedBase('a')
|
| 301 |
+
b = IndexedBase('b')
|
| 302 |
+
c = IndexedBase('c')
|
| 303 |
+
y = IndexedBase('y')
|
| 304 |
+
i = Idx('i', m)
|
| 305 |
+
j = Idx('j', n)
|
| 306 |
+
k = Idx('k', o)
|
| 307 |
+
|
| 308 |
+
s0 = (
|
| 309 |
+
'for (var i=0; i<m; i++){\n'
|
| 310 |
+
' y[i] = 0;\n'
|
| 311 |
+
'}\n'
|
| 312 |
+
)
|
| 313 |
+
s1 = (
|
| 314 |
+
'for (var i=0; i<m; i++){\n'
|
| 315 |
+
' for (var j=0; j<n; j++){\n'
|
| 316 |
+
' for (var k=0; k<o; k++){\n'
|
| 317 |
+
' y[i] = b[j]*b[k]*c[%s] + y[i];\n' % (i*n*o + j*o + k) +\
|
| 318 |
+
' }\n'
|
| 319 |
+
' }\n'
|
| 320 |
+
'}\n'
|
| 321 |
+
)
|
| 322 |
+
s2 = (
|
| 323 |
+
'for (var i=0; i<m; i++){\n'
|
| 324 |
+
' for (var k=0; k<o; k++){\n'
|
| 325 |
+
' y[i] = a[%s]*b[k] + y[i];\n' % (i*o + k) +\
|
| 326 |
+
' }\n'
|
| 327 |
+
'}\n'
|
| 328 |
+
)
|
| 329 |
+
s3 = (
|
| 330 |
+
'for (var i=0; i<m; i++){\n'
|
| 331 |
+
' for (var j=0; j<n; j++){\n'
|
| 332 |
+
' y[i] = a[%s]*b[j] + y[i];\n' % (i*n + j) +\
|
| 333 |
+
' }\n'
|
| 334 |
+
'}\n'
|
| 335 |
+
)
|
| 336 |
+
c = jscode(
|
| 337 |
+
b[j]*a[i, j] + b[k]*a[i, k] + b[j]*b[k]*c[i, j, k], assign_to=y[i])
|
| 338 |
+
assert (c == s0 + s1 + s2 + s3[:-1] or
|
| 339 |
+
c == s0 + s1 + s3 + s2[:-1] or
|
| 340 |
+
c == s0 + s2 + s1 + s3[:-1] or
|
| 341 |
+
c == s0 + s2 + s3 + s1[:-1] or
|
| 342 |
+
c == s0 + s3 + s1 + s2[:-1] or
|
| 343 |
+
c == s0 + s3 + s2 + s1[:-1])
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
def test_Matrix_printing():
|
| 347 |
+
# Test returning a Matrix
|
| 348 |
+
mat = Matrix([x*y, Piecewise((2 + x, y>0), (y, True)), sin(z)])
|
| 349 |
+
A = MatrixSymbol('A', 3, 1)
|
| 350 |
+
assert jscode(mat, A) == (
|
| 351 |
+
"A[0] = x*y;\n"
|
| 352 |
+
"if (y > 0) {\n"
|
| 353 |
+
" A[1] = x + 2;\n"
|
| 354 |
+
"}\n"
|
| 355 |
+
"else {\n"
|
| 356 |
+
" A[1] = y;\n"
|
| 357 |
+
"}\n"
|
| 358 |
+
"A[2] = Math.sin(z);")
|
| 359 |
+
# Test using MatrixElements in expressions
|
| 360 |
+
expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0]
|
| 361 |
+
assert jscode(expr) == (
|
| 362 |
+
"((x > 0) ? (\n"
|
| 363 |
+
" 2*A[2]\n"
|
| 364 |
+
")\n"
|
| 365 |
+
": (\n"
|
| 366 |
+
" A[2]\n"
|
| 367 |
+
")) + Math.sin(A[1]) + A[0]")
|
| 368 |
+
# Test using MatrixElements in a Matrix
|
| 369 |
+
q = MatrixSymbol('q', 5, 1)
|
| 370 |
+
M = MatrixSymbol('M', 3, 3)
|
| 371 |
+
m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])],
|
| 372 |
+
[q[1,0] + q[2,0], q[3, 0], 5],
|
| 373 |
+
[2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]])
|
| 374 |
+
assert jscode(m, M) == (
|
| 375 |
+
"M[0] = Math.sin(q[1]);\n"
|
| 376 |
+
"M[1] = 0;\n"
|
| 377 |
+
"M[2] = Math.cos(q[2]);\n"
|
| 378 |
+
"M[3] = q[1] + q[2];\n"
|
| 379 |
+
"M[4] = q[3];\n"
|
| 380 |
+
"M[5] = 5;\n"
|
| 381 |
+
"M[6] = 2*q[4]/q[1];\n"
|
| 382 |
+
"M[7] = Math.sqrt(q[0]) + 4;\n"
|
| 383 |
+
"M[8] = 0;")
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
def test_MatrixElement_printing():
|
| 387 |
+
# test cases for issue #11821
|
| 388 |
+
A = MatrixSymbol("A", 1, 3)
|
| 389 |
+
B = MatrixSymbol("B", 1, 3)
|
| 390 |
+
C = MatrixSymbol("C", 1, 3)
|
| 391 |
+
|
| 392 |
+
assert(jscode(A[0, 0]) == "A[0]")
|
| 393 |
+
assert(jscode(3 * A[0, 0]) == "3*A[0]")
|
| 394 |
+
|
| 395 |
+
F = C[0, 0].subs(C, A - B)
|
| 396 |
+
assert(jscode(F) == "(A - B)[0]")
|
lib/python3.12/site-packages/sympy/printing/tests/test_julia.py
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer,
|
| 2 |
+
Tuple, Symbol, Eq, Ne, Le, Lt, Gt, Ge)
|
| 3 |
+
from sympy.core import EulerGamma, GoldenRatio, Catalan, Lambda, Mul, Pow
|
| 4 |
+
from sympy.functions import Piecewise, sqrt, ceiling, exp, sin, cos
|
| 5 |
+
from sympy.testing.pytest import raises
|
| 6 |
+
from sympy.utilities.lambdify import implemented_function
|
| 7 |
+
from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity,
|
| 8 |
+
HadamardProduct, SparseMatrix)
|
| 9 |
+
from sympy.functions.special.bessel import (jn, yn, besselj, bessely, besseli,
|
| 10 |
+
besselk, hankel1, hankel2, airyai,
|
| 11 |
+
airybi, airyaiprime, airybiprime)
|
| 12 |
+
from sympy.testing.pytest import XFAIL
|
| 13 |
+
|
| 14 |
+
from sympy.printing.julia import julia_code
|
| 15 |
+
|
| 16 |
+
x, y, z = symbols('x,y,z')
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def test_Integer():
|
| 20 |
+
assert julia_code(Integer(67)) == "67"
|
| 21 |
+
assert julia_code(Integer(-1)) == "-1"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def test_Rational():
|
| 25 |
+
assert julia_code(Rational(3, 7)) == "3 // 7"
|
| 26 |
+
assert julia_code(Rational(18, 9)) == "2"
|
| 27 |
+
assert julia_code(Rational(3, -7)) == "-3 // 7"
|
| 28 |
+
assert julia_code(Rational(-3, -7)) == "3 // 7"
|
| 29 |
+
assert julia_code(x + Rational(3, 7)) == "x + 3 // 7"
|
| 30 |
+
assert julia_code(Rational(3, 7)*x) == "(3 // 7) * x"
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def test_Relational():
|
| 34 |
+
assert julia_code(Eq(x, y)) == "x == y"
|
| 35 |
+
assert julia_code(Ne(x, y)) == "x != y"
|
| 36 |
+
assert julia_code(Le(x, y)) == "x <= y"
|
| 37 |
+
assert julia_code(Lt(x, y)) == "x < y"
|
| 38 |
+
assert julia_code(Gt(x, y)) == "x > y"
|
| 39 |
+
assert julia_code(Ge(x, y)) == "x >= y"
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def test_Function():
|
| 43 |
+
assert julia_code(sin(x) ** cos(x)) == "sin(x) .^ cos(x)"
|
| 44 |
+
assert julia_code(abs(x)) == "abs(x)"
|
| 45 |
+
assert julia_code(ceiling(x)) == "ceil(x)"
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_Pow():
|
| 49 |
+
assert julia_code(x**3) == "x .^ 3"
|
| 50 |
+
assert julia_code(x**(y**3)) == "x .^ (y .^ 3)"
|
| 51 |
+
assert julia_code(x**Rational(2, 3)) == 'x .^ (2 // 3)'
|
| 52 |
+
g = implemented_function('g', Lambda(x, 2*x))
|
| 53 |
+
assert julia_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \
|
| 54 |
+
"(3.5 * 2 * x) .^ (-x + y .^ x) ./ (x .^ 2 + y)"
|
| 55 |
+
# For issue 14160
|
| 56 |
+
assert julia_code(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False),
|
| 57 |
+
evaluate=False)) == '-2 * x ./ (y .* y)'
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_basic_ops():
|
| 61 |
+
assert julia_code(x*y) == "x .* y"
|
| 62 |
+
assert julia_code(x + y) == "x + y"
|
| 63 |
+
assert julia_code(x - y) == "x - y"
|
| 64 |
+
assert julia_code(-x) == "-x"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_1_over_x_and_sqrt():
|
| 68 |
+
# 1.0 and 0.5 would do something different in regular StrPrinter,
|
| 69 |
+
# but these are exact in IEEE floating point so no different here.
|
| 70 |
+
assert julia_code(1/x) == '1 ./ x'
|
| 71 |
+
assert julia_code(x**-1) == julia_code(x**-1.0) == '1 ./ x'
|
| 72 |
+
assert julia_code(1/sqrt(x)) == '1 ./ sqrt(x)'
|
| 73 |
+
assert julia_code(x**-S.Half) == julia_code(x**-0.5) == '1 ./ sqrt(x)'
|
| 74 |
+
assert julia_code(sqrt(x)) == 'sqrt(x)'
|
| 75 |
+
assert julia_code(x**S.Half) == julia_code(x**0.5) == 'sqrt(x)'
|
| 76 |
+
assert julia_code(1/pi) == '1 / pi'
|
| 77 |
+
assert julia_code(pi**-1) == julia_code(pi**-1.0) == '1 / pi'
|
| 78 |
+
assert julia_code(pi**-0.5) == '1 / sqrt(pi)'
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def test_mix_number_mult_symbols():
|
| 82 |
+
assert julia_code(3*x) == "3 * x"
|
| 83 |
+
assert julia_code(pi*x) == "pi * x"
|
| 84 |
+
assert julia_code(3/x) == "3 ./ x"
|
| 85 |
+
assert julia_code(pi/x) == "pi ./ x"
|
| 86 |
+
assert julia_code(x/3) == "x / 3"
|
| 87 |
+
assert julia_code(x/pi) == "x / pi"
|
| 88 |
+
assert julia_code(x*y) == "x .* y"
|
| 89 |
+
assert julia_code(3*x*y) == "3 * x .* y"
|
| 90 |
+
assert julia_code(3*pi*x*y) == "3 * pi * x .* y"
|
| 91 |
+
assert julia_code(x/y) == "x ./ y"
|
| 92 |
+
assert julia_code(3*x/y) == "3 * x ./ y"
|
| 93 |
+
assert julia_code(x*y/z) == "x .* y ./ z"
|
| 94 |
+
assert julia_code(x/y*z) == "x .* z ./ y"
|
| 95 |
+
assert julia_code(1/x/y) == "1 ./ (x .* y)"
|
| 96 |
+
assert julia_code(2*pi*x/y/z) == "2 * pi * x ./ (y .* z)"
|
| 97 |
+
assert julia_code(3*pi/x) == "3 * pi ./ x"
|
| 98 |
+
assert julia_code(S(3)/5) == "3 // 5"
|
| 99 |
+
assert julia_code(S(3)/5*x) == "(3 // 5) * x"
|
| 100 |
+
assert julia_code(x/y/z) == "x ./ (y .* z)"
|
| 101 |
+
assert julia_code((x+y)/z) == "(x + y) ./ z"
|
| 102 |
+
assert julia_code((x+y)/(z+x)) == "(x + y) ./ (x + z)"
|
| 103 |
+
assert julia_code((x+y)/EulerGamma) == "(x + y) / eulergamma"
|
| 104 |
+
assert julia_code(x/3/pi) == "x / (3 * pi)"
|
| 105 |
+
assert julia_code(S(3)/5*x*y/pi) == "(3 // 5) * x .* y / pi"
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def test_mix_number_pow_symbols():
|
| 109 |
+
assert julia_code(pi**3) == 'pi ^ 3'
|
| 110 |
+
assert julia_code(x**2) == 'x .^ 2'
|
| 111 |
+
assert julia_code(x**(pi**3)) == 'x .^ (pi ^ 3)'
|
| 112 |
+
assert julia_code(x**y) == 'x .^ y'
|
| 113 |
+
assert julia_code(x**(y**z)) == 'x .^ (y .^ z)'
|
| 114 |
+
assert julia_code((x**y)**z) == '(x .^ y) .^ z'
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def test_imag():
|
| 118 |
+
I = S('I')
|
| 119 |
+
assert julia_code(I) == "im"
|
| 120 |
+
assert julia_code(5*I) == "5im"
|
| 121 |
+
assert julia_code((S(3)/2)*I) == "(3 // 2) * im"
|
| 122 |
+
assert julia_code(3+4*I) == "3 + 4im"
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def test_constants():
|
| 126 |
+
assert julia_code(pi) == "pi"
|
| 127 |
+
assert julia_code(oo) == "Inf"
|
| 128 |
+
assert julia_code(-oo) == "-Inf"
|
| 129 |
+
assert julia_code(S.NegativeInfinity) == "-Inf"
|
| 130 |
+
assert julia_code(S.NaN) == "NaN"
|
| 131 |
+
assert julia_code(S.Exp1) == "e"
|
| 132 |
+
assert julia_code(exp(1)) == "e"
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def test_constants_other():
|
| 136 |
+
assert julia_code(2*GoldenRatio) == "2 * golden"
|
| 137 |
+
assert julia_code(2*Catalan) == "2 * catalan"
|
| 138 |
+
assert julia_code(2*EulerGamma) == "2 * eulergamma"
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_boolean():
|
| 142 |
+
assert julia_code(x & y) == "x && y"
|
| 143 |
+
assert julia_code(x | y) == "x || y"
|
| 144 |
+
assert julia_code(~x) == "!x"
|
| 145 |
+
assert julia_code(x & y & z) == "x && y && z"
|
| 146 |
+
assert julia_code(x | y | z) == "x || y || z"
|
| 147 |
+
assert julia_code((x & y) | z) == "z || x && y"
|
| 148 |
+
assert julia_code((x | y) & z) == "z && (x || y)"
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def test_Matrices():
|
| 152 |
+
assert julia_code(Matrix(1, 1, [10])) == "[10]"
|
| 153 |
+
A = Matrix([[1, sin(x/2), abs(x)],
|
| 154 |
+
[0, 1, pi],
|
| 155 |
+
[0, exp(1), ceiling(x)]]);
|
| 156 |
+
expected = ("[1 sin(x / 2) abs(x);\n"
|
| 157 |
+
"0 1 pi;\n"
|
| 158 |
+
"0 e ceil(x)]")
|
| 159 |
+
assert julia_code(A) == expected
|
| 160 |
+
# row and columns
|
| 161 |
+
assert julia_code(A[:,0]) == "[1, 0, 0]"
|
| 162 |
+
assert julia_code(A[0,:]) == "[1 sin(x / 2) abs(x)]"
|
| 163 |
+
# empty matrices
|
| 164 |
+
assert julia_code(Matrix(0, 0, [])) == 'zeros(0, 0)'
|
| 165 |
+
assert julia_code(Matrix(0, 3, [])) == 'zeros(0, 3)'
|
| 166 |
+
# annoying to read but correct
|
| 167 |
+
assert julia_code(Matrix([[x, x - y, -y]])) == "[x x - y -y]"
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def test_vector_entries_hadamard():
|
| 171 |
+
# For a row or column, user might to use the other dimension
|
| 172 |
+
A = Matrix([[1, sin(2/x), 3*pi/x/5]])
|
| 173 |
+
assert julia_code(A) == "[1 sin(2 ./ x) (3 // 5) * pi ./ x]"
|
| 174 |
+
assert julia_code(A.T) == "[1, sin(2 ./ x), (3 // 5) * pi ./ x]"
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
@XFAIL
|
| 178 |
+
def test_Matrices_entries_not_hadamard():
|
| 179 |
+
# For Matrix with col >= 2, row >= 2, they need to be scalars
|
| 180 |
+
# FIXME: is it worth worrying about this? Its not wrong, just
|
| 181 |
+
# leave it user's responsibility to put scalar data for x.
|
| 182 |
+
A = Matrix([[1, sin(2/x), 3*pi/x/5], [1, 2, x*y]])
|
| 183 |
+
expected = ("[1 sin(2/x) 3*pi/(5*x);\n"
|
| 184 |
+
"1 2 x*y]") # <- we give x.*y
|
| 185 |
+
assert julia_code(A) == expected
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def test_MatrixSymbol():
|
| 189 |
+
n = Symbol('n', integer=True)
|
| 190 |
+
A = MatrixSymbol('A', n, n)
|
| 191 |
+
B = MatrixSymbol('B', n, n)
|
| 192 |
+
assert julia_code(A*B) == "A * B"
|
| 193 |
+
assert julia_code(B*A) == "B * A"
|
| 194 |
+
assert julia_code(2*A*B) == "2 * A * B"
|
| 195 |
+
assert julia_code(B*2*A) == "2 * B * A"
|
| 196 |
+
assert julia_code(A*(B + 3*Identity(n))) == "A * (3 * eye(n) + B)"
|
| 197 |
+
assert julia_code(A**(x**2)) == "A ^ (x .^ 2)"
|
| 198 |
+
assert julia_code(A**3) == "A ^ 3"
|
| 199 |
+
assert julia_code(A**S.Half) == "A ^ (1 // 2)"
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def test_special_matrices():
|
| 203 |
+
assert julia_code(6*Identity(3)) == "6 * eye(3)"
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
def test_containers():
|
| 207 |
+
assert julia_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \
|
| 208 |
+
"Any[1, 2, 3, Any[4, 5, Any[6, 7]], 8, Any[9, 10], 11]"
|
| 209 |
+
assert julia_code((1, 2, (3, 4))) == "(1, 2, (3, 4))"
|
| 210 |
+
assert julia_code([1]) == "Any[1]"
|
| 211 |
+
assert julia_code((1,)) == "(1,)"
|
| 212 |
+
assert julia_code(Tuple(*[1, 2, 3])) == "(1, 2, 3)"
|
| 213 |
+
assert julia_code((1, x*y, (3, x**2))) == "(1, x .* y, (3, x .^ 2))"
|
| 214 |
+
# scalar, matrix, empty matrix and empty list
|
| 215 |
+
assert julia_code((1, eye(3), Matrix(0, 0, []), [])) == "(1, [1 0 0;\n0 1 0;\n0 0 1], zeros(0, 0), Any[])"
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
def test_julia_noninline():
|
| 219 |
+
source = julia_code((x+y)/Catalan, assign_to='me', inline=False)
|
| 220 |
+
expected = (
|
| 221 |
+
"const Catalan = %s\n"
|
| 222 |
+
"me = (x + y) / Catalan"
|
| 223 |
+
) % Catalan.evalf(17)
|
| 224 |
+
assert source == expected
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def test_julia_piecewise():
|
| 228 |
+
expr = Piecewise((x, x < 1), (x**2, True))
|
| 229 |
+
assert julia_code(expr) == "((x < 1) ? (x) : (x .^ 2))"
|
| 230 |
+
assert julia_code(expr, assign_to="r") == (
|
| 231 |
+
"r = ((x < 1) ? (x) : (x .^ 2))")
|
| 232 |
+
assert julia_code(expr, assign_to="r", inline=False) == (
|
| 233 |
+
"if (x < 1)\n"
|
| 234 |
+
" r = x\n"
|
| 235 |
+
"else\n"
|
| 236 |
+
" r = x .^ 2\n"
|
| 237 |
+
"end")
|
| 238 |
+
expr = Piecewise((x**2, x < 1), (x**3, x < 2), (x**4, x < 3), (x**5, True))
|
| 239 |
+
expected = ("((x < 1) ? (x .^ 2) :\n"
|
| 240 |
+
"(x < 2) ? (x .^ 3) :\n"
|
| 241 |
+
"(x < 3) ? (x .^ 4) : (x .^ 5))")
|
| 242 |
+
assert julia_code(expr) == expected
|
| 243 |
+
assert julia_code(expr, assign_to="r") == "r = " + expected
|
| 244 |
+
assert julia_code(expr, assign_to="r", inline=False) == (
|
| 245 |
+
"if (x < 1)\n"
|
| 246 |
+
" r = x .^ 2\n"
|
| 247 |
+
"elseif (x < 2)\n"
|
| 248 |
+
" r = x .^ 3\n"
|
| 249 |
+
"elseif (x < 3)\n"
|
| 250 |
+
" r = x .^ 4\n"
|
| 251 |
+
"else\n"
|
| 252 |
+
" r = x .^ 5\n"
|
| 253 |
+
"end")
|
| 254 |
+
# Check that Piecewise without a True (default) condition error
|
| 255 |
+
expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0))
|
| 256 |
+
raises(ValueError, lambda: julia_code(expr))
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def test_julia_piecewise_times_const():
|
| 260 |
+
pw = Piecewise((x, x < 1), (x**2, True))
|
| 261 |
+
assert julia_code(2*pw) == "2 * ((x < 1) ? (x) : (x .^ 2))"
|
| 262 |
+
assert julia_code(pw/x) == "((x < 1) ? (x) : (x .^ 2)) ./ x"
|
| 263 |
+
assert julia_code(pw/(x*y)) == "((x < 1) ? (x) : (x .^ 2)) ./ (x .* y)"
|
| 264 |
+
assert julia_code(pw/3) == "((x < 1) ? (x) : (x .^ 2)) / 3"
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
def test_julia_matrix_assign_to():
|
| 268 |
+
A = Matrix([[1, 2, 3]])
|
| 269 |
+
assert julia_code(A, assign_to='a') == "a = [1 2 3]"
|
| 270 |
+
A = Matrix([[1, 2], [3, 4]])
|
| 271 |
+
assert julia_code(A, assign_to='A') == "A = [1 2;\n3 4]"
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def test_julia_matrix_assign_to_more():
|
| 275 |
+
# assigning to Symbol or MatrixSymbol requires lhs/rhs match
|
| 276 |
+
A = Matrix([[1, 2, 3]])
|
| 277 |
+
B = MatrixSymbol('B', 1, 3)
|
| 278 |
+
C = MatrixSymbol('C', 2, 3)
|
| 279 |
+
assert julia_code(A, assign_to=B) == "B = [1 2 3]"
|
| 280 |
+
raises(ValueError, lambda: julia_code(A, assign_to=x))
|
| 281 |
+
raises(ValueError, lambda: julia_code(A, assign_to=C))
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def test_julia_matrix_1x1():
|
| 285 |
+
A = Matrix([[3]])
|
| 286 |
+
B = MatrixSymbol('B', 1, 1)
|
| 287 |
+
C = MatrixSymbol('C', 1, 2)
|
| 288 |
+
assert julia_code(A, assign_to=B) == "B = [3]"
|
| 289 |
+
# FIXME?
|
| 290 |
+
#assert julia_code(A, assign_to=x) == "x = [3]"
|
| 291 |
+
raises(ValueError, lambda: julia_code(A, assign_to=C))
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
def test_julia_matrix_elements():
|
| 295 |
+
A = Matrix([[x, 2, x*y]])
|
| 296 |
+
assert julia_code(A[0, 0]**2 + A[0, 1] + A[0, 2]) == "x .^ 2 + x .* y + 2"
|
| 297 |
+
A = MatrixSymbol('AA', 1, 3)
|
| 298 |
+
assert julia_code(A) == "AA"
|
| 299 |
+
assert julia_code(A[0, 0]**2 + sin(A[0,1]) + A[0,2]) == \
|
| 300 |
+
"sin(AA[1,2]) + AA[1,1] .^ 2 + AA[1,3]"
|
| 301 |
+
assert julia_code(sum(A)) == "AA[1,1] + AA[1,2] + AA[1,3]"
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def test_julia_boolean():
|
| 305 |
+
assert julia_code(True) == "true"
|
| 306 |
+
assert julia_code(S.true) == "true"
|
| 307 |
+
assert julia_code(False) == "false"
|
| 308 |
+
assert julia_code(S.false) == "false"
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def test_julia_not_supported():
|
| 312 |
+
with raises(NotImplementedError):
|
| 313 |
+
julia_code(S.ComplexInfinity)
|
| 314 |
+
|
| 315 |
+
f = Function('f')
|
| 316 |
+
assert julia_code(f(x).diff(x), strict=False) == (
|
| 317 |
+
"# Not supported in Julia:\n"
|
| 318 |
+
"# Derivative\n"
|
| 319 |
+
"Derivative(f(x), x)"
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def test_trick_indent_with_end_else_words():
|
| 324 |
+
# words starting with "end" or "else" do not confuse the indenter
|
| 325 |
+
t1 = S('endless');
|
| 326 |
+
t2 = S('elsewhere');
|
| 327 |
+
pw = Piecewise((t1, x < 0), (t2, x <= 1), (1, True))
|
| 328 |
+
assert julia_code(pw, inline=False) == (
|
| 329 |
+
"if (x < 0)\n"
|
| 330 |
+
" endless\n"
|
| 331 |
+
"elseif (x <= 1)\n"
|
| 332 |
+
" elsewhere\n"
|
| 333 |
+
"else\n"
|
| 334 |
+
" 1\n"
|
| 335 |
+
"end")
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
def test_haramard():
|
| 339 |
+
A = MatrixSymbol('A', 3, 3)
|
| 340 |
+
B = MatrixSymbol('B', 3, 3)
|
| 341 |
+
v = MatrixSymbol('v', 3, 1)
|
| 342 |
+
h = MatrixSymbol('h', 1, 3)
|
| 343 |
+
C = HadamardProduct(A, B)
|
| 344 |
+
assert julia_code(C) == "A .* B"
|
| 345 |
+
assert julia_code(C*v) == "(A .* B) * v"
|
| 346 |
+
assert julia_code(h*C*v) == "h * (A .* B) * v"
|
| 347 |
+
assert julia_code(C*A) == "(A .* B) * A"
|
| 348 |
+
# mixing Hadamard and scalar strange b/c we vectorize scalars
|
| 349 |
+
assert julia_code(C*x*y) == "(x .* y) * (A .* B)"
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
def test_sparse():
|
| 353 |
+
M = SparseMatrix(5, 6, {})
|
| 354 |
+
M[2, 2] = 10;
|
| 355 |
+
M[1, 2] = 20;
|
| 356 |
+
M[1, 3] = 22;
|
| 357 |
+
M[0, 3] = 30;
|
| 358 |
+
M[3, 0] = x*y;
|
| 359 |
+
assert julia_code(M) == (
|
| 360 |
+
"sparse([4, 2, 3, 1, 2], [1, 3, 3, 4, 4], [x .* y, 20, 10, 30, 22], 5, 6)"
|
| 361 |
+
)
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
def test_specfun():
|
| 365 |
+
n = Symbol('n')
|
| 366 |
+
for f in [besselj, bessely, besseli, besselk]:
|
| 367 |
+
assert julia_code(f(n, x)) == f.__name__ + '(n, x)'
|
| 368 |
+
for f in [airyai, airyaiprime, airybi, airybiprime]:
|
| 369 |
+
assert julia_code(f(x)) == f.__name__ + '(x)'
|
| 370 |
+
assert julia_code(hankel1(n, x)) == 'hankelh1(n, x)'
|
| 371 |
+
assert julia_code(hankel2(n, x)) == 'hankelh2(n, x)'
|
| 372 |
+
assert julia_code(jn(n, x)) == 'sqrt(2) * sqrt(pi) * sqrt(1 ./ x) .* besselj(n + 1 // 2, x) / 2'
|
| 373 |
+
assert julia_code(yn(n, x)) == 'sqrt(2) * sqrt(pi) * sqrt(1 ./ x) .* bessely(n + 1 // 2, x) / 2'
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
def test_MatrixElement_printing():
|
| 377 |
+
# test cases for issue #11821
|
| 378 |
+
A = MatrixSymbol("A", 1, 3)
|
| 379 |
+
B = MatrixSymbol("B", 1, 3)
|
| 380 |
+
C = MatrixSymbol("C", 1, 3)
|
| 381 |
+
|
| 382 |
+
assert(julia_code(A[0, 0]) == "A[1,1]")
|
| 383 |
+
assert(julia_code(3 * A[0, 0]) == "3 * A[1,1]")
|
| 384 |
+
|
| 385 |
+
F = C[0, 0].subs(C, A - B)
|
| 386 |
+
assert(julia_code(F) == "(A - B)[1,1]")
|
lib/python3.12/site-packages/sympy/printing/tests/test_latex.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
lib/python3.12/site-packages/sympy/printing/tests/test_llvmjit.py
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.external import import_module
|
| 2 |
+
from sympy.testing.pytest import raises
|
| 3 |
+
import ctypes
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
if import_module('llvmlite'):
|
| 7 |
+
import sympy.printing.llvmjitcode as g
|
| 8 |
+
else:
|
| 9 |
+
disabled = True
|
| 10 |
+
|
| 11 |
+
import sympy
|
| 12 |
+
from sympy.abc import a, b, n
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# copied from numpy.isclose documentation
|
| 16 |
+
def isclose(a, b):
|
| 17 |
+
rtol = 1e-5
|
| 18 |
+
atol = 1e-8
|
| 19 |
+
return abs(a-b) <= atol + rtol*abs(b)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def test_simple_expr():
|
| 23 |
+
e = a + 1.0
|
| 24 |
+
f = g.llvm_callable([a], e)
|
| 25 |
+
res = float(e.subs({a: 4.0}).evalf())
|
| 26 |
+
jit_res = f(4.0)
|
| 27 |
+
|
| 28 |
+
assert isclose(jit_res, res)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def test_two_arg():
|
| 32 |
+
e = 4.0*a + b + 3.0
|
| 33 |
+
f = g.llvm_callable([a, b], e)
|
| 34 |
+
res = float(e.subs({a: 4.0, b: 3.0}).evalf())
|
| 35 |
+
jit_res = f(4.0, 3.0)
|
| 36 |
+
|
| 37 |
+
assert isclose(jit_res, res)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def test_func():
|
| 41 |
+
e = 4.0*sympy.exp(-a)
|
| 42 |
+
f = g.llvm_callable([a], e)
|
| 43 |
+
res = float(e.subs({a: 1.5}).evalf())
|
| 44 |
+
jit_res = f(1.5)
|
| 45 |
+
|
| 46 |
+
assert isclose(jit_res, res)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def test_two_func():
|
| 50 |
+
e = 4.0*sympy.exp(-a) + sympy.exp(b)
|
| 51 |
+
f = g.llvm_callable([a, b], e)
|
| 52 |
+
res = float(e.subs({a: 1.5, b: 2.0}).evalf())
|
| 53 |
+
jit_res = f(1.5, 2.0)
|
| 54 |
+
|
| 55 |
+
assert isclose(jit_res, res)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def test_two_sqrt():
|
| 59 |
+
e = 4.0*sympy.sqrt(a) + sympy.sqrt(b)
|
| 60 |
+
f = g.llvm_callable([a, b], e)
|
| 61 |
+
res = float(e.subs({a: 1.5, b: 2.0}).evalf())
|
| 62 |
+
jit_res = f(1.5, 2.0)
|
| 63 |
+
|
| 64 |
+
assert isclose(jit_res, res)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_two_pow():
|
| 68 |
+
e = a**1.5 + b**7
|
| 69 |
+
f = g.llvm_callable([a, b], e)
|
| 70 |
+
res = float(e.subs({a: 1.5, b: 2.0}).evalf())
|
| 71 |
+
jit_res = f(1.5, 2.0)
|
| 72 |
+
|
| 73 |
+
assert isclose(jit_res, res)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_callback():
|
| 77 |
+
e = a + 1.2
|
| 78 |
+
f = g.llvm_callable([a], e, callback_type='scipy.integrate.test')
|
| 79 |
+
m = ctypes.c_int(1)
|
| 80 |
+
array_type = ctypes.c_double * 1
|
| 81 |
+
inp = {a: 2.2}
|
| 82 |
+
array = array_type(inp[a])
|
| 83 |
+
jit_res = f(m, array)
|
| 84 |
+
|
| 85 |
+
res = float(e.subs(inp).evalf())
|
| 86 |
+
|
| 87 |
+
assert isclose(jit_res, res)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def test_callback_cubature():
|
| 91 |
+
e = a + 1.2
|
| 92 |
+
f = g.llvm_callable([a], e, callback_type='cubature')
|
| 93 |
+
m = ctypes.c_int(1)
|
| 94 |
+
array_type = ctypes.c_double * 1
|
| 95 |
+
inp = {a: 2.2}
|
| 96 |
+
array = array_type(inp[a])
|
| 97 |
+
out_array = array_type(0.0)
|
| 98 |
+
jit_ret = f(m, array, None, m, out_array)
|
| 99 |
+
|
| 100 |
+
assert jit_ret == 0
|
| 101 |
+
|
| 102 |
+
res = float(e.subs(inp).evalf())
|
| 103 |
+
|
| 104 |
+
assert isclose(out_array[0], res)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def test_callback_two():
|
| 108 |
+
e = 3*a*b
|
| 109 |
+
f = g.llvm_callable([a, b], e, callback_type='scipy.integrate.test')
|
| 110 |
+
m = ctypes.c_int(2)
|
| 111 |
+
array_type = ctypes.c_double * 2
|
| 112 |
+
inp = {a: 0.2, b: 1.7}
|
| 113 |
+
array = array_type(inp[a], inp[b])
|
| 114 |
+
jit_res = f(m, array)
|
| 115 |
+
|
| 116 |
+
res = float(e.subs(inp).evalf())
|
| 117 |
+
|
| 118 |
+
assert isclose(jit_res, res)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def test_callback_alt_two():
|
| 122 |
+
d = sympy.IndexedBase('d')
|
| 123 |
+
e = 3*d[0]*d[1]
|
| 124 |
+
f = g.llvm_callable([n, d], e, callback_type='scipy.integrate.test')
|
| 125 |
+
m = ctypes.c_int(2)
|
| 126 |
+
array_type = ctypes.c_double * 2
|
| 127 |
+
inp = {d[0]: 0.2, d[1]: 1.7}
|
| 128 |
+
array = array_type(inp[d[0]], inp[d[1]])
|
| 129 |
+
jit_res = f(m, array)
|
| 130 |
+
|
| 131 |
+
res = float(e.subs(inp).evalf())
|
| 132 |
+
|
| 133 |
+
assert isclose(jit_res, res)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def test_multiple_statements():
|
| 137 |
+
# Match return from CSE
|
| 138 |
+
e = [[(b, 4.0*a)], [b + 5]]
|
| 139 |
+
f = g.llvm_callable([a], e)
|
| 140 |
+
b_val = e[0][0][1].subs({a: 1.5})
|
| 141 |
+
res = float(e[1][0].subs({b: b_val}).evalf())
|
| 142 |
+
jit_res = f(1.5)
|
| 143 |
+
assert isclose(jit_res, res)
|
| 144 |
+
|
| 145 |
+
f_callback = g.llvm_callable([a], e, callback_type='scipy.integrate.test')
|
| 146 |
+
m = ctypes.c_int(1)
|
| 147 |
+
array_type = ctypes.c_double * 1
|
| 148 |
+
array = array_type(1.5)
|
| 149 |
+
jit_callback_res = f_callback(m, array)
|
| 150 |
+
assert isclose(jit_callback_res, res)
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def test_cse():
|
| 154 |
+
e = a*a + b*b + sympy.exp(-a*a - b*b)
|
| 155 |
+
e2 = sympy.cse(e)
|
| 156 |
+
f = g.llvm_callable([a, b], e2)
|
| 157 |
+
res = float(e.subs({a: 2.3, b: 0.1}).evalf())
|
| 158 |
+
jit_res = f(2.3, 0.1)
|
| 159 |
+
|
| 160 |
+
assert isclose(jit_res, res)
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def eval_cse(e, sub_dict):
|
| 164 |
+
tmp_dict = {}
|
| 165 |
+
for tmp_name, tmp_expr in e[0]:
|
| 166 |
+
e2 = tmp_expr.subs(sub_dict)
|
| 167 |
+
e3 = e2.subs(tmp_dict)
|
| 168 |
+
tmp_dict[tmp_name] = e3
|
| 169 |
+
return [e.subs(sub_dict).subs(tmp_dict) for e in e[1]]
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def test_cse_multiple():
|
| 173 |
+
e1 = a*a
|
| 174 |
+
e2 = a*a + b*b
|
| 175 |
+
e3 = sympy.cse([e1, e2])
|
| 176 |
+
|
| 177 |
+
raises(NotImplementedError,
|
| 178 |
+
lambda: g.llvm_callable([a, b], e3, callback_type='scipy.integrate'))
|
| 179 |
+
|
| 180 |
+
f = g.llvm_callable([a, b], e3)
|
| 181 |
+
jit_res = f(0.1, 1.5)
|
| 182 |
+
assert len(jit_res) == 2
|
| 183 |
+
res = eval_cse(e3, {a: 0.1, b: 1.5})
|
| 184 |
+
assert isclose(res[0], jit_res[0])
|
| 185 |
+
assert isclose(res[1], jit_res[1])
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def test_callback_cubature_multiple():
|
| 189 |
+
e1 = a*a
|
| 190 |
+
e2 = a*a + b*b
|
| 191 |
+
e3 = sympy.cse([e1, e2, 4*e2])
|
| 192 |
+
f = g.llvm_callable([a, b], e3, callback_type='cubature')
|
| 193 |
+
|
| 194 |
+
# Number of input variables
|
| 195 |
+
ndim = 2
|
| 196 |
+
# Number of output expression values
|
| 197 |
+
outdim = 3
|
| 198 |
+
|
| 199 |
+
m = ctypes.c_int(ndim)
|
| 200 |
+
fdim = ctypes.c_int(outdim)
|
| 201 |
+
array_type = ctypes.c_double * ndim
|
| 202 |
+
out_array_type = ctypes.c_double * outdim
|
| 203 |
+
inp = {a: 0.2, b: 1.5}
|
| 204 |
+
array = array_type(inp[a], inp[b])
|
| 205 |
+
out_array = out_array_type()
|
| 206 |
+
jit_ret = f(m, array, None, fdim, out_array)
|
| 207 |
+
|
| 208 |
+
assert jit_ret == 0
|
| 209 |
+
|
| 210 |
+
res = eval_cse(e3, inp)
|
| 211 |
+
|
| 212 |
+
assert isclose(out_array[0], res[0])
|
| 213 |
+
assert isclose(out_array[1], res[1])
|
| 214 |
+
assert isclose(out_array[2], res[2])
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
def test_symbol_not_found():
|
| 218 |
+
e = a*a + b
|
| 219 |
+
raises(LookupError, lambda: g.llvm_callable([a], e))
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def test_bad_callback():
|
| 223 |
+
e = a
|
| 224 |
+
raises(ValueError, lambda: g.llvm_callable([a], e, callback_type='bad_callback'))
|
lib/python3.12/site-packages/sympy/printing/tests/test_maple.py
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer,
|
| 2 |
+
Tuple, Symbol, Eq, Ne, Le, Lt, Gt, Ge)
|
| 3 |
+
from sympy.core import EulerGamma, GoldenRatio, Catalan, Lambda, Mul, Pow
|
| 4 |
+
from sympy.functions import Piecewise, sqrt, ceiling, exp, sin, cos, sinc, lucas
|
| 5 |
+
from sympy.testing.pytest import raises
|
| 6 |
+
from sympy.utilities.lambdify import implemented_function
|
| 7 |
+
from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity,
|
| 8 |
+
HadamardProduct, SparseMatrix)
|
| 9 |
+
from sympy.functions.special.bessel import besseli
|
| 10 |
+
|
| 11 |
+
from sympy.printing.maple import maple_code
|
| 12 |
+
|
| 13 |
+
x, y, z = symbols('x,y,z')
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_Integer():
|
| 17 |
+
assert maple_code(Integer(67)) == "67"
|
| 18 |
+
assert maple_code(Integer(-1)) == "-1"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_Rational():
|
| 22 |
+
assert maple_code(Rational(3, 7)) == "3/7"
|
| 23 |
+
assert maple_code(Rational(18, 9)) == "2"
|
| 24 |
+
assert maple_code(Rational(3, -7)) == "-3/7"
|
| 25 |
+
assert maple_code(Rational(-3, -7)) == "3/7"
|
| 26 |
+
assert maple_code(x + Rational(3, 7)) == "x + 3/7"
|
| 27 |
+
assert maple_code(Rational(3, 7) * x) == '(3/7)*x'
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def test_Relational():
|
| 31 |
+
assert maple_code(Eq(x, y)) == "x = y"
|
| 32 |
+
assert maple_code(Ne(x, y)) == "x <> y"
|
| 33 |
+
assert maple_code(Le(x, y)) == "x <= y"
|
| 34 |
+
assert maple_code(Lt(x, y)) == "x < y"
|
| 35 |
+
assert maple_code(Gt(x, y)) == "x > y"
|
| 36 |
+
assert maple_code(Ge(x, y)) == "x >= y"
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_Function():
|
| 40 |
+
assert maple_code(sin(x) ** cos(x)) == "sin(x)^cos(x)"
|
| 41 |
+
assert maple_code(abs(x)) == "abs(x)"
|
| 42 |
+
assert maple_code(ceiling(x)) == "ceil(x)"
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def test_Pow():
|
| 46 |
+
assert maple_code(x ** 3) == "x^3"
|
| 47 |
+
assert maple_code(x ** (y ** 3)) == "x^(y^3)"
|
| 48 |
+
|
| 49 |
+
assert maple_code((x ** 3) ** y) == "(x^3)^y"
|
| 50 |
+
assert maple_code(x ** Rational(2, 3)) == 'x^(2/3)'
|
| 51 |
+
|
| 52 |
+
g = implemented_function('g', Lambda(x, 2 * x))
|
| 53 |
+
assert maple_code(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == \
|
| 54 |
+
"(3.5*2*x)^(-x + y^x)/(x^2 + y)"
|
| 55 |
+
# For issue 14160
|
| 56 |
+
assert maple_code(Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False),
|
| 57 |
+
evaluate=False)) == '-2*x/(y*y)'
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_basic_ops():
|
| 61 |
+
assert maple_code(x * y) == "x*y"
|
| 62 |
+
assert maple_code(x + y) == "x + y"
|
| 63 |
+
assert maple_code(x - y) == "x - y"
|
| 64 |
+
assert maple_code(-x) == "-x"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_1_over_x_and_sqrt():
|
| 68 |
+
# 1.0 and 0.5 would do something different in regular StrPrinter,
|
| 69 |
+
# but these are exact in IEEE floating point so no different here.
|
| 70 |
+
assert maple_code(1 / x) == '1/x'
|
| 71 |
+
assert maple_code(x ** -1) == maple_code(x ** -1.0) == '1/x'
|
| 72 |
+
assert maple_code(1 / sqrt(x)) == '1/sqrt(x)'
|
| 73 |
+
assert maple_code(x ** -S.Half) == maple_code(x ** -0.5) == '1/sqrt(x)'
|
| 74 |
+
assert maple_code(sqrt(x)) == 'sqrt(x)'
|
| 75 |
+
assert maple_code(x ** S.Half) == maple_code(x ** 0.5) == 'sqrt(x)'
|
| 76 |
+
assert maple_code(1 / pi) == '1/Pi'
|
| 77 |
+
assert maple_code(pi ** -1) == maple_code(pi ** -1.0) == '1/Pi'
|
| 78 |
+
assert maple_code(pi ** -0.5) == '1/sqrt(Pi)'
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def test_mix_number_mult_symbols():
|
| 82 |
+
assert maple_code(3 * x) == "3*x"
|
| 83 |
+
assert maple_code(pi * x) == "Pi*x"
|
| 84 |
+
assert maple_code(3 / x) == "3/x"
|
| 85 |
+
assert maple_code(pi / x) == "Pi/x"
|
| 86 |
+
assert maple_code(x / 3) == '(1/3)*x'
|
| 87 |
+
assert maple_code(x / pi) == "x/Pi"
|
| 88 |
+
assert maple_code(x * y) == "x*y"
|
| 89 |
+
assert maple_code(3 * x * y) == "3*x*y"
|
| 90 |
+
assert maple_code(3 * pi * x * y) == "3*Pi*x*y"
|
| 91 |
+
assert maple_code(x / y) == "x/y"
|
| 92 |
+
assert maple_code(3 * x / y) == "3*x/y"
|
| 93 |
+
assert maple_code(x * y / z) == "x*y/z"
|
| 94 |
+
assert maple_code(x / y * z) == "x*z/y"
|
| 95 |
+
assert maple_code(1 / x / y) == "1/(x*y)"
|
| 96 |
+
assert maple_code(2 * pi * x / y / z) == "2*Pi*x/(y*z)"
|
| 97 |
+
assert maple_code(3 * pi / x) == "3*Pi/x"
|
| 98 |
+
assert maple_code(S(3) / 5) == "3/5"
|
| 99 |
+
assert maple_code(S(3) / 5 * x) == '(3/5)*x'
|
| 100 |
+
assert maple_code(x / y / z) == "x/(y*z)"
|
| 101 |
+
assert maple_code((x + y) / z) == "(x + y)/z"
|
| 102 |
+
assert maple_code((x + y) / (z + x)) == "(x + y)/(x + z)"
|
| 103 |
+
assert maple_code((x + y) / EulerGamma) == '(x + y)/gamma'
|
| 104 |
+
assert maple_code(x / 3 / pi) == '(1/3)*x/Pi'
|
| 105 |
+
assert maple_code(S(3) / 5 * x * y / pi) == '(3/5)*x*y/Pi'
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def test_mix_number_pow_symbols():
|
| 109 |
+
assert maple_code(pi ** 3) == 'Pi^3'
|
| 110 |
+
assert maple_code(x ** 2) == 'x^2'
|
| 111 |
+
|
| 112 |
+
assert maple_code(x ** (pi ** 3)) == 'x^(Pi^3)'
|
| 113 |
+
assert maple_code(x ** y) == 'x^y'
|
| 114 |
+
|
| 115 |
+
assert maple_code(x ** (y ** z)) == 'x^(y^z)'
|
| 116 |
+
assert maple_code((x ** y) ** z) == '(x^y)^z'
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def test_imag():
|
| 120 |
+
I = S('I')
|
| 121 |
+
assert maple_code(I) == "I"
|
| 122 |
+
assert maple_code(5 * I) == "5*I"
|
| 123 |
+
|
| 124 |
+
assert maple_code((S(3) / 2) * I) == "(3/2)*I"
|
| 125 |
+
assert maple_code(3 + 4 * I) == "3 + 4*I"
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def test_constants():
|
| 129 |
+
assert maple_code(pi) == "Pi"
|
| 130 |
+
assert maple_code(oo) == "infinity"
|
| 131 |
+
assert maple_code(-oo) == "-infinity"
|
| 132 |
+
assert maple_code(S.NegativeInfinity) == "-infinity"
|
| 133 |
+
assert maple_code(S.NaN) == "undefined"
|
| 134 |
+
assert maple_code(S.Exp1) == "exp(1)"
|
| 135 |
+
assert maple_code(exp(1)) == "exp(1)"
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def test_constants_other():
|
| 139 |
+
assert maple_code(2 * GoldenRatio) == '2*(1/2 + (1/2)*sqrt(5))'
|
| 140 |
+
assert maple_code(2 * Catalan) == '2*Catalan'
|
| 141 |
+
assert maple_code(2 * EulerGamma) == "2*gamma"
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def test_boolean():
|
| 145 |
+
assert maple_code(x & y) == "x and y"
|
| 146 |
+
assert maple_code(x | y) == "x or y"
|
| 147 |
+
assert maple_code(~x) == "not x"
|
| 148 |
+
assert maple_code(x & y & z) == "x and y and z"
|
| 149 |
+
assert maple_code(x | y | z) == "x or y or z"
|
| 150 |
+
assert maple_code((x & y) | z) == "z or x and y"
|
| 151 |
+
assert maple_code((x | y) & z) == "z and (x or y)"
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def test_Matrices():
|
| 155 |
+
assert maple_code(Matrix(1, 1, [10])) == \
|
| 156 |
+
'Matrix([[10]], storage = rectangular)'
|
| 157 |
+
|
| 158 |
+
A = Matrix([[1, sin(x / 2), abs(x)],
|
| 159 |
+
[0, 1, pi],
|
| 160 |
+
[0, exp(1), ceiling(x)]])
|
| 161 |
+
expected = \
|
| 162 |
+
'Matrix(' \
|
| 163 |
+
'[[1, sin((1/2)*x), abs(x)],' \
|
| 164 |
+
' [0, 1, Pi],' \
|
| 165 |
+
' [0, exp(1), ceil(x)]], ' \
|
| 166 |
+
'storage = rectangular)'
|
| 167 |
+
assert maple_code(A) == expected
|
| 168 |
+
|
| 169 |
+
# row and columns
|
| 170 |
+
assert maple_code(A[:, 0]) == \
|
| 171 |
+
'Matrix([[1], [0], [0]], storage = rectangular)'
|
| 172 |
+
assert maple_code(A[0, :]) == \
|
| 173 |
+
'Matrix([[1, sin((1/2)*x), abs(x)]], storage = rectangular)'
|
| 174 |
+
assert maple_code(Matrix([[x, x - y, -y]])) == \
|
| 175 |
+
'Matrix([[x, x - y, -y]], storage = rectangular)'
|
| 176 |
+
|
| 177 |
+
# empty matrices
|
| 178 |
+
assert maple_code(Matrix(0, 0, [])) == \
|
| 179 |
+
'Matrix([], storage = rectangular)'
|
| 180 |
+
assert maple_code(Matrix(0, 3, [])) == \
|
| 181 |
+
'Matrix([], storage = rectangular)'
|
| 182 |
+
|
| 183 |
+
def test_SparseMatrices():
|
| 184 |
+
assert maple_code(SparseMatrix(Identity(2))) == 'Matrix([[1, 0], [0, 1]], storage = sparse)'
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def test_vector_entries_hadamard():
|
| 188 |
+
# For a row or column, user might to use the other dimension
|
| 189 |
+
A = Matrix([[1, sin(2 / x), 3 * pi / x / 5]])
|
| 190 |
+
assert maple_code(A) == \
|
| 191 |
+
'Matrix([[1, sin(2/x), (3/5)*Pi/x]], storage = rectangular)'
|
| 192 |
+
assert maple_code(A.T) == \
|
| 193 |
+
'Matrix([[1], [sin(2/x)], [(3/5)*Pi/x]], storage = rectangular)'
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def test_Matrices_entries_not_hadamard():
|
| 197 |
+
A = Matrix([[1, sin(2 / x), 3 * pi / x / 5], [1, 2, x * y]])
|
| 198 |
+
expected = \
|
| 199 |
+
'Matrix([[1, sin(2/x), (3/5)*Pi/x], [1, 2, x*y]], ' \
|
| 200 |
+
'storage = rectangular)'
|
| 201 |
+
assert maple_code(A) == expected
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def test_MatrixSymbol():
|
| 205 |
+
n = Symbol('n', integer=True)
|
| 206 |
+
A = MatrixSymbol('A', n, n)
|
| 207 |
+
B = MatrixSymbol('B', n, n)
|
| 208 |
+
assert maple_code(A * B) == "A.B"
|
| 209 |
+
assert maple_code(B * A) == "B.A"
|
| 210 |
+
assert maple_code(2 * A * B) == "2*A.B"
|
| 211 |
+
assert maple_code(B * 2 * A) == "2*B.A"
|
| 212 |
+
|
| 213 |
+
assert maple_code(
|
| 214 |
+
A * (B + 3 * Identity(n))) == "A.(3*Matrix(n, shape = identity) + B)"
|
| 215 |
+
|
| 216 |
+
assert maple_code(A ** (x ** 2)) == "MatrixPower(A, x^2)"
|
| 217 |
+
assert maple_code(A ** 3) == "MatrixPower(A, 3)"
|
| 218 |
+
assert maple_code(A ** (S.Half)) == "MatrixPower(A, 1/2)"
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def test_special_matrices():
|
| 222 |
+
assert maple_code(6 * Identity(3)) == "6*Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], storage = sparse)"
|
| 223 |
+
assert maple_code(Identity(x)) == 'Matrix(x, shape = identity)'
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def test_containers():
|
| 227 |
+
assert maple_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \
|
| 228 |
+
"[1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]"
|
| 229 |
+
|
| 230 |
+
assert maple_code((1, 2, (3, 4))) == "[1, 2, [3, 4]]"
|
| 231 |
+
assert maple_code([1]) == "[1]"
|
| 232 |
+
assert maple_code((1,)) == "[1]"
|
| 233 |
+
assert maple_code(Tuple(*[1, 2, 3])) == "[1, 2, 3]"
|
| 234 |
+
assert maple_code((1, x * y, (3, x ** 2))) == "[1, x*y, [3, x^2]]"
|
| 235 |
+
# scalar, matrix, empty matrix and empty list
|
| 236 |
+
|
| 237 |
+
assert maple_code((1, eye(3), Matrix(0, 0, []), [])) == \
|
| 238 |
+
"[1, Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], storage = rectangular), Matrix([], storage = rectangular), []]"
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def test_maple_noninline():
|
| 242 |
+
source = maple_code((x + y)/Catalan, assign_to='me', inline=False)
|
| 243 |
+
expected = "me := (x + y)/Catalan"
|
| 244 |
+
|
| 245 |
+
assert source == expected
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def test_maple_matrix_assign_to():
|
| 249 |
+
A = Matrix([[1, 2, 3]])
|
| 250 |
+
assert maple_code(A, assign_to='a') == "a := Matrix([[1, 2, 3]], storage = rectangular)"
|
| 251 |
+
A = Matrix([[1, 2], [3, 4]])
|
| 252 |
+
assert maple_code(A, assign_to='A') == "A := Matrix([[1, 2], [3, 4]], storage = rectangular)"
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def test_maple_matrix_assign_to_more():
|
| 256 |
+
# assigning to Symbol or MatrixSymbol requires lhs/rhs match
|
| 257 |
+
A = Matrix([[1, 2, 3]])
|
| 258 |
+
B = MatrixSymbol('B', 1, 3)
|
| 259 |
+
C = MatrixSymbol('C', 2, 3)
|
| 260 |
+
assert maple_code(A, assign_to=B) == "B := Matrix([[1, 2, 3]], storage = rectangular)"
|
| 261 |
+
raises(ValueError, lambda: maple_code(A, assign_to=x))
|
| 262 |
+
raises(ValueError, lambda: maple_code(A, assign_to=C))
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def test_maple_matrix_1x1():
|
| 266 |
+
A = Matrix([[3]])
|
| 267 |
+
assert maple_code(A, assign_to='B') == "B := Matrix([[3]], storage = rectangular)"
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def test_maple_matrix_elements():
|
| 271 |
+
A = Matrix([[x, 2, x * y]])
|
| 272 |
+
|
| 273 |
+
assert maple_code(A[0, 0] ** 2 + A[0, 1] + A[0, 2]) == "x^2 + x*y + 2"
|
| 274 |
+
AA = MatrixSymbol('AA', 1, 3)
|
| 275 |
+
assert maple_code(AA) == "AA"
|
| 276 |
+
|
| 277 |
+
assert maple_code(AA[0, 0] ** 2 + sin(AA[0, 1]) + AA[0, 2]) == \
|
| 278 |
+
"sin(AA[1, 2]) + AA[1, 1]^2 + AA[1, 3]"
|
| 279 |
+
assert maple_code(sum(AA)) == "AA[1, 1] + AA[1, 2] + AA[1, 3]"
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def test_maple_boolean():
|
| 283 |
+
assert maple_code(True) == "true"
|
| 284 |
+
assert maple_code(S.true) == "true"
|
| 285 |
+
assert maple_code(False) == "false"
|
| 286 |
+
assert maple_code(S.false) == "false"
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
def test_sparse():
|
| 290 |
+
M = SparseMatrix(5, 6, {})
|
| 291 |
+
M[2, 2] = 10
|
| 292 |
+
M[1, 2] = 20
|
| 293 |
+
M[1, 3] = 22
|
| 294 |
+
M[0, 3] = 30
|
| 295 |
+
M[3, 0] = x * y
|
| 296 |
+
assert maple_code(M) == \
|
| 297 |
+
'Matrix([[0, 0, 0, 30, 0, 0],' \
|
| 298 |
+
' [0, 0, 20, 22, 0, 0],' \
|
| 299 |
+
' [0, 0, 10, 0, 0, 0],' \
|
| 300 |
+
' [x*y, 0, 0, 0, 0, 0],' \
|
| 301 |
+
' [0, 0, 0, 0, 0, 0]], ' \
|
| 302 |
+
'storage = sparse)'
|
| 303 |
+
|
| 304 |
+
# Not an important point.
|
| 305 |
+
def test_maple_not_supported():
|
| 306 |
+
with raises(NotImplementedError):
|
| 307 |
+
maple_code(S.ComplexInfinity)
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
def test_MatrixElement_printing():
|
| 311 |
+
# test cases for issue #11821
|
| 312 |
+
A = MatrixSymbol("A", 1, 3)
|
| 313 |
+
B = MatrixSymbol("B", 1, 3)
|
| 314 |
+
|
| 315 |
+
assert (maple_code(A[0, 0]) == "A[1, 1]")
|
| 316 |
+
assert (maple_code(3 * A[0, 0]) == "3*A[1, 1]")
|
| 317 |
+
|
| 318 |
+
F = A-B
|
| 319 |
+
|
| 320 |
+
assert (maple_code(F[0,0]) == "A[1, 1] - B[1, 1]")
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def test_hadamard():
|
| 324 |
+
A = MatrixSymbol('A', 3, 3)
|
| 325 |
+
B = MatrixSymbol('B', 3, 3)
|
| 326 |
+
v = MatrixSymbol('v', 3, 1)
|
| 327 |
+
h = MatrixSymbol('h', 1, 3)
|
| 328 |
+
C = HadamardProduct(A, B)
|
| 329 |
+
assert maple_code(C) == "A*B"
|
| 330 |
+
|
| 331 |
+
assert maple_code(C * v) == "(A*B).v"
|
| 332 |
+
# HadamardProduct is higher than dot product.
|
| 333 |
+
|
| 334 |
+
assert maple_code(h * C * v) == "h.(A*B).v"
|
| 335 |
+
|
| 336 |
+
assert maple_code(C * A) == "(A*B).A"
|
| 337 |
+
# mixing Hadamard and scalar strange b/c we vectorize scalars
|
| 338 |
+
|
| 339 |
+
assert maple_code(C * x * y) == "x*y*(A*B)"
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
def test_maple_piecewise():
|
| 343 |
+
expr = Piecewise((x, x < 1), (x ** 2, True))
|
| 344 |
+
|
| 345 |
+
assert maple_code(expr) == "piecewise(x < 1, x, x^2)"
|
| 346 |
+
assert maple_code(expr, assign_to="r") == (
|
| 347 |
+
"r := piecewise(x < 1, x, x^2)")
|
| 348 |
+
|
| 349 |
+
expr = Piecewise((x ** 2, x < 1), (x ** 3, x < 2), (x ** 4, x < 3), (x ** 5, True))
|
| 350 |
+
expected = "piecewise(x < 1, x^2, x < 2, x^3, x < 3, x^4, x^5)"
|
| 351 |
+
assert maple_code(expr) == expected
|
| 352 |
+
assert maple_code(expr, assign_to="r") == "r := " + expected
|
| 353 |
+
|
| 354 |
+
# Check that Piecewise without a True (default) condition error
|
| 355 |
+
expr = Piecewise((x, x < 1), (x ** 2, x > 1), (sin(x), x > 0))
|
| 356 |
+
raises(ValueError, lambda: maple_code(expr))
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
def test_maple_piecewise_times_const():
|
| 360 |
+
pw = Piecewise((x, x < 1), (x ** 2, True))
|
| 361 |
+
|
| 362 |
+
assert maple_code(2 * pw) == "2*piecewise(x < 1, x, x^2)"
|
| 363 |
+
assert maple_code(pw / x) == "piecewise(x < 1, x, x^2)/x"
|
| 364 |
+
assert maple_code(pw / (x * y)) == "piecewise(x < 1, x, x^2)/(x*y)"
|
| 365 |
+
assert maple_code(pw / 3) == "(1/3)*piecewise(x < 1, x, x^2)"
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
def test_maple_derivatives():
|
| 369 |
+
f = Function('f')
|
| 370 |
+
assert maple_code(f(x).diff(x)) == 'diff(f(x), x)'
|
| 371 |
+
assert maple_code(f(x).diff(x, 2)) == 'diff(f(x), x$2)'
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def test_automatic_rewrites():
|
| 375 |
+
assert maple_code(lucas(x)) == '(2^(-x)*((1 - sqrt(5))^x + (1 + sqrt(5))^x))'
|
| 376 |
+
assert maple_code(sinc(x)) == '(piecewise(x <> 0, sin(x)/x, 1))'
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
def test_specfun():
|
| 380 |
+
assert maple_code('asin(x)') == 'arcsin(x)'
|
| 381 |
+
assert maple_code(besseli(x, y)) == 'BesselI(x, y)'
|
lib/python3.12/site-packages/sympy/printing/tests/test_mathematica.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer, Tuple,
|
| 2 |
+
Derivative, Eq, Ne, Le, Lt, Gt, Ge)
|
| 3 |
+
from sympy.integrals import Integral
|
| 4 |
+
from sympy.concrete import Sum
|
| 5 |
+
from sympy.functions import (exp, sin, cos, fresnelc, fresnels, conjugate, Max,
|
| 6 |
+
Min, gamma, polygamma, loggamma, erf, erfi, erfc,
|
| 7 |
+
erf2, expint, erfinv, erfcinv, Ei, Si, Ci, li,
|
| 8 |
+
Shi, Chi, uppergamma, beta, subfactorial, erf2inv,
|
| 9 |
+
factorial, factorial2, catalan, RisingFactorial,
|
| 10 |
+
FallingFactorial, harmonic, atan2, sec, acsc,
|
| 11 |
+
hermite, laguerre, assoc_laguerre, jacobi,
|
| 12 |
+
gegenbauer, chebyshevt, chebyshevu, legendre,
|
| 13 |
+
assoc_legendre, Li, LambertW)
|
| 14 |
+
|
| 15 |
+
from sympy.printing.mathematica import mathematica_code as mcode
|
| 16 |
+
|
| 17 |
+
x, y, z, w = symbols('x,y,z,w')
|
| 18 |
+
f = Function('f')
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_Integer():
|
| 22 |
+
assert mcode(Integer(67)) == "67"
|
| 23 |
+
assert mcode(Integer(-1)) == "-1"
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def test_Rational():
|
| 27 |
+
assert mcode(Rational(3, 7)) == "3/7"
|
| 28 |
+
assert mcode(Rational(18, 9)) == "2"
|
| 29 |
+
assert mcode(Rational(3, -7)) == "-3/7"
|
| 30 |
+
assert mcode(Rational(-3, -7)) == "3/7"
|
| 31 |
+
assert mcode(x + Rational(3, 7)) == "x + 3/7"
|
| 32 |
+
assert mcode(Rational(3, 7)*x) == "(3/7)*x"
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def test_Relational():
|
| 36 |
+
assert mcode(Eq(x, y)) == "x == y"
|
| 37 |
+
assert mcode(Ne(x, y)) == "x != y"
|
| 38 |
+
assert mcode(Le(x, y)) == "x <= y"
|
| 39 |
+
assert mcode(Lt(x, y)) == "x < y"
|
| 40 |
+
assert mcode(Gt(x, y)) == "x > y"
|
| 41 |
+
assert mcode(Ge(x, y)) == "x >= y"
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def test_Function():
|
| 45 |
+
assert mcode(f(x, y, z)) == "f[x, y, z]"
|
| 46 |
+
assert mcode(sin(x) ** cos(x)) == "Sin[x]^Cos[x]"
|
| 47 |
+
assert mcode(sec(x) * acsc(x)) == "ArcCsc[x]*Sec[x]"
|
| 48 |
+
assert mcode(atan2(x, y)) == "ArcTan[x, y]"
|
| 49 |
+
assert mcode(conjugate(x)) == "Conjugate[x]"
|
| 50 |
+
assert mcode(Max(x, y, z)*Min(y, z)) == "Max[x, y, z]*Min[y, z]"
|
| 51 |
+
assert mcode(fresnelc(x)) == "FresnelC[x]"
|
| 52 |
+
assert mcode(fresnels(x)) == "FresnelS[x]"
|
| 53 |
+
assert mcode(gamma(x)) == "Gamma[x]"
|
| 54 |
+
assert mcode(uppergamma(x, y)) == "Gamma[x, y]"
|
| 55 |
+
assert mcode(polygamma(x, y)) == "PolyGamma[x, y]"
|
| 56 |
+
assert mcode(loggamma(x)) == "LogGamma[x]"
|
| 57 |
+
assert mcode(erf(x)) == "Erf[x]"
|
| 58 |
+
assert mcode(erfc(x)) == "Erfc[x]"
|
| 59 |
+
assert mcode(erfi(x)) == "Erfi[x]"
|
| 60 |
+
assert mcode(erf2(x, y)) == "Erf[x, y]"
|
| 61 |
+
assert mcode(expint(x, y)) == "ExpIntegralE[x, y]"
|
| 62 |
+
assert mcode(erfcinv(x)) == "InverseErfc[x]"
|
| 63 |
+
assert mcode(erfinv(x)) == "InverseErf[x]"
|
| 64 |
+
assert mcode(erf2inv(x, y)) == "InverseErf[x, y]"
|
| 65 |
+
assert mcode(Ei(x)) == "ExpIntegralEi[x]"
|
| 66 |
+
assert mcode(Ci(x)) == "CosIntegral[x]"
|
| 67 |
+
assert mcode(li(x)) == "LogIntegral[x]"
|
| 68 |
+
assert mcode(Si(x)) == "SinIntegral[x]"
|
| 69 |
+
assert mcode(Shi(x)) == "SinhIntegral[x]"
|
| 70 |
+
assert mcode(Chi(x)) == "CoshIntegral[x]"
|
| 71 |
+
assert mcode(beta(x, y)) == "Beta[x, y]"
|
| 72 |
+
assert mcode(factorial(x)) == "Factorial[x]"
|
| 73 |
+
assert mcode(factorial2(x)) == "Factorial2[x]"
|
| 74 |
+
assert mcode(subfactorial(x)) == "Subfactorial[x]"
|
| 75 |
+
assert mcode(FallingFactorial(x, y)) == "FactorialPower[x, y]"
|
| 76 |
+
assert mcode(RisingFactorial(x, y)) == "Pochhammer[x, y]"
|
| 77 |
+
assert mcode(catalan(x)) == "CatalanNumber[x]"
|
| 78 |
+
assert mcode(harmonic(x)) == "HarmonicNumber[x]"
|
| 79 |
+
assert mcode(harmonic(x, y)) == "HarmonicNumber[x, y]"
|
| 80 |
+
assert mcode(Li(x)) == "LogIntegral[x] - LogIntegral[2]"
|
| 81 |
+
assert mcode(LambertW(x)) == "ProductLog[x]"
|
| 82 |
+
assert mcode(LambertW(x, -1)) == "ProductLog[-1, x]"
|
| 83 |
+
assert mcode(LambertW(x, y)) == "ProductLog[y, x]"
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def test_special_polynomials():
|
| 87 |
+
assert mcode(hermite(x, y)) == "HermiteH[x, y]"
|
| 88 |
+
assert mcode(laguerre(x, y)) == "LaguerreL[x, y]"
|
| 89 |
+
assert mcode(assoc_laguerre(x, y, z)) == "LaguerreL[x, y, z]"
|
| 90 |
+
assert mcode(jacobi(x, y, z, w)) == "JacobiP[x, y, z, w]"
|
| 91 |
+
assert mcode(gegenbauer(x, y, z)) == "GegenbauerC[x, y, z]"
|
| 92 |
+
assert mcode(chebyshevt(x, y)) == "ChebyshevT[x, y]"
|
| 93 |
+
assert mcode(chebyshevu(x, y)) == "ChebyshevU[x, y]"
|
| 94 |
+
assert mcode(legendre(x, y)) == "LegendreP[x, y]"
|
| 95 |
+
assert mcode(assoc_legendre(x, y, z)) == "LegendreP[x, y, z]"
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def test_Pow():
|
| 99 |
+
assert mcode(x**3) == "x^3"
|
| 100 |
+
assert mcode(x**(y**3)) == "x^(y^3)"
|
| 101 |
+
assert mcode(1/(f(x)*3.5)**(x - y**x)/(x**2 + y)) == \
|
| 102 |
+
"(3.5*f[x])^(-x + y^x)/(x^2 + y)"
|
| 103 |
+
assert mcode(x**-1.0) == 'x^(-1.0)'
|
| 104 |
+
assert mcode(x**Rational(2, 3)) == 'x^(2/3)'
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def test_Mul():
|
| 108 |
+
A, B, C, D = symbols('A B C D', commutative=False)
|
| 109 |
+
assert mcode(x*y*z) == "x*y*z"
|
| 110 |
+
assert mcode(x*y*A) == "x*y*A"
|
| 111 |
+
assert mcode(x*y*A*B) == "x*y*A**B"
|
| 112 |
+
assert mcode(x*y*A*B*C) == "x*y*A**B**C"
|
| 113 |
+
assert mcode(x*A*B*(C + D)*A*y) == "x*y*A**B**(C + D)**A"
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def test_constants():
|
| 117 |
+
assert mcode(S.Zero) == "0"
|
| 118 |
+
assert mcode(S.One) == "1"
|
| 119 |
+
assert mcode(S.NegativeOne) == "-1"
|
| 120 |
+
assert mcode(S.Half) == "1/2"
|
| 121 |
+
assert mcode(S.ImaginaryUnit) == "I"
|
| 122 |
+
|
| 123 |
+
assert mcode(oo) == "Infinity"
|
| 124 |
+
assert mcode(S.NegativeInfinity) == "-Infinity"
|
| 125 |
+
assert mcode(S.ComplexInfinity) == "ComplexInfinity"
|
| 126 |
+
assert mcode(S.NaN) == "Indeterminate"
|
| 127 |
+
|
| 128 |
+
assert mcode(S.Exp1) == "E"
|
| 129 |
+
assert mcode(pi) == "Pi"
|
| 130 |
+
assert mcode(S.GoldenRatio) == "GoldenRatio"
|
| 131 |
+
assert mcode(S.TribonacciConstant) == \
|
| 132 |
+
"(1/3 + (1/3)*(19 - 3*33^(1/2))^(1/3) + " \
|
| 133 |
+
"(1/3)*(3*33^(1/2) + 19)^(1/3))"
|
| 134 |
+
assert mcode(2*S.TribonacciConstant) == \
|
| 135 |
+
"2*(1/3 + (1/3)*(19 - 3*33^(1/2))^(1/3) + " \
|
| 136 |
+
"(1/3)*(3*33^(1/2) + 19)^(1/3))"
|
| 137 |
+
assert mcode(S.EulerGamma) == "EulerGamma"
|
| 138 |
+
assert mcode(S.Catalan) == "Catalan"
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_containers():
|
| 142 |
+
assert mcode([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \
|
| 143 |
+
"{1, 2, 3, {4, 5, {6, 7}}, 8, {9, 10}, 11}"
|
| 144 |
+
assert mcode((1, 2, (3, 4))) == "{1, 2, {3, 4}}"
|
| 145 |
+
assert mcode([1]) == "{1}"
|
| 146 |
+
assert mcode((1,)) == "{1}"
|
| 147 |
+
assert mcode(Tuple(*[1, 2, 3])) == "{1, 2, 3}"
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test_matrices():
|
| 151 |
+
from sympy.matrices import MutableDenseMatrix, MutableSparseMatrix, \
|
| 152 |
+
ImmutableDenseMatrix, ImmutableSparseMatrix
|
| 153 |
+
A = MutableDenseMatrix(
|
| 154 |
+
[[1, -1, 0, 0],
|
| 155 |
+
[0, 1, -1, 0],
|
| 156 |
+
[0, 0, 1, -1],
|
| 157 |
+
[0, 0, 0, 1]]
|
| 158 |
+
)
|
| 159 |
+
B = MutableSparseMatrix(A)
|
| 160 |
+
C = ImmutableDenseMatrix(A)
|
| 161 |
+
D = ImmutableSparseMatrix(A)
|
| 162 |
+
|
| 163 |
+
assert mcode(C) == mcode(A) == \
|
| 164 |
+
"{{1, -1, 0, 0}, " \
|
| 165 |
+
"{0, 1, -1, 0}, " \
|
| 166 |
+
"{0, 0, 1, -1}, " \
|
| 167 |
+
"{0, 0, 0, 1}}"
|
| 168 |
+
|
| 169 |
+
assert mcode(D) == mcode(B) == \
|
| 170 |
+
"SparseArray[{" \
|
| 171 |
+
"{1, 1} -> 1, {1, 2} -> -1, {2, 2} -> 1, {2, 3} -> -1, " \
|
| 172 |
+
"{3, 3} -> 1, {3, 4} -> -1, {4, 4} -> 1" \
|
| 173 |
+
"}, {4, 4}]"
|
| 174 |
+
|
| 175 |
+
# Trivial cases of matrices
|
| 176 |
+
assert mcode(MutableDenseMatrix(0, 0, [])) == '{}'
|
| 177 |
+
assert mcode(MutableSparseMatrix(0, 0, [])) == 'SparseArray[{}, {0, 0}]'
|
| 178 |
+
assert mcode(MutableDenseMatrix(0, 3, [])) == '{}'
|
| 179 |
+
assert mcode(MutableSparseMatrix(0, 3, [])) == 'SparseArray[{}, {0, 3}]'
|
| 180 |
+
assert mcode(MutableDenseMatrix(3, 0, [])) == '{{}, {}, {}}'
|
| 181 |
+
assert mcode(MutableSparseMatrix(3, 0, [])) == 'SparseArray[{}, {3, 0}]'
|
| 182 |
+
|
| 183 |
+
def test_NDArray():
|
| 184 |
+
from sympy.tensor.array import (
|
| 185 |
+
MutableDenseNDimArray, ImmutableDenseNDimArray,
|
| 186 |
+
MutableSparseNDimArray, ImmutableSparseNDimArray)
|
| 187 |
+
|
| 188 |
+
example = MutableDenseNDimArray(
|
| 189 |
+
[[[1, 2, 3, 4],
|
| 190 |
+
[5, 6, 7, 8],
|
| 191 |
+
[9, 10, 11, 12]],
|
| 192 |
+
[[13, 14, 15, 16],
|
| 193 |
+
[17, 18, 19, 20],
|
| 194 |
+
[21, 22, 23, 24]]]
|
| 195 |
+
)
|
| 196 |
+
|
| 197 |
+
assert mcode(example) == \
|
| 198 |
+
"{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " \
|
| 199 |
+
"{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}"
|
| 200 |
+
|
| 201 |
+
example = ImmutableDenseNDimArray(example)
|
| 202 |
+
|
| 203 |
+
assert mcode(example) == \
|
| 204 |
+
"{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " \
|
| 205 |
+
"{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}"
|
| 206 |
+
|
| 207 |
+
example = MutableSparseNDimArray(example)
|
| 208 |
+
|
| 209 |
+
assert mcode(example) == \
|
| 210 |
+
"SparseArray[{" \
|
| 211 |
+
"{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " \
|
| 212 |
+
"{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " \
|
| 213 |
+
"{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " \
|
| 214 |
+
"{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " \
|
| 215 |
+
"{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " \
|
| 216 |
+
"{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " \
|
| 217 |
+
"{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " \
|
| 218 |
+
"{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" \
|
| 219 |
+
"}, {2, 3, 4}]"
|
| 220 |
+
|
| 221 |
+
example = ImmutableSparseNDimArray(example)
|
| 222 |
+
|
| 223 |
+
assert mcode(example) == \
|
| 224 |
+
"SparseArray[{" \
|
| 225 |
+
"{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " \
|
| 226 |
+
"{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " \
|
| 227 |
+
"{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " \
|
| 228 |
+
"{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " \
|
| 229 |
+
"{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " \
|
| 230 |
+
"{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " \
|
| 231 |
+
"{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " \
|
| 232 |
+
"{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" \
|
| 233 |
+
"}, {2, 3, 4}]"
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def test_Integral():
|
| 237 |
+
assert mcode(Integral(sin(sin(x)), x)) == "Hold[Integrate[Sin[Sin[x]], x]]"
|
| 238 |
+
assert mcode(Integral(exp(-x**2 - y**2),
|
| 239 |
+
(x, -oo, oo),
|
| 240 |
+
(y, -oo, oo))) == \
|
| 241 |
+
"Hold[Integrate[Exp[-x^2 - y^2], {x, -Infinity, Infinity}, " \
|
| 242 |
+
"{y, -Infinity, Infinity}]]"
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
def test_Derivative():
|
| 246 |
+
assert mcode(Derivative(sin(x), x)) == "Hold[D[Sin[x], x]]"
|
| 247 |
+
assert mcode(Derivative(x, x)) == "Hold[D[x, x]]"
|
| 248 |
+
assert mcode(Derivative(sin(x)*y**4, x, 2)) == "Hold[D[y^4*Sin[x], {x, 2}]]"
|
| 249 |
+
assert mcode(Derivative(sin(x)*y**4, x, y, x)) == "Hold[D[y^4*Sin[x], x, y, x]]"
|
| 250 |
+
assert mcode(Derivative(sin(x)*y**4, x, y, 3, x)) == "Hold[D[y^4*Sin[x], x, {y, 3}, x]]"
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def test_Sum():
|
| 254 |
+
assert mcode(Sum(sin(x), (x, 0, 10))) == "Hold[Sum[Sin[x], {x, 0, 10}]]"
|
| 255 |
+
assert mcode(Sum(exp(-x**2 - y**2),
|
| 256 |
+
(x, -oo, oo),
|
| 257 |
+
(y, -oo, oo))) == \
|
| 258 |
+
"Hold[Sum[Exp[-x^2 - y^2], {x, -Infinity, Infinity}, " \
|
| 259 |
+
"{y, -Infinity, Infinity}]]"
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def test_comment():
|
| 263 |
+
from sympy.printing.mathematica import MCodePrinter
|
| 264 |
+
assert MCodePrinter()._get_comment("Hello World") == \
|
| 265 |
+
"(* Hello World *)"
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
def test_userfuncs():
|
| 269 |
+
# Dictionary mutation test
|
| 270 |
+
some_function = symbols("some_function", cls=Function)
|
| 271 |
+
my_user_functions = {"some_function": "SomeFunction"}
|
| 272 |
+
assert mcode(
|
| 273 |
+
some_function(z),
|
| 274 |
+
user_functions=my_user_functions) == \
|
| 275 |
+
'SomeFunction[z]'
|
| 276 |
+
assert mcode(
|
| 277 |
+
some_function(z),
|
| 278 |
+
user_functions=my_user_functions) == \
|
| 279 |
+
'SomeFunction[z]'
|
| 280 |
+
|
| 281 |
+
# List argument test
|
| 282 |
+
my_user_functions = \
|
| 283 |
+
{"some_function": [(lambda x: True, "SomeOtherFunction")]}
|
| 284 |
+
assert mcode(
|
| 285 |
+
some_function(z),
|
| 286 |
+
user_functions=my_user_functions) == \
|
| 287 |
+
'SomeOtherFunction[z]'
|
lib/python3.12/site-packages/sympy/printing/tests/test_octave.py
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer,
|
| 2 |
+
Tuple, Symbol, EulerGamma, GoldenRatio, Catalan,
|
| 3 |
+
Lambda, Mul, Pow, Mod, Eq, Ne, Le, Lt, Gt, Ge)
|
| 4 |
+
from sympy.codegen.matrix_nodes import MatrixSolve
|
| 5 |
+
from sympy.functions import (arg, atan2, bernoulli, beta, ceiling, chebyshevu,
|
| 6 |
+
chebyshevt, conjugate, DiracDelta, exp, expint,
|
| 7 |
+
factorial, floor, harmonic, Heaviside, im,
|
| 8 |
+
laguerre, LambertW, log, Max, Min, Piecewise,
|
| 9 |
+
polylog, re, RisingFactorial, sign, sinc, sqrt,
|
| 10 |
+
zeta, binomial, legendre, dirichlet_eta,
|
| 11 |
+
riemann_xi)
|
| 12 |
+
from sympy.functions import (sin, cos, tan, cot, sec, csc, asin, acos, acot,
|
| 13 |
+
atan, asec, acsc, sinh, cosh, tanh, coth, csch,
|
| 14 |
+
sech, asinh, acosh, atanh, acoth, asech, acsch)
|
| 15 |
+
from sympy.testing.pytest import raises, XFAIL
|
| 16 |
+
from sympy.utilities.lambdify import implemented_function
|
| 17 |
+
from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity,
|
| 18 |
+
HadamardProduct, SparseMatrix, HadamardPower)
|
| 19 |
+
from sympy.functions.special.bessel import (jn, yn, besselj, bessely, besseli,
|
| 20 |
+
besselk, hankel1, hankel2, airyai,
|
| 21 |
+
airybi, airyaiprime, airybiprime)
|
| 22 |
+
from sympy.functions.special.gamma_functions import (gamma, lowergamma,
|
| 23 |
+
uppergamma, loggamma,
|
| 24 |
+
polygamma)
|
| 25 |
+
from sympy.functions.special.error_functions import (Chi, Ci, erf, erfc, erfi,
|
| 26 |
+
erfcinv, erfinv, fresnelc,
|
| 27 |
+
fresnels, li, Shi, Si, Li,
|
| 28 |
+
erf2, Ei)
|
| 29 |
+
from sympy.printing.octave import octave_code, octave_code as mcode
|
| 30 |
+
|
| 31 |
+
x, y, z = symbols('x,y,z')
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def test_Integer():
|
| 35 |
+
assert mcode(Integer(67)) == "67"
|
| 36 |
+
assert mcode(Integer(-1)) == "-1"
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_Rational():
|
| 40 |
+
assert mcode(Rational(3, 7)) == "3/7"
|
| 41 |
+
assert mcode(Rational(18, 9)) == "2"
|
| 42 |
+
assert mcode(Rational(3, -7)) == "-3/7"
|
| 43 |
+
assert mcode(Rational(-3, -7)) == "3/7"
|
| 44 |
+
assert mcode(x + Rational(3, 7)) == "x + 3/7"
|
| 45 |
+
assert mcode(Rational(3, 7)*x) == "3*x/7"
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_Relational():
|
| 49 |
+
assert mcode(Eq(x, y)) == "x == y"
|
| 50 |
+
assert mcode(Ne(x, y)) == "x != y"
|
| 51 |
+
assert mcode(Le(x, y)) == "x <= y"
|
| 52 |
+
assert mcode(Lt(x, y)) == "x < y"
|
| 53 |
+
assert mcode(Gt(x, y)) == "x > y"
|
| 54 |
+
assert mcode(Ge(x, y)) == "x >= y"
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def test_Function():
|
| 58 |
+
assert mcode(sin(x) ** cos(x)) == "sin(x).^cos(x)"
|
| 59 |
+
assert mcode(sign(x)) == "sign(x)"
|
| 60 |
+
assert mcode(exp(x)) == "exp(x)"
|
| 61 |
+
assert mcode(log(x)) == "log(x)"
|
| 62 |
+
assert mcode(factorial(x)) == "factorial(x)"
|
| 63 |
+
assert mcode(floor(x)) == "floor(x)"
|
| 64 |
+
assert mcode(atan2(y, x)) == "atan2(y, x)"
|
| 65 |
+
assert mcode(beta(x, y)) == 'beta(x, y)'
|
| 66 |
+
assert mcode(polylog(x, y)) == 'polylog(x, y)'
|
| 67 |
+
assert mcode(harmonic(x)) == 'harmonic(x)'
|
| 68 |
+
assert mcode(bernoulli(x)) == "bernoulli(x)"
|
| 69 |
+
assert mcode(bernoulli(x, y)) == "bernoulli(x, y)"
|
| 70 |
+
assert mcode(legendre(x, y)) == "legendre(x, y)"
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def test_Function_change_name():
|
| 74 |
+
assert mcode(abs(x)) == "abs(x)"
|
| 75 |
+
assert mcode(ceiling(x)) == "ceil(x)"
|
| 76 |
+
assert mcode(arg(x)) == "angle(x)"
|
| 77 |
+
assert mcode(im(x)) == "imag(x)"
|
| 78 |
+
assert mcode(re(x)) == "real(x)"
|
| 79 |
+
assert mcode(conjugate(x)) == "conj(x)"
|
| 80 |
+
assert mcode(chebyshevt(y, x)) == "chebyshevT(y, x)"
|
| 81 |
+
assert mcode(chebyshevu(y, x)) == "chebyshevU(y, x)"
|
| 82 |
+
assert mcode(laguerre(x, y)) == "laguerreL(x, y)"
|
| 83 |
+
assert mcode(Chi(x)) == "coshint(x)"
|
| 84 |
+
assert mcode(Shi(x)) == "sinhint(x)"
|
| 85 |
+
assert mcode(Ci(x)) == "cosint(x)"
|
| 86 |
+
assert mcode(Si(x)) == "sinint(x)"
|
| 87 |
+
assert mcode(li(x)) == "logint(x)"
|
| 88 |
+
assert mcode(loggamma(x)) == "gammaln(x)"
|
| 89 |
+
assert mcode(polygamma(x, y)) == "psi(x, y)"
|
| 90 |
+
assert mcode(RisingFactorial(x, y)) == "pochhammer(x, y)"
|
| 91 |
+
assert mcode(DiracDelta(x)) == "dirac(x)"
|
| 92 |
+
assert mcode(DiracDelta(x, 3)) == "dirac(3, x)"
|
| 93 |
+
assert mcode(Heaviside(x)) == "heaviside(x, 1/2)"
|
| 94 |
+
assert mcode(Heaviside(x, y)) == "heaviside(x, y)"
|
| 95 |
+
assert mcode(binomial(x, y)) == "bincoeff(x, y)"
|
| 96 |
+
assert mcode(Mod(x, y)) == "mod(x, y)"
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def test_minmax():
|
| 100 |
+
assert mcode(Max(x, y) + Min(x, y)) == "max(x, y) + min(x, y)"
|
| 101 |
+
assert mcode(Max(x, y, z)) == "max(x, max(y, z))"
|
| 102 |
+
assert mcode(Min(x, y, z)) == "min(x, min(y, z))"
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def test_Pow():
|
| 106 |
+
assert mcode(x**3) == "x.^3"
|
| 107 |
+
assert mcode(x**(y**3)) == "x.^(y.^3)"
|
| 108 |
+
assert mcode(x**Rational(2, 3)) == 'x.^(2/3)'
|
| 109 |
+
g = implemented_function('g', Lambda(x, 2*x))
|
| 110 |
+
assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \
|
| 111 |
+
"(3.5*2*x).^(-x + y.^x)./(x.^2 + y)"
|
| 112 |
+
# For issue 14160
|
| 113 |
+
assert mcode(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False),
|
| 114 |
+
evaluate=False)) == '-2*x./(y.*y)'
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def test_basic_ops():
|
| 118 |
+
assert mcode(x*y) == "x.*y"
|
| 119 |
+
assert mcode(x + y) == "x + y"
|
| 120 |
+
assert mcode(x - y) == "x - y"
|
| 121 |
+
assert mcode(-x) == "-x"
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def test_1_over_x_and_sqrt():
|
| 125 |
+
# 1.0 and 0.5 would do something different in regular StrPrinter,
|
| 126 |
+
# but these are exact in IEEE floating point so no different here.
|
| 127 |
+
assert mcode(1/x) == '1./x'
|
| 128 |
+
assert mcode(x**-1) == mcode(x**-1.0) == '1./x'
|
| 129 |
+
assert mcode(1/sqrt(x)) == '1./sqrt(x)'
|
| 130 |
+
assert mcode(x**-S.Half) == mcode(x**-0.5) == '1./sqrt(x)'
|
| 131 |
+
assert mcode(sqrt(x)) == 'sqrt(x)'
|
| 132 |
+
assert mcode(x**S.Half) == mcode(x**0.5) == 'sqrt(x)'
|
| 133 |
+
assert mcode(1/pi) == '1/pi'
|
| 134 |
+
assert mcode(pi**-1) == mcode(pi**-1.0) == '1/pi'
|
| 135 |
+
assert mcode(pi**-0.5) == '1/sqrt(pi)'
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def test_mix_number_mult_symbols():
|
| 139 |
+
assert mcode(3*x) == "3*x"
|
| 140 |
+
assert mcode(pi*x) == "pi*x"
|
| 141 |
+
assert mcode(3/x) == "3./x"
|
| 142 |
+
assert mcode(pi/x) == "pi./x"
|
| 143 |
+
assert mcode(x/3) == "x/3"
|
| 144 |
+
assert mcode(x/pi) == "x/pi"
|
| 145 |
+
assert mcode(x*y) == "x.*y"
|
| 146 |
+
assert mcode(3*x*y) == "3*x.*y"
|
| 147 |
+
assert mcode(3*pi*x*y) == "3*pi*x.*y"
|
| 148 |
+
assert mcode(x/y) == "x./y"
|
| 149 |
+
assert mcode(3*x/y) == "3*x./y"
|
| 150 |
+
assert mcode(x*y/z) == "x.*y./z"
|
| 151 |
+
assert mcode(x/y*z) == "x.*z./y"
|
| 152 |
+
assert mcode(1/x/y) == "1./(x.*y)"
|
| 153 |
+
assert mcode(2*pi*x/y/z) == "2*pi*x./(y.*z)"
|
| 154 |
+
assert mcode(3*pi/x) == "3*pi./x"
|
| 155 |
+
assert mcode(S(3)/5) == "3/5"
|
| 156 |
+
assert mcode(S(3)/5*x) == "3*x/5"
|
| 157 |
+
assert mcode(x/y/z) == "x./(y.*z)"
|
| 158 |
+
assert mcode((x+y)/z) == "(x + y)./z"
|
| 159 |
+
assert mcode((x+y)/(z+x)) == "(x + y)./(x + z)"
|
| 160 |
+
assert mcode((x+y)/EulerGamma) == "(x + y)/%s" % EulerGamma.evalf(17)
|
| 161 |
+
assert mcode(x/3/pi) == "x/(3*pi)"
|
| 162 |
+
assert mcode(S(3)/5*x*y/pi) == "3*x.*y/(5*pi)"
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
def test_mix_number_pow_symbols():
|
| 166 |
+
assert mcode(pi**3) == 'pi^3'
|
| 167 |
+
assert mcode(x**2) == 'x.^2'
|
| 168 |
+
assert mcode(x**(pi**3)) == 'x.^(pi^3)'
|
| 169 |
+
assert mcode(x**y) == 'x.^y'
|
| 170 |
+
assert mcode(x**(y**z)) == 'x.^(y.^z)'
|
| 171 |
+
assert mcode((x**y)**z) == '(x.^y).^z'
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def test_imag():
|
| 175 |
+
I = S('I')
|
| 176 |
+
assert mcode(I) == "1i"
|
| 177 |
+
assert mcode(5*I) == "5i"
|
| 178 |
+
assert mcode((S(3)/2)*I) == "3*1i/2"
|
| 179 |
+
assert mcode(3+4*I) == "3 + 4i"
|
| 180 |
+
assert mcode(sqrt(3)*I) == "sqrt(3)*1i"
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def test_constants():
|
| 184 |
+
assert mcode(pi) == "pi"
|
| 185 |
+
assert mcode(oo) == "inf"
|
| 186 |
+
assert mcode(-oo) == "-inf"
|
| 187 |
+
assert mcode(S.NegativeInfinity) == "-inf"
|
| 188 |
+
assert mcode(S.NaN) == "NaN"
|
| 189 |
+
assert mcode(S.Exp1) == "exp(1)"
|
| 190 |
+
assert mcode(exp(1)) == "exp(1)"
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def test_constants_other():
|
| 194 |
+
assert mcode(2*GoldenRatio) == "2*(1+sqrt(5))/2"
|
| 195 |
+
assert mcode(2*Catalan) == "2*%s" % Catalan.evalf(17)
|
| 196 |
+
assert mcode(2*EulerGamma) == "2*%s" % EulerGamma.evalf(17)
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
def test_boolean():
|
| 200 |
+
assert mcode(x & y) == "x & y"
|
| 201 |
+
assert mcode(x | y) == "x | y"
|
| 202 |
+
assert mcode(~x) == "~x"
|
| 203 |
+
assert mcode(x & y & z) == "x & y & z"
|
| 204 |
+
assert mcode(x | y | z) == "x | y | z"
|
| 205 |
+
assert mcode((x & y) | z) == "z | x & y"
|
| 206 |
+
assert mcode((x | y) & z) == "z & (x | y)"
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def test_KroneckerDelta():
|
| 210 |
+
from sympy.functions import KroneckerDelta
|
| 211 |
+
assert mcode(KroneckerDelta(x, y)) == "double(x == y)"
|
| 212 |
+
assert mcode(KroneckerDelta(x, y + 1)) == "double(x == (y + 1))"
|
| 213 |
+
assert mcode(KroneckerDelta(2**x, y)) == "double((2.^x) == y)"
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def test_Matrices():
|
| 217 |
+
assert mcode(Matrix(1, 1, [10])) == "10"
|
| 218 |
+
A = Matrix([[1, sin(x/2), abs(x)],
|
| 219 |
+
[0, 1, pi],
|
| 220 |
+
[0, exp(1), ceiling(x)]]);
|
| 221 |
+
expected = "[1 sin(x/2) abs(x); 0 1 pi; 0 exp(1) ceil(x)]"
|
| 222 |
+
assert mcode(A) == expected
|
| 223 |
+
# row and columns
|
| 224 |
+
assert mcode(A[:,0]) == "[1; 0; 0]"
|
| 225 |
+
assert mcode(A[0,:]) == "[1 sin(x/2) abs(x)]"
|
| 226 |
+
# empty matrices
|
| 227 |
+
assert mcode(Matrix(0, 0, [])) == '[]'
|
| 228 |
+
assert mcode(Matrix(0, 3, [])) == 'zeros(0, 3)'
|
| 229 |
+
# annoying to read but correct
|
| 230 |
+
assert mcode(Matrix([[x, x - y, -y]])) == "[x x - y -y]"
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def test_vector_entries_hadamard():
|
| 234 |
+
# For a row or column, user might to use the other dimension
|
| 235 |
+
A = Matrix([[1, sin(2/x), 3*pi/x/5]])
|
| 236 |
+
assert mcode(A) == "[1 sin(2./x) 3*pi./(5*x)]"
|
| 237 |
+
assert mcode(A.T) == "[1; sin(2./x); 3*pi./(5*x)]"
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
@XFAIL
|
| 241 |
+
def test_Matrices_entries_not_hadamard():
|
| 242 |
+
# For Matrix with col >= 2, row >= 2, they need to be scalars
|
| 243 |
+
# FIXME: is it worth worrying about this? Its not wrong, just
|
| 244 |
+
# leave it user's responsibility to put scalar data for x.
|
| 245 |
+
A = Matrix([[1, sin(2/x), 3*pi/x/5], [1, 2, x*y]])
|
| 246 |
+
expected = ("[1 sin(2/x) 3*pi/(5*x);\n"
|
| 247 |
+
"1 2 x*y]") # <- we give x.*y
|
| 248 |
+
assert mcode(A) == expected
|
| 249 |
+
|
| 250 |
+
|
| 251 |
+
def test_MatrixSymbol():
|
| 252 |
+
n = Symbol('n', integer=True)
|
| 253 |
+
A = MatrixSymbol('A', n, n)
|
| 254 |
+
B = MatrixSymbol('B', n, n)
|
| 255 |
+
assert mcode(A*B) == "A*B"
|
| 256 |
+
assert mcode(B*A) == "B*A"
|
| 257 |
+
assert mcode(2*A*B) == "2*A*B"
|
| 258 |
+
assert mcode(B*2*A) == "2*B*A"
|
| 259 |
+
assert mcode(A*(B + 3*Identity(n))) == "A*(3*eye(n) + B)"
|
| 260 |
+
assert mcode(A**(x**2)) == "A^(x.^2)"
|
| 261 |
+
assert mcode(A**3) == "A^3"
|
| 262 |
+
assert mcode(A**S.Half) == "A^(1/2)"
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def test_MatrixSolve():
|
| 266 |
+
n = Symbol('n', integer=True)
|
| 267 |
+
A = MatrixSymbol('A', n, n)
|
| 268 |
+
x = MatrixSymbol('x', n, 1)
|
| 269 |
+
assert mcode(MatrixSolve(A, x)) == "A \\ x"
|
| 270 |
+
|
| 271 |
+
def test_special_matrices():
|
| 272 |
+
assert mcode(6*Identity(3)) == "6*eye(3)"
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def test_containers():
|
| 276 |
+
assert mcode([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \
|
| 277 |
+
"{1, 2, 3, {4, 5, {6, 7}}, 8, {9, 10}, 11}"
|
| 278 |
+
assert mcode((1, 2, (3, 4))) == "{1, 2, {3, 4}}"
|
| 279 |
+
assert mcode([1]) == "{1}"
|
| 280 |
+
assert mcode((1,)) == "{1}"
|
| 281 |
+
assert mcode(Tuple(*[1, 2, 3])) == "{1, 2, 3}"
|
| 282 |
+
assert mcode((1, x*y, (3, x**2))) == "{1, x.*y, {3, x.^2}}"
|
| 283 |
+
# scalar, matrix, empty matrix and empty list
|
| 284 |
+
assert mcode((1, eye(3), Matrix(0, 0, []), [])) == "{1, [1 0 0; 0 1 0; 0 0 1], [], {}}"
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def test_octave_noninline():
|
| 288 |
+
source = mcode((x+y)/Catalan, assign_to='me', inline=False)
|
| 289 |
+
expected = (
|
| 290 |
+
"Catalan = %s;\n"
|
| 291 |
+
"me = (x + y)/Catalan;"
|
| 292 |
+
) % Catalan.evalf(17)
|
| 293 |
+
assert source == expected
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def test_octave_piecewise():
|
| 297 |
+
expr = Piecewise((x, x < 1), (x**2, True))
|
| 298 |
+
assert mcode(expr) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))"
|
| 299 |
+
assert mcode(expr, assign_to="r") == (
|
| 300 |
+
"r = ((x < 1).*(x) + (~(x < 1)).*(x.^2));")
|
| 301 |
+
assert mcode(expr, assign_to="r", inline=False) == (
|
| 302 |
+
"if (x < 1)\n"
|
| 303 |
+
" r = x;\n"
|
| 304 |
+
"else\n"
|
| 305 |
+
" r = x.^2;\n"
|
| 306 |
+
"end")
|
| 307 |
+
expr = Piecewise((x**2, x < 1), (x**3, x < 2), (x**4, x < 3), (x**5, True))
|
| 308 |
+
expected = ("((x < 1).*(x.^2) + (~(x < 1)).*( ...\n"
|
| 309 |
+
"(x < 2).*(x.^3) + (~(x < 2)).*( ...\n"
|
| 310 |
+
"(x < 3).*(x.^4) + (~(x < 3)).*(x.^5))))")
|
| 311 |
+
assert mcode(expr) == expected
|
| 312 |
+
assert mcode(expr, assign_to="r") == "r = " + expected + ";"
|
| 313 |
+
assert mcode(expr, assign_to="r", inline=False) == (
|
| 314 |
+
"if (x < 1)\n"
|
| 315 |
+
" r = x.^2;\n"
|
| 316 |
+
"elseif (x < 2)\n"
|
| 317 |
+
" r = x.^3;\n"
|
| 318 |
+
"elseif (x < 3)\n"
|
| 319 |
+
" r = x.^4;\n"
|
| 320 |
+
"else\n"
|
| 321 |
+
" r = x.^5;\n"
|
| 322 |
+
"end")
|
| 323 |
+
# Check that Piecewise without a True (default) condition error
|
| 324 |
+
expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0))
|
| 325 |
+
raises(ValueError, lambda: mcode(expr))
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
def test_octave_piecewise_times_const():
|
| 329 |
+
pw = Piecewise((x, x < 1), (x**2, True))
|
| 330 |
+
assert mcode(2*pw) == "2*((x < 1).*(x) + (~(x < 1)).*(x.^2))"
|
| 331 |
+
assert mcode(pw/x) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))./x"
|
| 332 |
+
assert mcode(pw/(x*y)) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))./(x.*y)"
|
| 333 |
+
assert mcode(pw/3) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))/3"
|
| 334 |
+
|
| 335 |
+
|
| 336 |
+
def test_octave_matrix_assign_to():
|
| 337 |
+
A = Matrix([[1, 2, 3]])
|
| 338 |
+
assert mcode(A, assign_to='a') == "a = [1 2 3];"
|
| 339 |
+
A = Matrix([[1, 2], [3, 4]])
|
| 340 |
+
assert mcode(A, assign_to='A') == "A = [1 2; 3 4];"
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def test_octave_matrix_assign_to_more():
|
| 344 |
+
# assigning to Symbol or MatrixSymbol requires lhs/rhs match
|
| 345 |
+
A = Matrix([[1, 2, 3]])
|
| 346 |
+
B = MatrixSymbol('B', 1, 3)
|
| 347 |
+
C = MatrixSymbol('C', 2, 3)
|
| 348 |
+
assert mcode(A, assign_to=B) == "B = [1 2 3];"
|
| 349 |
+
raises(ValueError, lambda: mcode(A, assign_to=x))
|
| 350 |
+
raises(ValueError, lambda: mcode(A, assign_to=C))
|
| 351 |
+
|
| 352 |
+
|
| 353 |
+
def test_octave_matrix_1x1():
|
| 354 |
+
A = Matrix([[3]])
|
| 355 |
+
B = MatrixSymbol('B', 1, 1)
|
| 356 |
+
C = MatrixSymbol('C', 1, 2)
|
| 357 |
+
assert mcode(A, assign_to=B) == "B = 3;"
|
| 358 |
+
# FIXME?
|
| 359 |
+
#assert mcode(A, assign_to=x) == "x = 3;"
|
| 360 |
+
raises(ValueError, lambda: mcode(A, assign_to=C))
|
| 361 |
+
|
| 362 |
+
|
| 363 |
+
def test_octave_matrix_elements():
|
| 364 |
+
A = Matrix([[x, 2, x*y]])
|
| 365 |
+
assert mcode(A[0, 0]**2 + A[0, 1] + A[0, 2]) == "x.^2 + x.*y + 2"
|
| 366 |
+
A = MatrixSymbol('AA', 1, 3)
|
| 367 |
+
assert mcode(A) == "AA"
|
| 368 |
+
assert mcode(A[0, 0]**2 + sin(A[0,1]) + A[0,2]) == \
|
| 369 |
+
"sin(AA(1, 2)) + AA(1, 1).^2 + AA(1, 3)"
|
| 370 |
+
assert mcode(sum(A)) == "AA(1, 1) + AA(1, 2) + AA(1, 3)"
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def test_octave_boolean():
|
| 374 |
+
assert mcode(True) == "true"
|
| 375 |
+
assert mcode(S.true) == "true"
|
| 376 |
+
assert mcode(False) == "false"
|
| 377 |
+
assert mcode(S.false) == "false"
|
| 378 |
+
|
| 379 |
+
|
| 380 |
+
def test_octave_not_supported():
|
| 381 |
+
with raises(NotImplementedError):
|
| 382 |
+
mcode(S.ComplexInfinity)
|
| 383 |
+
f = Function('f')
|
| 384 |
+
assert mcode(f(x).diff(x), strict=False) == (
|
| 385 |
+
"% Not supported in Octave:\n"
|
| 386 |
+
"% Derivative\n"
|
| 387 |
+
"Derivative(f(x), x)"
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
def test_octave_not_supported_not_on_whitelist():
|
| 392 |
+
from sympy.functions.special.polynomials import assoc_laguerre
|
| 393 |
+
with raises(NotImplementedError):
|
| 394 |
+
mcode(assoc_laguerre(x, y, z))
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
def test_octave_expint():
|
| 398 |
+
assert mcode(expint(1, x)) == "expint(x)"
|
| 399 |
+
with raises(NotImplementedError):
|
| 400 |
+
mcode(expint(2, x))
|
| 401 |
+
assert mcode(expint(y, x), strict=False) == (
|
| 402 |
+
"% Not supported in Octave:\n"
|
| 403 |
+
"% expint\n"
|
| 404 |
+
"expint(y, x)"
|
| 405 |
+
)
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
def test_trick_indent_with_end_else_words():
|
| 409 |
+
# words starting with "end" or "else" do not confuse the indenter
|
| 410 |
+
t1 = S('endless');
|
| 411 |
+
t2 = S('elsewhere');
|
| 412 |
+
pw = Piecewise((t1, x < 0), (t2, x <= 1), (1, True))
|
| 413 |
+
assert mcode(pw, inline=False) == (
|
| 414 |
+
"if (x < 0)\n"
|
| 415 |
+
" endless\n"
|
| 416 |
+
"elseif (x <= 1)\n"
|
| 417 |
+
" elsewhere\n"
|
| 418 |
+
"else\n"
|
| 419 |
+
" 1\n"
|
| 420 |
+
"end")
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
def test_hadamard():
|
| 424 |
+
A = MatrixSymbol('A', 3, 3)
|
| 425 |
+
B = MatrixSymbol('B', 3, 3)
|
| 426 |
+
v = MatrixSymbol('v', 3, 1)
|
| 427 |
+
h = MatrixSymbol('h', 1, 3)
|
| 428 |
+
C = HadamardProduct(A, B)
|
| 429 |
+
n = Symbol('n')
|
| 430 |
+
assert mcode(C) == "A.*B"
|
| 431 |
+
assert mcode(C*v) == "(A.*B)*v"
|
| 432 |
+
assert mcode(h*C*v) == "h*(A.*B)*v"
|
| 433 |
+
assert mcode(C*A) == "(A.*B)*A"
|
| 434 |
+
# mixing Hadamard and scalar strange b/c we vectorize scalars
|
| 435 |
+
assert mcode(C*x*y) == "(x.*y)*(A.*B)"
|
| 436 |
+
|
| 437 |
+
# Testing HadamardPower:
|
| 438 |
+
assert mcode(HadamardPower(A, n)) == "A.**n"
|
| 439 |
+
assert mcode(HadamardPower(A, 1+n)) == "A.**(n + 1)"
|
| 440 |
+
assert mcode(HadamardPower(A*B.T, 1+n)) == "(A*B.T).**(n + 1)"
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
def test_sparse():
|
| 444 |
+
M = SparseMatrix(5, 6, {})
|
| 445 |
+
M[2, 2] = 10;
|
| 446 |
+
M[1, 2] = 20;
|
| 447 |
+
M[1, 3] = 22;
|
| 448 |
+
M[0, 3] = 30;
|
| 449 |
+
M[3, 0] = x*y;
|
| 450 |
+
assert mcode(M) == (
|
| 451 |
+
"sparse([4 2 3 1 2], [1 3 3 4 4], [x.*y 20 10 30 22], 5, 6)"
|
| 452 |
+
)
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
def test_sinc():
|
| 456 |
+
assert mcode(sinc(x)) == 'sinc(x/pi)'
|
| 457 |
+
assert mcode(sinc(x + 3)) == 'sinc((x + 3)/pi)'
|
| 458 |
+
assert mcode(sinc(pi*(x + 3))) == 'sinc(x + 3)'
|
| 459 |
+
|
| 460 |
+
|
| 461 |
+
def test_trigfun():
|
| 462 |
+
for f in (sin, cos, tan, cot, sec, csc, asin, acos, acot, atan, asec, acsc,
|
| 463 |
+
sinh, cosh, tanh, coth, csch, sech, asinh, acosh, atanh, acoth,
|
| 464 |
+
asech, acsch):
|
| 465 |
+
assert octave_code(f(x) == f.__name__ + '(x)')
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
def test_specfun():
|
| 469 |
+
n = Symbol('n')
|
| 470 |
+
for f in [besselj, bessely, besseli, besselk]:
|
| 471 |
+
assert octave_code(f(n, x)) == f.__name__ + '(n, x)'
|
| 472 |
+
for f in (erfc, erfi, erf, erfinv, erfcinv, fresnelc, fresnels, gamma):
|
| 473 |
+
assert octave_code(f(x)) == f.__name__ + '(x)'
|
| 474 |
+
assert octave_code(hankel1(n, x)) == 'besselh(n, 1, x)'
|
| 475 |
+
assert octave_code(hankel2(n, x)) == 'besselh(n, 2, x)'
|
| 476 |
+
assert octave_code(airyai(x)) == 'airy(0, x)'
|
| 477 |
+
assert octave_code(airyaiprime(x)) == 'airy(1, x)'
|
| 478 |
+
assert octave_code(airybi(x)) == 'airy(2, x)'
|
| 479 |
+
assert octave_code(airybiprime(x)) == 'airy(3, x)'
|
| 480 |
+
assert octave_code(uppergamma(n, x)) == '(gammainc(x, n, \'upper\').*gamma(n))'
|
| 481 |
+
assert octave_code(lowergamma(n, x)) == '(gammainc(x, n).*gamma(n))'
|
| 482 |
+
assert octave_code(z**lowergamma(n, x)) == 'z.^(gammainc(x, n).*gamma(n))'
|
| 483 |
+
assert octave_code(jn(n, x)) == 'sqrt(2)*sqrt(pi)*sqrt(1./x).*besselj(n + 1/2, x)/2'
|
| 484 |
+
assert octave_code(yn(n, x)) == 'sqrt(2)*sqrt(pi)*sqrt(1./x).*bessely(n + 1/2, x)/2'
|
| 485 |
+
assert octave_code(LambertW(x)) == 'lambertw(x)'
|
| 486 |
+
assert octave_code(LambertW(x, n)) == 'lambertw(n, x)'
|
| 487 |
+
|
| 488 |
+
# Automatic rewrite
|
| 489 |
+
assert octave_code(Ei(x)) == '(logint(exp(x)))'
|
| 490 |
+
assert octave_code(dirichlet_eta(x)) == '(((x == 1).*(log(2)) + (~(x == 1)).*((1 - 2.^(1 - x)).*zeta(x))))'
|
| 491 |
+
assert octave_code(riemann_xi(x)) == '(pi.^(-x/2).*x.*(x - 1).*gamma(x/2).*zeta(x)/2)'
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
def test_MatrixElement_printing():
|
| 495 |
+
# test cases for issue #11821
|
| 496 |
+
A = MatrixSymbol("A", 1, 3)
|
| 497 |
+
B = MatrixSymbol("B", 1, 3)
|
| 498 |
+
C = MatrixSymbol("C", 1, 3)
|
| 499 |
+
|
| 500 |
+
assert mcode(A[0, 0]) == "A(1, 1)"
|
| 501 |
+
assert mcode(3 * A[0, 0]) == "3*A(1, 1)"
|
| 502 |
+
|
| 503 |
+
F = C[0, 0].subs(C, A - B)
|
| 504 |
+
assert mcode(F) == "(A - B)(1, 1)"
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
def test_zeta_printing_issue_14820():
|
| 508 |
+
assert octave_code(zeta(x)) == 'zeta(x)'
|
| 509 |
+
with raises(NotImplementedError):
|
| 510 |
+
octave_code(zeta(x, y))
|
| 511 |
+
|
| 512 |
+
|
| 513 |
+
def test_automatic_rewrite():
|
| 514 |
+
assert octave_code(Li(x)) == '(logint(x) - logint(2))'
|
| 515 |
+
assert octave_code(erf2(x, y)) == '(-erf(x) + erf(y))'
|
lib/python3.12/site-packages/sympy/printing/tests/test_preview.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
|
| 3 |
+
from sympy.core.relational import Eq
|
| 4 |
+
from sympy.core.symbol import Symbol
|
| 5 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 6 |
+
from sympy.printing.preview import preview
|
| 7 |
+
|
| 8 |
+
from io import BytesIO
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def test_preview():
|
| 12 |
+
x = Symbol('x')
|
| 13 |
+
obj = BytesIO()
|
| 14 |
+
try:
|
| 15 |
+
preview(x, output='png', viewer='BytesIO', outputbuffer=obj)
|
| 16 |
+
except RuntimeError:
|
| 17 |
+
pass # latex not installed on CI server
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def test_preview_unicode_symbol():
|
| 21 |
+
# issue 9107
|
| 22 |
+
a = Symbol('α')
|
| 23 |
+
obj = BytesIO()
|
| 24 |
+
try:
|
| 25 |
+
preview(a, output='png', viewer='BytesIO', outputbuffer=obj)
|
| 26 |
+
except RuntimeError:
|
| 27 |
+
pass # latex not installed on CI server
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def test_preview_latex_construct_in_expr():
|
| 31 |
+
# see PR 9801
|
| 32 |
+
x = Symbol('x')
|
| 33 |
+
pw = Piecewise((1, Eq(x, 0)), (0, True))
|
| 34 |
+
obj = BytesIO()
|
| 35 |
+
try:
|
| 36 |
+
preview(pw, output='png', viewer='BytesIO', outputbuffer=obj)
|
| 37 |
+
except RuntimeError:
|
| 38 |
+
pass # latex not installed on CI server
|
lib/python3.12/site-packages/sympy/printing/tests/test_pycode.py
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.codegen import Assignment
|
| 2 |
+
from sympy.codegen.ast import none
|
| 3 |
+
from sympy.codegen.cfunctions import expm1, log1p
|
| 4 |
+
from sympy.codegen.scipy_nodes import cosm1
|
| 5 |
+
from sympy.codegen.matrix_nodes import MatrixSolve
|
| 6 |
+
from sympy.core import Expr, Mod, symbols, Eq, Le, Gt, zoo, oo, Rational, Pow
|
| 7 |
+
from sympy.core.numbers import pi
|
| 8 |
+
from sympy.core.singleton import S
|
| 9 |
+
from sympy.functions import acos, KroneckerDelta, Piecewise, sign, sqrt, Min, Max, cot, acsch, asec, coth, sec
|
| 10 |
+
from sympy.logic import And, Or
|
| 11 |
+
from sympy.matrices import SparseMatrix, MatrixSymbol, Identity
|
| 12 |
+
from sympy.printing.pycode import (
|
| 13 |
+
MpmathPrinter, PythonCodePrinter, pycode, SymPyPrinter
|
| 14 |
+
)
|
| 15 |
+
from sympy.printing.tensorflow import TensorflowPrinter
|
| 16 |
+
from sympy.printing.numpy import NumPyPrinter, SciPyPrinter
|
| 17 |
+
from sympy.testing.pytest import raises, skip
|
| 18 |
+
from sympy.tensor import IndexedBase, Idx
|
| 19 |
+
from sympy.tensor.array.expressions.array_expressions import ArraySymbol, ArrayDiagonal, ArrayContraction, ZeroArray, OneArray
|
| 20 |
+
from sympy.external import import_module
|
| 21 |
+
from sympy.functions.special.gamma_functions import loggamma
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
x, y, z = symbols('x y z')
|
| 25 |
+
p = IndexedBase("p")
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def test_PythonCodePrinter():
|
| 29 |
+
prntr = PythonCodePrinter()
|
| 30 |
+
|
| 31 |
+
assert not prntr.module_imports
|
| 32 |
+
|
| 33 |
+
assert prntr.doprint(x**y) == 'x**y'
|
| 34 |
+
assert prntr.doprint(Mod(x, 2)) == 'x % 2'
|
| 35 |
+
assert prntr.doprint(-Mod(x, y)) == '-(x % y)'
|
| 36 |
+
assert prntr.doprint(Mod(-x, y)) == '(-x) % y'
|
| 37 |
+
assert prntr.doprint(And(x, y)) == 'x and y'
|
| 38 |
+
assert prntr.doprint(Or(x, y)) == 'x or y'
|
| 39 |
+
assert prntr.doprint(1/(x+y)) == '1/(x + y)'
|
| 40 |
+
assert not prntr.module_imports
|
| 41 |
+
|
| 42 |
+
assert prntr.doprint(pi) == 'math.pi'
|
| 43 |
+
assert prntr.module_imports == {'math': {'pi'}}
|
| 44 |
+
|
| 45 |
+
assert prntr.doprint(x**Rational(1, 2)) == 'math.sqrt(x)'
|
| 46 |
+
assert prntr.doprint(sqrt(x)) == 'math.sqrt(x)'
|
| 47 |
+
assert prntr.module_imports == {'math': {'pi', 'sqrt'}}
|
| 48 |
+
|
| 49 |
+
assert prntr.doprint(acos(x)) == 'math.acos(x)'
|
| 50 |
+
assert prntr.doprint(cot(x)) == '(1/math.tan(x))'
|
| 51 |
+
assert prntr.doprint(coth(x)) == '((math.exp(x) + math.exp(-x))/(math.exp(x) - math.exp(-x)))'
|
| 52 |
+
assert prntr.doprint(asec(x)) == '(math.acos(1/x))'
|
| 53 |
+
assert prntr.doprint(acsch(x)) == '(math.log(math.sqrt(1 + x**(-2)) + 1/x))'
|
| 54 |
+
|
| 55 |
+
assert prntr.doprint(Assignment(x, 2)) == 'x = 2'
|
| 56 |
+
assert prntr.doprint(Piecewise((1, Eq(x, 0)),
|
| 57 |
+
(2, x>6))) == '((1) if (x == 0) else (2) if (x > 6) else None)'
|
| 58 |
+
assert prntr.doprint(Piecewise((2, Le(x, 0)),
|
| 59 |
+
(3, Gt(x, 0)), evaluate=False)) == '((2) if (x <= 0) else'\
|
| 60 |
+
' (3) if (x > 0) else None)'
|
| 61 |
+
assert prntr.doprint(sign(x)) == '(0.0 if x == 0 else math.copysign(1, x))'
|
| 62 |
+
assert prntr.doprint(p[0, 1]) == 'p[0, 1]'
|
| 63 |
+
assert prntr.doprint(KroneckerDelta(x,y)) == '(1 if x == y else 0)'
|
| 64 |
+
|
| 65 |
+
assert prntr.doprint((2,3)) == "(2, 3)"
|
| 66 |
+
assert prntr.doprint([2,3]) == "[2, 3]"
|
| 67 |
+
|
| 68 |
+
assert prntr.doprint(Min(x, y)) == "min(x, y)"
|
| 69 |
+
assert prntr.doprint(Max(x, y)) == "max(x, y)"
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def test_PythonCodePrinter_standard():
|
| 73 |
+
prntr = PythonCodePrinter()
|
| 74 |
+
|
| 75 |
+
assert prntr.standard == 'python3'
|
| 76 |
+
|
| 77 |
+
raises(ValueError, lambda: PythonCodePrinter({'standard':'python4'}))
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_MpmathPrinter():
|
| 81 |
+
p = MpmathPrinter()
|
| 82 |
+
assert p.doprint(sign(x)) == 'mpmath.sign(x)'
|
| 83 |
+
assert p.doprint(Rational(1, 2)) == 'mpmath.mpf(1)/mpmath.mpf(2)'
|
| 84 |
+
|
| 85 |
+
assert p.doprint(S.Exp1) == 'mpmath.e'
|
| 86 |
+
assert p.doprint(S.Pi) == 'mpmath.pi'
|
| 87 |
+
assert p.doprint(S.GoldenRatio) == 'mpmath.phi'
|
| 88 |
+
assert p.doprint(S.EulerGamma) == 'mpmath.euler'
|
| 89 |
+
assert p.doprint(S.NaN) == 'mpmath.nan'
|
| 90 |
+
assert p.doprint(S.Infinity) == 'mpmath.inf'
|
| 91 |
+
assert p.doprint(S.NegativeInfinity) == 'mpmath.ninf'
|
| 92 |
+
assert p.doprint(loggamma(x)) == 'mpmath.loggamma(x)'
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def test_NumPyPrinter():
|
| 96 |
+
from sympy.core.function import Lambda
|
| 97 |
+
from sympy.matrices.expressions.adjoint import Adjoint
|
| 98 |
+
from sympy.matrices.expressions.diagonal import (DiagMatrix, DiagonalMatrix, DiagonalOf)
|
| 99 |
+
from sympy.matrices.expressions.funcmatrix import FunctionMatrix
|
| 100 |
+
from sympy.matrices.expressions.hadamard import HadamardProduct
|
| 101 |
+
from sympy.matrices.expressions.kronecker import KroneckerProduct
|
| 102 |
+
from sympy.matrices.expressions.special import (OneMatrix, ZeroMatrix)
|
| 103 |
+
from sympy.abc import a, b
|
| 104 |
+
p = NumPyPrinter()
|
| 105 |
+
assert p.doprint(sign(x)) == 'numpy.sign(x)'
|
| 106 |
+
A = MatrixSymbol("A", 2, 2)
|
| 107 |
+
B = MatrixSymbol("B", 2, 2)
|
| 108 |
+
C = MatrixSymbol("C", 1, 5)
|
| 109 |
+
D = MatrixSymbol("D", 3, 4)
|
| 110 |
+
assert p.doprint(A**(-1)) == "numpy.linalg.inv(A)"
|
| 111 |
+
assert p.doprint(A**5) == "numpy.linalg.matrix_power(A, 5)"
|
| 112 |
+
assert p.doprint(Identity(3)) == "numpy.eye(3)"
|
| 113 |
+
|
| 114 |
+
u = MatrixSymbol('x', 2, 1)
|
| 115 |
+
v = MatrixSymbol('y', 2, 1)
|
| 116 |
+
assert p.doprint(MatrixSolve(A, u)) == 'numpy.linalg.solve(A, x)'
|
| 117 |
+
assert p.doprint(MatrixSolve(A, u) + v) == 'numpy.linalg.solve(A, x) + y'
|
| 118 |
+
|
| 119 |
+
assert p.doprint(ZeroMatrix(2, 3)) == "numpy.zeros((2, 3))"
|
| 120 |
+
assert p.doprint(OneMatrix(2, 3)) == "numpy.ones((2, 3))"
|
| 121 |
+
assert p.doprint(FunctionMatrix(4, 5, Lambda((a, b), a + b))) == \
|
| 122 |
+
"numpy.fromfunction(lambda a, b: a + b, (4, 5))"
|
| 123 |
+
assert p.doprint(HadamardProduct(A, B)) == "numpy.multiply(A, B)"
|
| 124 |
+
assert p.doprint(KroneckerProduct(A, B)) == "numpy.kron(A, B)"
|
| 125 |
+
assert p.doprint(Adjoint(A)) == "numpy.conjugate(numpy.transpose(A))"
|
| 126 |
+
assert p.doprint(DiagonalOf(A)) == "numpy.reshape(numpy.diag(A), (-1, 1))"
|
| 127 |
+
assert p.doprint(DiagMatrix(C)) == "numpy.diagflat(C)"
|
| 128 |
+
assert p.doprint(DiagonalMatrix(D)) == "numpy.multiply(D, numpy.eye(3, 4))"
|
| 129 |
+
|
| 130 |
+
# Workaround for numpy negative integer power errors
|
| 131 |
+
assert p.doprint(x**-1) == 'x**(-1.0)'
|
| 132 |
+
assert p.doprint(x**-2) == 'x**(-2.0)'
|
| 133 |
+
|
| 134 |
+
expr = Pow(2, -1, evaluate=False)
|
| 135 |
+
assert p.doprint(expr) == "2**(-1.0)"
|
| 136 |
+
|
| 137 |
+
assert p.doprint(S.Exp1) == 'numpy.e'
|
| 138 |
+
assert p.doprint(S.Pi) == 'numpy.pi'
|
| 139 |
+
assert p.doprint(S.EulerGamma) == 'numpy.euler_gamma'
|
| 140 |
+
assert p.doprint(S.NaN) == 'numpy.nan'
|
| 141 |
+
assert p.doprint(S.Infinity) == 'numpy.inf'
|
| 142 |
+
assert p.doprint(S.NegativeInfinity) == '-numpy.inf'
|
| 143 |
+
|
| 144 |
+
# Function rewriting operator precedence fix
|
| 145 |
+
assert p.doprint(sec(x)**2) == '(numpy.cos(x)**(-1.0))**2'
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def test_issue_18770():
|
| 149 |
+
numpy = import_module('numpy')
|
| 150 |
+
if not numpy:
|
| 151 |
+
skip("numpy not installed.")
|
| 152 |
+
|
| 153 |
+
from sympy.functions.elementary.miscellaneous import (Max, Min)
|
| 154 |
+
from sympy.utilities.lambdify import lambdify
|
| 155 |
+
|
| 156 |
+
expr1 = Min(0.1*x + 3, x + 1, 0.5*x + 1)
|
| 157 |
+
func = lambdify(x, expr1, "numpy")
|
| 158 |
+
assert (func(numpy.linspace(0, 3, 3)) == [1.0, 1.75, 2.5 ]).all()
|
| 159 |
+
assert func(4) == 3
|
| 160 |
+
|
| 161 |
+
expr1 = Max(x**2, x**3)
|
| 162 |
+
func = lambdify(x,expr1, "numpy")
|
| 163 |
+
assert (func(numpy.linspace(-1, 2, 4)) == [1, 0, 1, 8] ).all()
|
| 164 |
+
assert func(4) == 64
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def test_SciPyPrinter():
|
| 168 |
+
p = SciPyPrinter()
|
| 169 |
+
expr = acos(x)
|
| 170 |
+
assert 'numpy' not in p.module_imports
|
| 171 |
+
assert p.doprint(expr) == 'numpy.arccos(x)'
|
| 172 |
+
assert 'numpy' in p.module_imports
|
| 173 |
+
assert not any(m.startswith('scipy') for m in p.module_imports)
|
| 174 |
+
smat = SparseMatrix(2, 5, {(0, 1): 3})
|
| 175 |
+
assert p.doprint(smat) == \
|
| 176 |
+
'scipy.sparse.coo_matrix(([3], ([0], [1])), shape=(2, 5))'
|
| 177 |
+
assert 'scipy.sparse' in p.module_imports
|
| 178 |
+
|
| 179 |
+
assert p.doprint(S.GoldenRatio) == 'scipy.constants.golden_ratio'
|
| 180 |
+
assert p.doprint(S.Pi) == 'scipy.constants.pi'
|
| 181 |
+
assert p.doprint(S.Exp1) == 'numpy.e'
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def test_pycode_reserved_words():
|
| 185 |
+
s1, s2 = symbols('if else')
|
| 186 |
+
raises(ValueError, lambda: pycode(s1 + s2, error_on_reserved=True))
|
| 187 |
+
py_str = pycode(s1 + s2)
|
| 188 |
+
assert py_str in ('else_ + if_', 'if_ + else_')
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def test_issue_20762():
|
| 192 |
+
# Make sure pycode removes curly braces from subscripted variables
|
| 193 |
+
a_b, b, a_11 = symbols('a_{b} b a_{11}')
|
| 194 |
+
expr = a_b*b
|
| 195 |
+
assert pycode(expr) == 'a_b*b'
|
| 196 |
+
expr = a_11*b
|
| 197 |
+
assert pycode(expr) == 'a_11*b'
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def test_sqrt():
|
| 201 |
+
prntr = PythonCodePrinter()
|
| 202 |
+
assert prntr._print_Pow(sqrt(x), rational=False) == 'math.sqrt(x)'
|
| 203 |
+
assert prntr._print_Pow(1/sqrt(x), rational=False) == '1/math.sqrt(x)'
|
| 204 |
+
|
| 205 |
+
prntr = PythonCodePrinter({'standard' : 'python3'})
|
| 206 |
+
assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)'
|
| 207 |
+
assert prntr._print_Pow(1/sqrt(x), rational=True) == 'x**(-1/2)'
|
| 208 |
+
|
| 209 |
+
prntr = MpmathPrinter()
|
| 210 |
+
assert prntr._print_Pow(sqrt(x), rational=False) == 'mpmath.sqrt(x)'
|
| 211 |
+
assert prntr._print_Pow(sqrt(x), rational=True) == \
|
| 212 |
+
"x**(mpmath.mpf(1)/mpmath.mpf(2))"
|
| 213 |
+
|
| 214 |
+
prntr = NumPyPrinter()
|
| 215 |
+
assert prntr._print_Pow(sqrt(x), rational=False) == 'numpy.sqrt(x)'
|
| 216 |
+
assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)'
|
| 217 |
+
|
| 218 |
+
prntr = SciPyPrinter()
|
| 219 |
+
assert prntr._print_Pow(sqrt(x), rational=False) == 'numpy.sqrt(x)'
|
| 220 |
+
assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)'
|
| 221 |
+
|
| 222 |
+
prntr = SymPyPrinter()
|
| 223 |
+
assert prntr._print_Pow(sqrt(x), rational=False) == 'sympy.sqrt(x)'
|
| 224 |
+
assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)'
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def test_frac():
|
| 228 |
+
from sympy.functions.elementary.integers import frac
|
| 229 |
+
|
| 230 |
+
expr = frac(x)
|
| 231 |
+
prntr = NumPyPrinter()
|
| 232 |
+
assert prntr.doprint(expr) == 'numpy.mod(x, 1)'
|
| 233 |
+
|
| 234 |
+
prntr = SciPyPrinter()
|
| 235 |
+
assert prntr.doprint(expr) == 'numpy.mod(x, 1)'
|
| 236 |
+
|
| 237 |
+
prntr = PythonCodePrinter()
|
| 238 |
+
assert prntr.doprint(expr) == 'x % 1'
|
| 239 |
+
|
| 240 |
+
prntr = MpmathPrinter()
|
| 241 |
+
assert prntr.doprint(expr) == 'mpmath.frac(x)'
|
| 242 |
+
|
| 243 |
+
prntr = SymPyPrinter()
|
| 244 |
+
assert prntr.doprint(expr) == 'sympy.functions.elementary.integers.frac(x)'
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
class CustomPrintedObject(Expr):
|
| 248 |
+
def _numpycode(self, printer):
|
| 249 |
+
return 'numpy'
|
| 250 |
+
|
| 251 |
+
def _mpmathcode(self, printer):
|
| 252 |
+
return 'mpmath'
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def test_printmethod():
|
| 256 |
+
obj = CustomPrintedObject()
|
| 257 |
+
assert NumPyPrinter().doprint(obj) == 'numpy'
|
| 258 |
+
assert MpmathPrinter().doprint(obj) == 'mpmath'
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
def test_codegen_ast_nodes():
|
| 262 |
+
assert pycode(none) == 'None'
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def test_issue_14283():
|
| 266 |
+
prntr = PythonCodePrinter()
|
| 267 |
+
|
| 268 |
+
assert prntr.doprint(zoo) == "math.nan"
|
| 269 |
+
assert prntr.doprint(-oo) == "float('-inf')"
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
def test_NumPyPrinter_print_seq():
|
| 273 |
+
n = NumPyPrinter()
|
| 274 |
+
|
| 275 |
+
assert n._print_seq(range(2)) == '(0, 1,)'
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def test_issue_16535_16536():
|
| 279 |
+
from sympy.functions.special.gamma_functions import (lowergamma, uppergamma)
|
| 280 |
+
|
| 281 |
+
a = symbols('a')
|
| 282 |
+
expr1 = lowergamma(a, x)
|
| 283 |
+
expr2 = uppergamma(a, x)
|
| 284 |
+
|
| 285 |
+
prntr = SciPyPrinter()
|
| 286 |
+
assert prntr.doprint(expr1) == 'scipy.special.gamma(a)*scipy.special.gammainc(a, x)'
|
| 287 |
+
assert prntr.doprint(expr2) == 'scipy.special.gamma(a)*scipy.special.gammaincc(a, x)'
|
| 288 |
+
|
| 289 |
+
p_numpy = NumPyPrinter()
|
| 290 |
+
p_pycode = PythonCodePrinter({'strict': False})
|
| 291 |
+
|
| 292 |
+
for expr in [expr1, expr2]:
|
| 293 |
+
with raises(NotImplementedError):
|
| 294 |
+
p_numpy.doprint(expr1)
|
| 295 |
+
assert "Not supported" in p_pycode.doprint(expr)
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
def test_Integral():
|
| 299 |
+
from sympy.functions.elementary.exponential import exp
|
| 300 |
+
from sympy.integrals.integrals import Integral
|
| 301 |
+
|
| 302 |
+
single = Integral(exp(-x), (x, 0, oo))
|
| 303 |
+
double = Integral(x**2*exp(x*y), (x, -z, z), (y, 0, z))
|
| 304 |
+
indefinite = Integral(x**2, x)
|
| 305 |
+
evaluateat = Integral(x**2, (x, 1))
|
| 306 |
+
|
| 307 |
+
prntr = SciPyPrinter()
|
| 308 |
+
assert prntr.doprint(single) == 'scipy.integrate.quad(lambda x: numpy.exp(-x), 0, numpy.inf)[0]'
|
| 309 |
+
assert prntr.doprint(double) == 'scipy.integrate.nquad(lambda x, y: x**2*numpy.exp(x*y), ((-z, z), (0, z)))[0]'
|
| 310 |
+
raises(NotImplementedError, lambda: prntr.doprint(indefinite))
|
| 311 |
+
raises(NotImplementedError, lambda: prntr.doprint(evaluateat))
|
| 312 |
+
|
| 313 |
+
prntr = MpmathPrinter()
|
| 314 |
+
assert prntr.doprint(single) == 'mpmath.quad(lambda x: mpmath.exp(-x), (0, mpmath.inf))'
|
| 315 |
+
assert prntr.doprint(double) == 'mpmath.quad(lambda x, y: x**2*mpmath.exp(x*y), (-z, z), (0, z))'
|
| 316 |
+
raises(NotImplementedError, lambda: prntr.doprint(indefinite))
|
| 317 |
+
raises(NotImplementedError, lambda: prntr.doprint(evaluateat))
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
def test_fresnel_integrals():
|
| 321 |
+
from sympy.functions.special.error_functions import (fresnelc, fresnels)
|
| 322 |
+
|
| 323 |
+
expr1 = fresnelc(x)
|
| 324 |
+
expr2 = fresnels(x)
|
| 325 |
+
|
| 326 |
+
prntr = SciPyPrinter()
|
| 327 |
+
assert prntr.doprint(expr1) == 'scipy.special.fresnel(x)[1]'
|
| 328 |
+
assert prntr.doprint(expr2) == 'scipy.special.fresnel(x)[0]'
|
| 329 |
+
|
| 330 |
+
p_numpy = NumPyPrinter()
|
| 331 |
+
p_pycode = PythonCodePrinter()
|
| 332 |
+
p_mpmath = MpmathPrinter()
|
| 333 |
+
for expr in [expr1, expr2]:
|
| 334 |
+
with raises(NotImplementedError):
|
| 335 |
+
p_numpy.doprint(expr)
|
| 336 |
+
with raises(NotImplementedError):
|
| 337 |
+
p_pycode.doprint(expr)
|
| 338 |
+
|
| 339 |
+
assert p_mpmath.doprint(expr1) == 'mpmath.fresnelc(x)'
|
| 340 |
+
assert p_mpmath.doprint(expr2) == 'mpmath.fresnels(x)'
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def test_beta():
|
| 344 |
+
from sympy.functions.special.beta_functions import beta
|
| 345 |
+
|
| 346 |
+
expr = beta(x, y)
|
| 347 |
+
|
| 348 |
+
prntr = SciPyPrinter()
|
| 349 |
+
assert prntr.doprint(expr) == 'scipy.special.beta(x, y)'
|
| 350 |
+
|
| 351 |
+
prntr = NumPyPrinter()
|
| 352 |
+
assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))'
|
| 353 |
+
|
| 354 |
+
prntr = PythonCodePrinter()
|
| 355 |
+
assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))'
|
| 356 |
+
|
| 357 |
+
prntr = PythonCodePrinter({'allow_unknown_functions': True})
|
| 358 |
+
assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))'
|
| 359 |
+
|
| 360 |
+
prntr = MpmathPrinter()
|
| 361 |
+
assert prntr.doprint(expr) == 'mpmath.beta(x, y)'
|
| 362 |
+
|
| 363 |
+
def test_airy():
|
| 364 |
+
from sympy.functions.special.bessel import (airyai, airybi)
|
| 365 |
+
|
| 366 |
+
expr1 = airyai(x)
|
| 367 |
+
expr2 = airybi(x)
|
| 368 |
+
|
| 369 |
+
prntr = SciPyPrinter()
|
| 370 |
+
assert prntr.doprint(expr1) == 'scipy.special.airy(x)[0]'
|
| 371 |
+
assert prntr.doprint(expr2) == 'scipy.special.airy(x)[2]'
|
| 372 |
+
|
| 373 |
+
prntr = NumPyPrinter({'strict': False})
|
| 374 |
+
assert "Not supported" in prntr.doprint(expr1)
|
| 375 |
+
assert "Not supported" in prntr.doprint(expr2)
|
| 376 |
+
|
| 377 |
+
prntr = PythonCodePrinter({'strict': False})
|
| 378 |
+
assert "Not supported" in prntr.doprint(expr1)
|
| 379 |
+
assert "Not supported" in prntr.doprint(expr2)
|
| 380 |
+
|
| 381 |
+
def test_airy_prime():
|
| 382 |
+
from sympy.functions.special.bessel import (airyaiprime, airybiprime)
|
| 383 |
+
|
| 384 |
+
expr1 = airyaiprime(x)
|
| 385 |
+
expr2 = airybiprime(x)
|
| 386 |
+
|
| 387 |
+
prntr = SciPyPrinter()
|
| 388 |
+
assert prntr.doprint(expr1) == 'scipy.special.airy(x)[1]'
|
| 389 |
+
assert prntr.doprint(expr2) == 'scipy.special.airy(x)[3]'
|
| 390 |
+
|
| 391 |
+
prntr = NumPyPrinter({'strict': False})
|
| 392 |
+
assert "Not supported" in prntr.doprint(expr1)
|
| 393 |
+
assert "Not supported" in prntr.doprint(expr2)
|
| 394 |
+
|
| 395 |
+
prntr = PythonCodePrinter({'strict': False})
|
| 396 |
+
assert "Not supported" in prntr.doprint(expr1)
|
| 397 |
+
assert "Not supported" in prntr.doprint(expr2)
|
| 398 |
+
|
| 399 |
+
|
| 400 |
+
def test_numerical_accuracy_functions():
|
| 401 |
+
prntr = SciPyPrinter()
|
| 402 |
+
assert prntr.doprint(expm1(x)) == 'numpy.expm1(x)'
|
| 403 |
+
assert prntr.doprint(log1p(x)) == 'numpy.log1p(x)'
|
| 404 |
+
assert prntr.doprint(cosm1(x)) == 'scipy.special.cosm1(x)'
|
| 405 |
+
|
| 406 |
+
def test_array_printer():
|
| 407 |
+
A = ArraySymbol('A', (4,4,6,6,6))
|
| 408 |
+
I = IndexedBase('I')
|
| 409 |
+
i,j,k = Idx('i', (0,1)), Idx('j', (2,3)), Idx('k', (4,5))
|
| 410 |
+
|
| 411 |
+
prntr = NumPyPrinter()
|
| 412 |
+
assert prntr.doprint(ZeroArray(5)) == 'numpy.zeros((5,))'
|
| 413 |
+
assert prntr.doprint(OneArray(5)) == 'numpy.ones((5,))'
|
| 414 |
+
assert prntr.doprint(ArrayContraction(A, [2,3])) == 'numpy.einsum("abccd->abd", A)'
|
| 415 |
+
assert prntr.doprint(I) == 'I'
|
| 416 |
+
assert prntr.doprint(ArrayDiagonal(A, [2,3,4])) == 'numpy.einsum("abccc->abc", A)'
|
| 417 |
+
assert prntr.doprint(ArrayDiagonal(A, [0,1], [2,3])) == 'numpy.einsum("aabbc->cab", A)'
|
| 418 |
+
assert prntr.doprint(ArrayContraction(A, [2], [3])) == 'numpy.einsum("abcde->abe", A)'
|
| 419 |
+
assert prntr.doprint(Assignment(I[i,j,k], I[i,j,k])) == 'I = I'
|
| 420 |
+
|
| 421 |
+
prntr = TensorflowPrinter()
|
| 422 |
+
assert prntr.doprint(ZeroArray(5)) == 'tensorflow.zeros((5,))'
|
| 423 |
+
assert prntr.doprint(OneArray(5)) == 'tensorflow.ones((5,))'
|
| 424 |
+
assert prntr.doprint(ArrayContraction(A, [2,3])) == 'tensorflow.linalg.einsum("abccd->abd", A)'
|
| 425 |
+
assert prntr.doprint(I) == 'I'
|
| 426 |
+
assert prntr.doprint(ArrayDiagonal(A, [2,3,4])) == 'tensorflow.linalg.einsum("abccc->abc", A)'
|
| 427 |
+
assert prntr.doprint(ArrayDiagonal(A, [0,1], [2,3])) == 'tensorflow.linalg.einsum("aabbc->cab", A)'
|
| 428 |
+
assert prntr.doprint(ArrayContraction(A, [2], [3])) == 'tensorflow.linalg.einsum("abcde->abe", A)'
|
| 429 |
+
assert prntr.doprint(Assignment(I[i,j,k], I[i,j,k])) == 'I = I'
|
lib/python3.12/site-packages/sympy/printing/tests/test_repr.py
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
from sympy.external.gmpy import GROUND_TYPES
|
| 5 |
+
from sympy.testing.pytest import raises, warns_deprecated_sympy
|
| 6 |
+
from sympy.assumptions.ask import Q
|
| 7 |
+
from sympy.core.function import (Function, WildFunction)
|
| 8 |
+
from sympy.core.numbers import (AlgebraicNumber, Float, Integer, Rational)
|
| 9 |
+
from sympy.core.singleton import S
|
| 10 |
+
from sympy.core.symbol import (Dummy, Symbol, Wild, symbols)
|
| 11 |
+
from sympy.core.sympify import sympify
|
| 12 |
+
from sympy.functions.elementary.complexes import Abs
|
| 13 |
+
from sympy.functions.elementary.miscellaneous import (root, sqrt)
|
| 14 |
+
from sympy.functions.elementary.trigonometric import sin
|
| 15 |
+
from sympy.functions.special.delta_functions import Heaviside
|
| 16 |
+
from sympy.logic.boolalg import (false, true)
|
| 17 |
+
from sympy.matrices.dense import (Matrix, ones)
|
| 18 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 19 |
+
from sympy.matrices.immutable import ImmutableDenseMatrix
|
| 20 |
+
from sympy.combinatorics import Cycle, Permutation
|
| 21 |
+
from sympy.core.symbol import Str
|
| 22 |
+
from sympy.geometry import Point, Ellipse
|
| 23 |
+
from sympy.printing import srepr
|
| 24 |
+
from sympy.polys import ring, field, ZZ, QQ, lex, grlex, Poly
|
| 25 |
+
from sympy.polys.polyclasses import DMP
|
| 26 |
+
from sympy.polys.agca.extensions import FiniteExtension
|
| 27 |
+
|
| 28 |
+
x, y = symbols('x,y')
|
| 29 |
+
|
| 30 |
+
# eval(srepr(expr)) == expr has to succeed in the right environment. The right
|
| 31 |
+
# environment is the scope of "from sympy import *" for most cases.
|
| 32 |
+
ENV: dict[str, Any] = {"Str": Str}
|
| 33 |
+
exec("from sympy import *", ENV)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def sT(expr, string, import_stmt=None, **kwargs):
|
| 37 |
+
"""
|
| 38 |
+
sT := sreprTest
|
| 39 |
+
|
| 40 |
+
Tests that srepr delivers the expected string and that
|
| 41 |
+
the condition eval(srepr(expr))==expr holds.
|
| 42 |
+
"""
|
| 43 |
+
if import_stmt is None:
|
| 44 |
+
ENV2 = ENV
|
| 45 |
+
else:
|
| 46 |
+
ENV2 = ENV.copy()
|
| 47 |
+
exec(import_stmt, ENV2)
|
| 48 |
+
|
| 49 |
+
assert srepr(expr, **kwargs) == string
|
| 50 |
+
assert eval(string, ENV2) == expr
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def test_printmethod():
|
| 54 |
+
class R(Abs):
|
| 55 |
+
def _sympyrepr(self, printer):
|
| 56 |
+
return "foo(%s)" % printer._print(self.args[0])
|
| 57 |
+
assert srepr(R(x)) == "foo(Symbol('x'))"
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_Add():
|
| 61 |
+
sT(x + y, "Add(Symbol('x'), Symbol('y'))")
|
| 62 |
+
assert srepr(x**2 + 1, order='lex') == "Add(Pow(Symbol('x'), Integer(2)), Integer(1))"
|
| 63 |
+
assert srepr(x**2 + 1, order='old') == "Add(Integer(1), Pow(Symbol('x'), Integer(2)))"
|
| 64 |
+
assert srepr(sympify('x + 3 - 2', evaluate=False), order='none') == "Add(Symbol('x'), Integer(3), Mul(Integer(-1), Integer(2)))"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_more_than_255_args_issue_10259():
|
| 68 |
+
from sympy.core.add import Add
|
| 69 |
+
from sympy.core.mul import Mul
|
| 70 |
+
for op in (Add, Mul):
|
| 71 |
+
expr = op(*symbols('x:256'))
|
| 72 |
+
assert eval(srepr(expr)) == expr
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def test_Function():
|
| 76 |
+
sT(Function("f")(x), "Function('f')(Symbol('x'))")
|
| 77 |
+
# test unapplied Function
|
| 78 |
+
sT(Function('f'), "Function('f')")
|
| 79 |
+
|
| 80 |
+
sT(sin(x), "sin(Symbol('x'))")
|
| 81 |
+
sT(sin, "sin")
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def test_Heaviside():
|
| 85 |
+
sT(Heaviside(x), "Heaviside(Symbol('x'))")
|
| 86 |
+
sT(Heaviside(x, 1), "Heaviside(Symbol('x'), Integer(1))")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def test_Geometry():
|
| 90 |
+
sT(Point(0, 0), "Point2D(Integer(0), Integer(0))")
|
| 91 |
+
sT(Ellipse(Point(0, 0), 5, 1),
|
| 92 |
+
"Ellipse(Point2D(Integer(0), Integer(0)), Integer(5), Integer(1))")
|
| 93 |
+
# TODO more tests
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def test_Singletons():
|
| 97 |
+
sT(S.Catalan, 'Catalan')
|
| 98 |
+
sT(S.ComplexInfinity, 'zoo')
|
| 99 |
+
sT(S.EulerGamma, 'EulerGamma')
|
| 100 |
+
sT(S.Exp1, 'E')
|
| 101 |
+
sT(S.GoldenRatio, 'GoldenRatio')
|
| 102 |
+
sT(S.TribonacciConstant, 'TribonacciConstant')
|
| 103 |
+
sT(S.Half, 'Rational(1, 2)')
|
| 104 |
+
sT(S.ImaginaryUnit, 'I')
|
| 105 |
+
sT(S.Infinity, 'oo')
|
| 106 |
+
sT(S.NaN, 'nan')
|
| 107 |
+
sT(S.NegativeInfinity, '-oo')
|
| 108 |
+
sT(S.NegativeOne, 'Integer(-1)')
|
| 109 |
+
sT(S.One, 'Integer(1)')
|
| 110 |
+
sT(S.Pi, 'pi')
|
| 111 |
+
sT(S.Zero, 'Integer(0)')
|
| 112 |
+
sT(S.Complexes, 'Complexes')
|
| 113 |
+
sT(S.EmptySequence, 'EmptySequence')
|
| 114 |
+
sT(S.EmptySet, 'EmptySet')
|
| 115 |
+
# sT(S.IdentityFunction, 'Lambda(_x, _x)')
|
| 116 |
+
sT(S.Naturals, 'Naturals')
|
| 117 |
+
sT(S.Naturals0, 'Naturals0')
|
| 118 |
+
sT(S.Rationals, 'Rationals')
|
| 119 |
+
sT(S.Reals, 'Reals')
|
| 120 |
+
sT(S.UniversalSet, 'UniversalSet')
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def test_Integer():
|
| 124 |
+
sT(Integer(4), "Integer(4)")
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def test_list():
|
| 128 |
+
sT([x, Integer(4)], "[Symbol('x'), Integer(4)]")
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def test_Matrix():
|
| 132 |
+
for cls, name in [(Matrix, "MutableDenseMatrix"), (ImmutableDenseMatrix, "ImmutableDenseMatrix")]:
|
| 133 |
+
sT(cls([[x**+1, 1], [y, x + y]]),
|
| 134 |
+
"%s([[Symbol('x'), Integer(1)], [Symbol('y'), Add(Symbol('x'), Symbol('y'))]])" % name)
|
| 135 |
+
|
| 136 |
+
sT(cls(), "%s([])" % name)
|
| 137 |
+
|
| 138 |
+
sT(cls([[x**+1, 1], [y, x + y]]), "%s([[Symbol('x'), Integer(1)], [Symbol('y'), Add(Symbol('x'), Symbol('y'))]])" % name)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_empty_Matrix():
|
| 142 |
+
sT(ones(0, 3), "MutableDenseMatrix(0, 3, [])")
|
| 143 |
+
sT(ones(4, 0), "MutableDenseMatrix(4, 0, [])")
|
| 144 |
+
sT(ones(0, 0), "MutableDenseMatrix([])")
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def test_Rational():
|
| 148 |
+
sT(Rational(1, 3), "Rational(1, 3)")
|
| 149 |
+
sT(Rational(-1, 3), "Rational(-1, 3)")
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def test_Float():
|
| 153 |
+
sT(Float('1.23', dps=3), "Float('1.22998', precision=13)")
|
| 154 |
+
sT(Float('1.23456789', dps=9), "Float('1.23456788994', precision=33)")
|
| 155 |
+
sT(Float('1.234567890123456789', dps=19),
|
| 156 |
+
"Float('1.234567890123456789013', precision=66)")
|
| 157 |
+
sT(Float('0.60038617995049726', dps=15),
|
| 158 |
+
"Float('0.60038617995049726', precision=53)")
|
| 159 |
+
|
| 160 |
+
sT(Float('1.23', precision=13), "Float('1.22998', precision=13)")
|
| 161 |
+
sT(Float('1.23456789', precision=33),
|
| 162 |
+
"Float('1.23456788994', precision=33)")
|
| 163 |
+
sT(Float('1.234567890123456789', precision=66),
|
| 164 |
+
"Float('1.234567890123456789013', precision=66)")
|
| 165 |
+
sT(Float('0.60038617995049726', precision=53),
|
| 166 |
+
"Float('0.60038617995049726', precision=53)")
|
| 167 |
+
|
| 168 |
+
sT(Float('0.60038617995049726', 15),
|
| 169 |
+
"Float('0.60038617995049726', precision=53)")
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def test_Symbol():
|
| 173 |
+
sT(x, "Symbol('x')")
|
| 174 |
+
sT(y, "Symbol('y')")
|
| 175 |
+
sT(Symbol('x', negative=True), "Symbol('x', negative=True)")
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def test_Symbol_two_assumptions():
|
| 179 |
+
x = Symbol('x', negative=0, integer=1)
|
| 180 |
+
# order could vary
|
| 181 |
+
s1 = "Symbol('x', integer=True, negative=False)"
|
| 182 |
+
s2 = "Symbol('x', negative=False, integer=True)"
|
| 183 |
+
assert srepr(x) in (s1, s2)
|
| 184 |
+
assert eval(srepr(x), ENV) == x
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def test_Symbol_no_special_commutative_treatment():
|
| 188 |
+
sT(Symbol('x'), "Symbol('x')")
|
| 189 |
+
sT(Symbol('x', commutative=False), "Symbol('x', commutative=False)")
|
| 190 |
+
sT(Symbol('x', commutative=0), "Symbol('x', commutative=False)")
|
| 191 |
+
sT(Symbol('x', commutative=True), "Symbol('x', commutative=True)")
|
| 192 |
+
sT(Symbol('x', commutative=1), "Symbol('x', commutative=True)")
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def test_Wild():
|
| 196 |
+
sT(Wild('x', even=True), "Wild('x', even=True)")
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
def test_Dummy():
|
| 200 |
+
d = Dummy('d')
|
| 201 |
+
sT(d, "Dummy('d', dummy_index=%s)" % str(d.dummy_index))
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def test_Dummy_assumption():
|
| 205 |
+
d = Dummy('d', nonzero=True)
|
| 206 |
+
assert d == eval(srepr(d))
|
| 207 |
+
s1 = "Dummy('d', dummy_index=%s, nonzero=True)" % str(d.dummy_index)
|
| 208 |
+
s2 = "Dummy('d', nonzero=True, dummy_index=%s)" % str(d.dummy_index)
|
| 209 |
+
assert srepr(d) in (s1, s2)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def test_Dummy_from_Symbol():
|
| 213 |
+
# should not get the full dictionary of assumptions
|
| 214 |
+
n = Symbol('n', integer=True)
|
| 215 |
+
d = n.as_dummy()
|
| 216 |
+
assert srepr(d
|
| 217 |
+
) == "Dummy('n', dummy_index=%s)" % str(d.dummy_index)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def test_tuple():
|
| 221 |
+
sT((x,), "(Symbol('x'),)")
|
| 222 |
+
sT((x, y), "(Symbol('x'), Symbol('y'))")
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def test_WildFunction():
|
| 226 |
+
sT(WildFunction('w'), "WildFunction('w')")
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
def test_settins():
|
| 230 |
+
raises(TypeError, lambda: srepr(x, method="garbage"))
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def test_Mul():
|
| 234 |
+
sT(3*x**3*y, "Mul(Integer(3), Pow(Symbol('x'), Integer(3)), Symbol('y'))")
|
| 235 |
+
assert srepr(3*x**3*y, order='old') == "Mul(Integer(3), Symbol('y'), Pow(Symbol('x'), Integer(3)))"
|
| 236 |
+
assert srepr(sympify('(x+4)*2*x*7', evaluate=False), order='none') == "Mul(Add(Symbol('x'), Integer(4)), Integer(2), Symbol('x'), Integer(7))"
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def test_AlgebraicNumber():
|
| 240 |
+
a = AlgebraicNumber(sqrt(2))
|
| 241 |
+
sT(a, "AlgebraicNumber(Pow(Integer(2), Rational(1, 2)), [Integer(1), Integer(0)])")
|
| 242 |
+
a = AlgebraicNumber(root(-2, 3))
|
| 243 |
+
sT(a, "AlgebraicNumber(Pow(Integer(-2), Rational(1, 3)), [Integer(1), Integer(0)])")
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
def test_PolyRing():
|
| 247 |
+
assert srepr(ring("x", ZZ, lex)[0]) == "PolyRing((Symbol('x'),), ZZ, lex)"
|
| 248 |
+
assert srepr(ring("x,y", QQ, grlex)[0]) == "PolyRing((Symbol('x'), Symbol('y')), QQ, grlex)"
|
| 249 |
+
assert srepr(ring("x,y,z", ZZ["t"], lex)[0]) == "PolyRing((Symbol('x'), Symbol('y'), Symbol('z')), ZZ[t], lex)"
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
def test_FracField():
|
| 253 |
+
assert srepr(field("x", ZZ, lex)[0]) == "FracField((Symbol('x'),), ZZ, lex)"
|
| 254 |
+
assert srepr(field("x,y", QQ, grlex)[0]) == "FracField((Symbol('x'), Symbol('y')), QQ, grlex)"
|
| 255 |
+
assert srepr(field("x,y,z", ZZ["t"], lex)[0]) == "FracField((Symbol('x'), Symbol('y'), Symbol('z')), ZZ[t], lex)"
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
def test_PolyElement():
|
| 259 |
+
R, x, y = ring("x,y", ZZ)
|
| 260 |
+
assert srepr(3*x**2*y + 1) == "PolyElement(PolyRing((Symbol('x'), Symbol('y')), ZZ, lex), [((2, 1), 3), ((0, 0), 1)])"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def test_FracElement():
|
| 264 |
+
F, x, y = field("x,y", ZZ)
|
| 265 |
+
assert srepr((3*x**2*y + 1)/(x - y**2)) == "FracElement(FracField((Symbol('x'), Symbol('y')), ZZ, lex), [((2, 1), 3), ((0, 0), 1)], [((1, 0), 1), ((0, 2), -1)])"
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
def test_FractionField():
|
| 269 |
+
assert srepr(QQ.frac_field(x)) == \
|
| 270 |
+
"FractionField(FracField((Symbol('x'),), QQ, lex))"
|
| 271 |
+
assert srepr(QQ.frac_field(x, y, order=grlex)) == \
|
| 272 |
+
"FractionField(FracField((Symbol('x'), Symbol('y')), QQ, grlex))"
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def test_PolynomialRingBase():
|
| 276 |
+
assert srepr(ZZ.old_poly_ring(x)) == \
|
| 277 |
+
"GlobalPolynomialRing(ZZ, Symbol('x'))"
|
| 278 |
+
assert srepr(ZZ[x].old_poly_ring(y)) == \
|
| 279 |
+
"GlobalPolynomialRing(ZZ[x], Symbol('y'))"
|
| 280 |
+
assert srepr(QQ.frac_field(x).old_poly_ring(y)) == \
|
| 281 |
+
"GlobalPolynomialRing(FractionField(FracField((Symbol('x'),), QQ, lex)), Symbol('y'))"
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
def test_DMP():
|
| 285 |
+
p1 = DMP([1, 2], ZZ)
|
| 286 |
+
p2 = ZZ.old_poly_ring(x)([1, 2])
|
| 287 |
+
if GROUND_TYPES != 'flint':
|
| 288 |
+
assert srepr(p1) == "DMP_Python([1, 2], ZZ)"
|
| 289 |
+
assert srepr(p2) == "DMP_Python([1, 2], ZZ)"
|
| 290 |
+
else:
|
| 291 |
+
assert srepr(p1) == "DUP_Flint([1, 2], ZZ)"
|
| 292 |
+
assert srepr(p2) == "DUP_Flint([1, 2], ZZ)"
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
def test_FiniteExtension():
|
| 296 |
+
assert srepr(FiniteExtension(Poly(x**2 + 1, x))) == \
|
| 297 |
+
"FiniteExtension(Poly(x**2 + 1, x, domain='ZZ'))"
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
def test_ExtensionElement():
|
| 301 |
+
A = FiniteExtension(Poly(x**2 + 1, x))
|
| 302 |
+
if GROUND_TYPES != 'flint':
|
| 303 |
+
ans = "ExtElem(DMP_Python([1, 0], ZZ), FiniteExtension(Poly(x**2 + 1, x, domain='ZZ')))"
|
| 304 |
+
else:
|
| 305 |
+
ans = "ExtElem(DUP_Flint([1, 0], ZZ), FiniteExtension(Poly(x**2 + 1, x, domain='ZZ')))"
|
| 306 |
+
assert srepr(A.generator) == ans
|
| 307 |
+
|
| 308 |
+
def test_BooleanAtom():
|
| 309 |
+
assert srepr(true) == "true"
|
| 310 |
+
assert srepr(false) == "false"
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def test_Integers():
|
| 314 |
+
sT(S.Integers, "Integers")
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def test_Naturals():
|
| 318 |
+
sT(S.Naturals, "Naturals")
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
def test_Naturals0():
|
| 322 |
+
sT(S.Naturals0, "Naturals0")
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
def test_Reals():
|
| 326 |
+
sT(S.Reals, "Reals")
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
def test_matrix_expressions():
|
| 330 |
+
n = symbols('n', integer=True)
|
| 331 |
+
A = MatrixSymbol("A", n, n)
|
| 332 |
+
B = MatrixSymbol("B", n, n)
|
| 333 |
+
sT(A, "MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True))")
|
| 334 |
+
sT(A*B, "MatMul(MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True)), MatrixSymbol(Str('B'), Symbol('n', integer=True), Symbol('n', integer=True)))")
|
| 335 |
+
sT(A + B, "MatAdd(MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True)), MatrixSymbol(Str('B'), Symbol('n', integer=True), Symbol('n', integer=True)))")
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
def test_Cycle():
|
| 339 |
+
# FIXME: sT fails because Cycle is not immutable and calling srepr(Cycle(1, 2))
|
| 340 |
+
# adds keys to the Cycle dict (GH-17661)
|
| 341 |
+
#import_stmt = "from sympy.combinatorics import Cycle"
|
| 342 |
+
#sT(Cycle(1, 2), "Cycle(1, 2)", import_stmt)
|
| 343 |
+
assert srepr(Cycle(1, 2)) == "Cycle(1, 2)"
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
def test_Permutation():
|
| 347 |
+
import_stmt = "from sympy.combinatorics import Permutation"
|
| 348 |
+
sT(Permutation(1, 2)(3, 4), "Permutation([0, 2, 1, 4, 3])", import_stmt, perm_cyclic=False)
|
| 349 |
+
sT(Permutation(1, 2)(3, 4), "Permutation(1, 2)(3, 4)", import_stmt, perm_cyclic=True)
|
| 350 |
+
|
| 351 |
+
with warns_deprecated_sympy():
|
| 352 |
+
old_print_cyclic = Permutation.print_cyclic
|
| 353 |
+
Permutation.print_cyclic = False
|
| 354 |
+
sT(Permutation(1, 2)(3, 4), "Permutation([0, 2, 1, 4, 3])", import_stmt)
|
| 355 |
+
Permutation.print_cyclic = old_print_cyclic
|
| 356 |
+
|
| 357 |
+
def test_dict():
|
| 358 |
+
from sympy.abc import x, y, z
|
| 359 |
+
d = {}
|
| 360 |
+
assert srepr(d) == "{}"
|
| 361 |
+
d = {x: y}
|
| 362 |
+
assert srepr(d) == "{Symbol('x'): Symbol('y')}"
|
| 363 |
+
d = {x: y, y: z}
|
| 364 |
+
assert srepr(d) in (
|
| 365 |
+
"{Symbol('x'): Symbol('y'), Symbol('y'): Symbol('z')}",
|
| 366 |
+
"{Symbol('y'): Symbol('z'), Symbol('x'): Symbol('y')}",
|
| 367 |
+
)
|
| 368 |
+
d = {x: {y: z}}
|
| 369 |
+
assert srepr(d) == "{Symbol('x'): {Symbol('y'): Symbol('z')}}"
|
| 370 |
+
|
| 371 |
+
def test_set():
|
| 372 |
+
from sympy.abc import x, y
|
| 373 |
+
s = set()
|
| 374 |
+
assert srepr(s) == "set()"
|
| 375 |
+
s = {x, y}
|
| 376 |
+
assert srepr(s) in ("{Symbol('x'), Symbol('y')}", "{Symbol('y'), Symbol('x')}")
|
| 377 |
+
|
| 378 |
+
def test_Predicate():
|
| 379 |
+
sT(Q.even, "Q.even")
|
| 380 |
+
|
| 381 |
+
def test_AppliedPredicate():
|
| 382 |
+
sT(Q.even(Symbol('z')), "AppliedPredicate(Q.even, Symbol('z'))")
|
lib/python3.12/site-packages/sympy/printing/tests/test_smtlib.py
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import contextlib
|
| 2 |
+
import itertools
|
| 3 |
+
import re
|
| 4 |
+
import typing
|
| 5 |
+
from enum import Enum
|
| 6 |
+
from typing import Callable
|
| 7 |
+
|
| 8 |
+
import sympy
|
| 9 |
+
from sympy import Add, Implies, sqrt
|
| 10 |
+
from sympy.core import Mul, Pow
|
| 11 |
+
from sympy.core import (S, pi, symbols, Function, Rational, Integer,
|
| 12 |
+
Symbol, Eq, Ne, Le, Lt, Gt, Ge)
|
| 13 |
+
from sympy.functions import Piecewise, exp, sin, cos
|
| 14 |
+
from sympy.assumptions.ask import Q
|
| 15 |
+
from sympy.printing.smtlib import smtlib_code
|
| 16 |
+
from sympy.testing.pytest import raises, Failed
|
| 17 |
+
|
| 18 |
+
x, y, z = symbols('x,y,z')
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class _W(Enum):
|
| 22 |
+
DEFAULTING_TO_FLOAT = re.compile("Could not infer type of `.+`. Defaulting to float.", re.I)
|
| 23 |
+
WILL_NOT_DECLARE = re.compile("Non-Symbol/Function `.+` will not be declared.", re.I)
|
| 24 |
+
WILL_NOT_ASSERT = re.compile("Non-Boolean expression `.+` will not be asserted. Converting to SMTLib verbatim.", re.I)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
@contextlib.contextmanager
|
| 28 |
+
def _check_warns(expected: typing.Iterable[_W]):
|
| 29 |
+
warns: typing.List[str] = []
|
| 30 |
+
log_warn = warns.append
|
| 31 |
+
yield log_warn
|
| 32 |
+
|
| 33 |
+
errors = []
|
| 34 |
+
for i, (w, e) in enumerate(itertools.zip_longest(warns, expected)):
|
| 35 |
+
if not e:
|
| 36 |
+
errors += [f"[{i}] Received unexpected warning `{w}`."]
|
| 37 |
+
elif not w:
|
| 38 |
+
errors += [f"[{i}] Did not receive expected warning `{e.name}`."]
|
| 39 |
+
elif not e.value.match(w):
|
| 40 |
+
errors += [f"[{i}] Warning `{w}` does not match expected {e.name}."]
|
| 41 |
+
|
| 42 |
+
if errors: raise Failed('\n'.join(errors))
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def test_Integer():
|
| 46 |
+
with _check_warns([_W.WILL_NOT_ASSERT] * 2) as w:
|
| 47 |
+
assert smtlib_code(Integer(67), log_warn=w) == "67"
|
| 48 |
+
assert smtlib_code(Integer(-1), log_warn=w) == "-1"
|
| 49 |
+
with _check_warns([]) as w:
|
| 50 |
+
assert smtlib_code(Integer(67)) == "67"
|
| 51 |
+
assert smtlib_code(Integer(-1)) == "-1"
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def test_Rational():
|
| 55 |
+
with _check_warns([_W.WILL_NOT_ASSERT] * 4) as w:
|
| 56 |
+
assert smtlib_code(Rational(3, 7), log_warn=w) == "(/ 3 7)"
|
| 57 |
+
assert smtlib_code(Rational(18, 9), log_warn=w) == "2"
|
| 58 |
+
assert smtlib_code(Rational(3, -7), log_warn=w) == "(/ -3 7)"
|
| 59 |
+
assert smtlib_code(Rational(-3, -7), log_warn=w) == "(/ 3 7)"
|
| 60 |
+
|
| 61 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT] * 2) as w:
|
| 62 |
+
assert smtlib_code(x + Rational(3, 7), auto_declare=False, log_warn=w) == "(+ (/ 3 7) x)"
|
| 63 |
+
assert smtlib_code(Rational(3, 7) * x, log_warn=w) == "(declare-const x Real)\n" \
|
| 64 |
+
"(* (/ 3 7) x)"
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_Relational():
|
| 68 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT] * 12) as w:
|
| 69 |
+
assert smtlib_code(Eq(x, y), auto_declare=False, log_warn=w) == "(assert (= x y))"
|
| 70 |
+
assert smtlib_code(Ne(x, y), auto_declare=False, log_warn=w) == "(assert (not (= x y)))"
|
| 71 |
+
assert smtlib_code(Le(x, y), auto_declare=False, log_warn=w) == "(assert (<= x y))"
|
| 72 |
+
assert smtlib_code(Lt(x, y), auto_declare=False, log_warn=w) == "(assert (< x y))"
|
| 73 |
+
assert smtlib_code(Gt(x, y), auto_declare=False, log_warn=w) == "(assert (> x y))"
|
| 74 |
+
assert smtlib_code(Ge(x, y), auto_declare=False, log_warn=w) == "(assert (>= x y))"
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def test_AppliedBinaryRelation():
|
| 78 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT] * 12) as w:
|
| 79 |
+
assert smtlib_code(Q.eq(x, y), auto_declare=False, log_warn=w) == "(assert (= x y))"
|
| 80 |
+
assert smtlib_code(Q.ne(x, y), auto_declare=False, log_warn=w) == "(assert (not (= x y)))"
|
| 81 |
+
assert smtlib_code(Q.lt(x, y), auto_declare=False, log_warn=w) == "(assert (< x y))"
|
| 82 |
+
assert smtlib_code(Q.le(x, y), auto_declare=False, log_warn=w) == "(assert (<= x y))"
|
| 83 |
+
assert smtlib_code(Q.gt(x, y), auto_declare=False, log_warn=w) == "(assert (> x y))"
|
| 84 |
+
assert smtlib_code(Q.ge(x, y), auto_declare=False, log_warn=w) == "(assert (>= x y))"
|
| 85 |
+
|
| 86 |
+
raises(ValueError, lambda: smtlib_code(Q.complex(x), log_warn=w))
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def test_AppliedPredicate():
|
| 90 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT] * 6) as w:
|
| 91 |
+
assert smtlib_code(Q.positive(x), auto_declare=False, log_warn=w) == "(assert (> x 0))"
|
| 92 |
+
assert smtlib_code(Q.negative(x), auto_declare=False, log_warn=w) == "(assert (< x 0))"
|
| 93 |
+
assert smtlib_code(Q.zero(x), auto_declare=False, log_warn=w) == "(assert (= x 0))"
|
| 94 |
+
assert smtlib_code(Q.nonpositive(x), auto_declare=False, log_warn=w) == "(assert (<= x 0))"
|
| 95 |
+
assert smtlib_code(Q.nonnegative(x), auto_declare=False, log_warn=w) == "(assert (>= x 0))"
|
| 96 |
+
assert smtlib_code(Q.nonzero(x), auto_declare=False, log_warn=w) == "(assert (not (= x 0)))"
|
| 97 |
+
|
| 98 |
+
def test_Function():
|
| 99 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 100 |
+
assert smtlib_code(sin(x) ** cos(x), auto_declare=False, log_warn=w) == "(pow (sin x) (cos x))"
|
| 101 |
+
|
| 102 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 103 |
+
assert smtlib_code(
|
| 104 |
+
abs(x),
|
| 105 |
+
symbol_table={x: int, y: bool},
|
| 106 |
+
known_types={int: "INTEGER_TYPE"},
|
| 107 |
+
known_functions={sympy.Abs: "ABSOLUTE_VALUE_OF"},
|
| 108 |
+
log_warn=w
|
| 109 |
+
) == "(declare-const x INTEGER_TYPE)\n" \
|
| 110 |
+
"(ABSOLUTE_VALUE_OF x)"
|
| 111 |
+
|
| 112 |
+
my_fun1 = Function('f1')
|
| 113 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 114 |
+
assert smtlib_code(
|
| 115 |
+
my_fun1(x),
|
| 116 |
+
symbol_table={my_fun1: Callable[[bool], float]},
|
| 117 |
+
log_warn=w
|
| 118 |
+
) == "(declare-const x Bool)\n" \
|
| 119 |
+
"(declare-fun f1 (Bool) Real)\n" \
|
| 120 |
+
"(f1 x)"
|
| 121 |
+
|
| 122 |
+
with _check_warns([]) as w:
|
| 123 |
+
assert smtlib_code(
|
| 124 |
+
my_fun1(x),
|
| 125 |
+
symbol_table={my_fun1: Callable[[bool], bool]},
|
| 126 |
+
log_warn=w
|
| 127 |
+
) == "(declare-const x Bool)\n" \
|
| 128 |
+
"(declare-fun f1 (Bool) Bool)\n" \
|
| 129 |
+
"(assert (f1 x))"
|
| 130 |
+
|
| 131 |
+
assert smtlib_code(
|
| 132 |
+
Eq(my_fun1(x, z), y),
|
| 133 |
+
symbol_table={my_fun1: Callable[[int, bool], bool]},
|
| 134 |
+
log_warn=w
|
| 135 |
+
) == "(declare-const x Int)\n" \
|
| 136 |
+
"(declare-const y Bool)\n" \
|
| 137 |
+
"(declare-const z Bool)\n" \
|
| 138 |
+
"(declare-fun f1 (Int Bool) Bool)\n" \
|
| 139 |
+
"(assert (= (f1 x z) y))"
|
| 140 |
+
|
| 141 |
+
assert smtlib_code(
|
| 142 |
+
Eq(my_fun1(x, z), y),
|
| 143 |
+
symbol_table={my_fun1: Callable[[int, bool], bool]},
|
| 144 |
+
known_functions={my_fun1: "MY_KNOWN_FUN", Eq: '=='},
|
| 145 |
+
log_warn=w
|
| 146 |
+
) == "(declare-const x Int)\n" \
|
| 147 |
+
"(declare-const y Bool)\n" \
|
| 148 |
+
"(declare-const z Bool)\n" \
|
| 149 |
+
"(assert (== (MY_KNOWN_FUN x z) y))"
|
| 150 |
+
|
| 151 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT] * 3) as w:
|
| 152 |
+
assert smtlib_code(
|
| 153 |
+
Eq(my_fun1(x, z), y),
|
| 154 |
+
known_functions={my_fun1: "MY_KNOWN_FUN", Eq: '=='},
|
| 155 |
+
log_warn=w
|
| 156 |
+
) == "(declare-const x Real)\n" \
|
| 157 |
+
"(declare-const y Real)\n" \
|
| 158 |
+
"(declare-const z Real)\n" \
|
| 159 |
+
"(assert (== (MY_KNOWN_FUN x z) y))"
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def test_Pow():
|
| 163 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 164 |
+
assert smtlib_code(x ** 3, auto_declare=False, log_warn=w) == "(pow x 3)"
|
| 165 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 166 |
+
assert smtlib_code(x ** (y ** 3), auto_declare=False, log_warn=w) == "(pow x (pow y 3))"
|
| 167 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 168 |
+
assert smtlib_code(x ** Rational(2, 3), auto_declare=False, log_warn=w) == '(pow x (/ 2 3))'
|
| 169 |
+
|
| 170 |
+
a = Symbol('a', integer=True)
|
| 171 |
+
b = Symbol('b', real=True)
|
| 172 |
+
c = Symbol('c')
|
| 173 |
+
|
| 174 |
+
def g(x): return 2 * x
|
| 175 |
+
|
| 176 |
+
# if x=1, y=2, then expr=2.333...
|
| 177 |
+
expr = 1 / (g(a) * 3.5) ** (a - b ** a) / (a ** 2 + b)
|
| 178 |
+
|
| 179 |
+
with _check_warns([]) as w:
|
| 180 |
+
assert smtlib_code(
|
| 181 |
+
[
|
| 182 |
+
Eq(a < 2, c),
|
| 183 |
+
Eq(b > a, c),
|
| 184 |
+
c & True,
|
| 185 |
+
Eq(expr, 2 + Rational(1, 3))
|
| 186 |
+
],
|
| 187 |
+
log_warn=w
|
| 188 |
+
) == '(declare-const a Int)\n' \
|
| 189 |
+
'(declare-const b Real)\n' \
|
| 190 |
+
'(declare-const c Bool)\n' \
|
| 191 |
+
'(assert (= (< a 2) c))\n' \
|
| 192 |
+
'(assert (= (> b a) c))\n' \
|
| 193 |
+
'(assert c)\n' \
|
| 194 |
+
'(assert (= ' \
|
| 195 |
+
'(* (pow (* 7.0 a) (+ (pow b a) (* -1 a))) (pow (+ b (pow a 2)) -1)) ' \
|
| 196 |
+
'(/ 7 3)' \
|
| 197 |
+
'))'
|
| 198 |
+
|
| 199 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 200 |
+
assert smtlib_code(
|
| 201 |
+
Mul(-2, c, Pow(Mul(b, b, evaluate=False), -1, evaluate=False), evaluate=False),
|
| 202 |
+
log_warn=w
|
| 203 |
+
) == '(declare-const b Real)\n' \
|
| 204 |
+
'(declare-const c Real)\n' \
|
| 205 |
+
'(* -2 c (pow (* b b) -1))'
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
def test_basic_ops():
|
| 209 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 210 |
+
assert smtlib_code(x * y, auto_declare=False, log_warn=w) == "(* x y)"
|
| 211 |
+
|
| 212 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 213 |
+
assert smtlib_code(x + y, auto_declare=False, log_warn=w) == "(+ x y)"
|
| 214 |
+
|
| 215 |
+
# with _check_warns([_SmtlibWarnings.DEFAULTING_TO_FLOAT, _SmtlibWarnings.DEFAULTING_TO_FLOAT, _SmtlibWarnings.WILL_NOT_ASSERT]) as w:
|
| 216 |
+
# todo: implement re-write, currently does '(+ x (* -1 y))' instead
|
| 217 |
+
# assert smtlib_code(x - y, auto_declare=False, log_warn=w) == "(- x y)"
|
| 218 |
+
|
| 219 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 220 |
+
assert smtlib_code(-x, auto_declare=False, log_warn=w) == "(* -1 x)"
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def test_quantifier_extensions():
|
| 224 |
+
from sympy.logic.boolalg import Boolean
|
| 225 |
+
from sympy import Interval, Tuple, sympify
|
| 226 |
+
|
| 227 |
+
# start For-all quantifier class example
|
| 228 |
+
class ForAll(Boolean):
|
| 229 |
+
def _smtlib(self, printer):
|
| 230 |
+
bound_symbol_declarations = [
|
| 231 |
+
printer._s_expr(sym.name, [
|
| 232 |
+
printer._known_types[printer.symbol_table[sym]],
|
| 233 |
+
Interval(start, end)
|
| 234 |
+
]) for sym, start, end in self.limits
|
| 235 |
+
]
|
| 236 |
+
return printer._s_expr('forall', [
|
| 237 |
+
printer._s_expr('', bound_symbol_declarations),
|
| 238 |
+
self.function
|
| 239 |
+
])
|
| 240 |
+
|
| 241 |
+
@property
|
| 242 |
+
def bound_symbols(self):
|
| 243 |
+
return {s for s, _, _ in self.limits}
|
| 244 |
+
|
| 245 |
+
@property
|
| 246 |
+
def free_symbols(self):
|
| 247 |
+
bound_symbol_names = {s.name for s in self.bound_symbols}
|
| 248 |
+
return {
|
| 249 |
+
s for s in self.function.free_symbols
|
| 250 |
+
if s.name not in bound_symbol_names
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
def __new__(cls, *args):
|
| 254 |
+
limits = [sympify(a) for a in args if isinstance(a, (tuple, Tuple))]
|
| 255 |
+
function = [sympify(a) for a in args if isinstance(a, Boolean)]
|
| 256 |
+
assert len(limits) + len(function) == len(args)
|
| 257 |
+
assert len(function) == 1
|
| 258 |
+
function = function[0]
|
| 259 |
+
|
| 260 |
+
if isinstance(function, ForAll): return ForAll.__new__(
|
| 261 |
+
ForAll, *(limits + function.limits), function.function
|
| 262 |
+
)
|
| 263 |
+
inst = Boolean.__new__(cls)
|
| 264 |
+
inst._args = tuple(limits + [function])
|
| 265 |
+
inst.limits = limits
|
| 266 |
+
inst.function = function
|
| 267 |
+
return inst
|
| 268 |
+
|
| 269 |
+
# end For-All Quantifier class example
|
| 270 |
+
|
| 271 |
+
f = Function('f')
|
| 272 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w:
|
| 273 |
+
assert smtlib_code(
|
| 274 |
+
ForAll((x, -42, +21), Eq(f(x), f(x))),
|
| 275 |
+
symbol_table={f: Callable[[float], float]},
|
| 276 |
+
log_warn=w
|
| 277 |
+
) == '(assert (forall ( (x Real [-42, 21])) true))'
|
| 278 |
+
|
| 279 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT] * 2) as w:
|
| 280 |
+
assert smtlib_code(
|
| 281 |
+
ForAll(
|
| 282 |
+
(x, -42, +21), (y, -100, 3),
|
| 283 |
+
Implies(Eq(x, y), Eq(f(x), f(y)))
|
| 284 |
+
),
|
| 285 |
+
symbol_table={f: Callable[[float], float]},
|
| 286 |
+
log_warn=w
|
| 287 |
+
) == '(declare-fun f (Real) Real)\n' \
|
| 288 |
+
'(assert (' \
|
| 289 |
+
'forall ( (x Real [-42, 21]) (y Real [-100, 3])) ' \
|
| 290 |
+
'(=> (= x y) (= (f x) (f y)))' \
|
| 291 |
+
'))'
|
| 292 |
+
|
| 293 |
+
a = Symbol('a', integer=True)
|
| 294 |
+
b = Symbol('b', real=True)
|
| 295 |
+
c = Symbol('c')
|
| 296 |
+
|
| 297 |
+
with _check_warns([]) as w:
|
| 298 |
+
assert smtlib_code(
|
| 299 |
+
ForAll(
|
| 300 |
+
(a, 2, 100), ForAll(
|
| 301 |
+
(b, 2, 100),
|
| 302 |
+
Implies(a < b, sqrt(a) < b) | c
|
| 303 |
+
)),
|
| 304 |
+
log_warn=w
|
| 305 |
+
) == '(declare-const c Bool)\n' \
|
| 306 |
+
'(assert (forall ( (a Int [2, 100]) (b Real [2, 100])) ' \
|
| 307 |
+
'(or c (=> (< a b) (< (pow a (/ 1 2)) b)))' \
|
| 308 |
+
'))'
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def test_mix_number_mult_symbols():
|
| 312 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 313 |
+
assert smtlib_code(
|
| 314 |
+
1 / pi,
|
| 315 |
+
known_constants={pi: "MY_PI"},
|
| 316 |
+
log_warn=w
|
| 317 |
+
) == '(pow MY_PI -1)'
|
| 318 |
+
|
| 319 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 320 |
+
assert smtlib_code(
|
| 321 |
+
[
|
| 322 |
+
Eq(pi, 3.14, evaluate=False),
|
| 323 |
+
1 / pi,
|
| 324 |
+
],
|
| 325 |
+
known_constants={pi: "MY_PI"},
|
| 326 |
+
log_warn=w
|
| 327 |
+
) == '(assert (= MY_PI 3.14))\n' \
|
| 328 |
+
'(pow MY_PI -1)'
|
| 329 |
+
|
| 330 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 331 |
+
assert smtlib_code(
|
| 332 |
+
Add(S.Zero, S.One, S.NegativeOne, S.Half,
|
| 333 |
+
S.Exp1, S.Pi, S.GoldenRatio, evaluate=False),
|
| 334 |
+
known_constants={
|
| 335 |
+
S.Pi: 'p', S.GoldenRatio: 'g',
|
| 336 |
+
S.Exp1: 'e'
|
| 337 |
+
},
|
| 338 |
+
known_functions={
|
| 339 |
+
Add: 'plus',
|
| 340 |
+
exp: 'exp'
|
| 341 |
+
},
|
| 342 |
+
precision=3,
|
| 343 |
+
log_warn=w
|
| 344 |
+
) == '(plus 0 1 -1 (/ 1 2) (exp 1) p g)'
|
| 345 |
+
|
| 346 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 347 |
+
assert smtlib_code(
|
| 348 |
+
Add(S.Zero, S.One, S.NegativeOne, S.Half,
|
| 349 |
+
S.Exp1, S.Pi, S.GoldenRatio, evaluate=False),
|
| 350 |
+
known_constants={
|
| 351 |
+
S.Pi: 'p'
|
| 352 |
+
},
|
| 353 |
+
known_functions={
|
| 354 |
+
Add: 'plus',
|
| 355 |
+
exp: 'exp'
|
| 356 |
+
},
|
| 357 |
+
precision=3,
|
| 358 |
+
log_warn=w
|
| 359 |
+
) == '(plus 0 1 -1 (/ 1 2) (exp 1) p 1.62)'
|
| 360 |
+
|
| 361 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 362 |
+
assert smtlib_code(
|
| 363 |
+
Add(S.Zero, S.One, S.NegativeOne, S.Half,
|
| 364 |
+
S.Exp1, S.Pi, S.GoldenRatio, evaluate=False),
|
| 365 |
+
known_functions={Add: 'plus'},
|
| 366 |
+
precision=3,
|
| 367 |
+
log_warn=w
|
| 368 |
+
) == '(plus 0 1 -1 (/ 1 2) 2.72 3.14 1.62)'
|
| 369 |
+
|
| 370 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 371 |
+
assert smtlib_code(
|
| 372 |
+
Add(S.Zero, S.One, S.NegativeOne, S.Half,
|
| 373 |
+
S.Exp1, S.Pi, S.GoldenRatio, evaluate=False),
|
| 374 |
+
known_constants={S.Exp1: 'e'},
|
| 375 |
+
known_functions={Add: 'plus'},
|
| 376 |
+
precision=3,
|
| 377 |
+
log_warn=w
|
| 378 |
+
) == '(plus 0 1 -1 (/ 1 2) e 3.14 1.62)'
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
def test_boolean():
|
| 382 |
+
with _check_warns([]) as w:
|
| 383 |
+
assert smtlib_code(x & y, log_warn=w) == '(declare-const x Bool)\n' \
|
| 384 |
+
'(declare-const y Bool)\n' \
|
| 385 |
+
'(assert (and x y))'
|
| 386 |
+
assert smtlib_code(x | y, log_warn=w) == '(declare-const x Bool)\n' \
|
| 387 |
+
'(declare-const y Bool)\n' \
|
| 388 |
+
'(assert (or x y))'
|
| 389 |
+
assert smtlib_code(~x, log_warn=w) == '(declare-const x Bool)\n' \
|
| 390 |
+
'(assert (not x))'
|
| 391 |
+
assert smtlib_code(x & y & z, log_warn=w) == '(declare-const x Bool)\n' \
|
| 392 |
+
'(declare-const y Bool)\n' \
|
| 393 |
+
'(declare-const z Bool)\n' \
|
| 394 |
+
'(assert (and x y z))'
|
| 395 |
+
|
| 396 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w:
|
| 397 |
+
assert smtlib_code((x & ~y) | (z > 3), log_warn=w) == '(declare-const x Bool)\n' \
|
| 398 |
+
'(declare-const y Bool)\n' \
|
| 399 |
+
'(declare-const z Real)\n' \
|
| 400 |
+
'(assert (or (> z 3) (and x (not y))))'
|
| 401 |
+
|
| 402 |
+
f = Function('f')
|
| 403 |
+
g = Function('g')
|
| 404 |
+
h = Function('h')
|
| 405 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w:
|
| 406 |
+
assert smtlib_code(
|
| 407 |
+
[Gt(f(x), y),
|
| 408 |
+
Lt(y, g(z))],
|
| 409 |
+
symbol_table={
|
| 410 |
+
f: Callable[[bool], int], g: Callable[[bool], int],
|
| 411 |
+
}, log_warn=w
|
| 412 |
+
) == '(declare-const x Bool)\n' \
|
| 413 |
+
'(declare-const y Real)\n' \
|
| 414 |
+
'(declare-const z Bool)\n' \
|
| 415 |
+
'(declare-fun f (Bool) Int)\n' \
|
| 416 |
+
'(declare-fun g (Bool) Int)\n' \
|
| 417 |
+
'(assert (> (f x) y))\n' \
|
| 418 |
+
'(assert (< y (g z)))'
|
| 419 |
+
|
| 420 |
+
with _check_warns([]) as w:
|
| 421 |
+
assert smtlib_code(
|
| 422 |
+
[Eq(f(x), y),
|
| 423 |
+
Lt(y, g(z))],
|
| 424 |
+
symbol_table={
|
| 425 |
+
f: Callable[[bool], int], g: Callable[[bool], int],
|
| 426 |
+
}, log_warn=w
|
| 427 |
+
) == '(declare-const x Bool)\n' \
|
| 428 |
+
'(declare-const y Int)\n' \
|
| 429 |
+
'(declare-const z Bool)\n' \
|
| 430 |
+
'(declare-fun f (Bool) Int)\n' \
|
| 431 |
+
'(declare-fun g (Bool) Int)\n' \
|
| 432 |
+
'(assert (= (f x) y))\n' \
|
| 433 |
+
'(assert (< y (g z)))'
|
| 434 |
+
|
| 435 |
+
with _check_warns([]) as w:
|
| 436 |
+
assert smtlib_code(
|
| 437 |
+
[Eq(f(x), y),
|
| 438 |
+
Eq(g(f(x)), z),
|
| 439 |
+
Eq(h(g(f(x))), x)],
|
| 440 |
+
symbol_table={
|
| 441 |
+
f: Callable[[float], int],
|
| 442 |
+
g: Callable[[int], bool],
|
| 443 |
+
h: Callable[[bool], float]
|
| 444 |
+
},
|
| 445 |
+
log_warn=w
|
| 446 |
+
) == '(declare-const x Real)\n' \
|
| 447 |
+
'(declare-const y Int)\n' \
|
| 448 |
+
'(declare-const z Bool)\n' \
|
| 449 |
+
'(declare-fun f (Real) Int)\n' \
|
| 450 |
+
'(declare-fun g (Int) Bool)\n' \
|
| 451 |
+
'(declare-fun h (Bool) Real)\n' \
|
| 452 |
+
'(assert (= (f x) y))\n' \
|
| 453 |
+
'(assert (= (g (f x)) z))\n' \
|
| 454 |
+
'(assert (= (h (g (f x))) x))'
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
# todo: make smtlib_code support arrays
|
| 458 |
+
# def test_containers():
|
| 459 |
+
# assert julia_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \
|
| 460 |
+
# "Any[1, 2, 3, Any[4, 5, Any[6, 7]], 8, Any[9, 10], 11]"
|
| 461 |
+
# assert julia_code((1, 2, (3, 4))) == "(1, 2, (3, 4))"
|
| 462 |
+
# assert julia_code([1]) == "Any[1]"
|
| 463 |
+
# assert julia_code((1,)) == "(1,)"
|
| 464 |
+
# assert julia_code(Tuple(*[1, 2, 3])) == "(1, 2, 3)"
|
| 465 |
+
# assert julia_code((1, x * y, (3, x ** 2))) == "(1, x .* y, (3, x .^ 2))"
|
| 466 |
+
# # scalar, matrix, empty matrix and empty list
|
| 467 |
+
# assert julia_code((1, eye(3), Matrix(0, 0, []), [])) == "(1, [1 0 0;\n0 1 0;\n0 0 1], zeros(0, 0), Any[])"
|
| 468 |
+
|
| 469 |
+
def test_smtlib_piecewise():
|
| 470 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 471 |
+
assert smtlib_code(
|
| 472 |
+
Piecewise((x, x < 1),
|
| 473 |
+
(x ** 2, True)),
|
| 474 |
+
auto_declare=False,
|
| 475 |
+
log_warn=w
|
| 476 |
+
) == '(ite (< x 1) x (pow x 2))'
|
| 477 |
+
|
| 478 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 479 |
+
assert smtlib_code(
|
| 480 |
+
Piecewise((x ** 2, x < 1),
|
| 481 |
+
(x ** 3, x < 2),
|
| 482 |
+
(x ** 4, x < 3),
|
| 483 |
+
(x ** 5, True)),
|
| 484 |
+
auto_declare=False,
|
| 485 |
+
log_warn=w
|
| 486 |
+
) == '(ite (< x 1) (pow x 2) ' \
|
| 487 |
+
'(ite (< x 2) (pow x 3) ' \
|
| 488 |
+
'(ite (< x 3) (pow x 4) ' \
|
| 489 |
+
'(pow x 5))))'
|
| 490 |
+
|
| 491 |
+
# Check that Piecewise without a True (default) condition error
|
| 492 |
+
expr = Piecewise((x, x < 1), (x ** 2, x > 1), (sin(x), x > 0))
|
| 493 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 494 |
+
raises(AssertionError, lambda: smtlib_code(expr, log_warn=w))
|
| 495 |
+
|
| 496 |
+
|
| 497 |
+
def test_smtlib_piecewise_times_const():
|
| 498 |
+
pw = Piecewise((x, x < 1), (x ** 2, True))
|
| 499 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 500 |
+
assert smtlib_code(2 * pw, log_warn=w) == '(declare-const x Real)\n(* 2 (ite (< x 1) x (pow x 2)))'
|
| 501 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 502 |
+
assert smtlib_code(pw / x, log_warn=w) == '(declare-const x Real)\n(* (pow x -1) (ite (< x 1) x (pow x 2)))'
|
| 503 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 504 |
+
assert smtlib_code(pw / (x * y), log_warn=w) == '(declare-const x Real)\n(declare-const y Real)\n(* (pow x -1) (pow y -1) (ite (< x 1) x (pow x 2)))'
|
| 505 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 506 |
+
assert smtlib_code(pw / 3, log_warn=w) == '(declare-const x Real)\n(* (/ 1 3) (ite (< x 1) x (pow x 2)))'
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
# todo: make smtlib_code support arrays / matrices ?
|
| 510 |
+
# def test_smtlib_matrix_assign_to():
|
| 511 |
+
# A = Matrix([[1, 2, 3]])
|
| 512 |
+
# assert smtlib_code(A, assign_to='a') == "a = [1 2 3]"
|
| 513 |
+
# A = Matrix([[1, 2], [3, 4]])
|
| 514 |
+
# assert smtlib_code(A, assign_to='A') == "A = [1 2;\n3 4]"
|
| 515 |
+
|
| 516 |
+
# def test_julia_matrix_1x1():
|
| 517 |
+
# A = Matrix([[3]])
|
| 518 |
+
# B = MatrixSymbol('B', 1, 1)
|
| 519 |
+
# C = MatrixSymbol('C', 1, 2)
|
| 520 |
+
# assert julia_code(A, assign_to=B) == "B = [3]"
|
| 521 |
+
# raises(ValueError, lambda: julia_code(A, assign_to=C))
|
| 522 |
+
|
| 523 |
+
# def test_julia_matrix_elements():
|
| 524 |
+
# A = Matrix([[x, 2, x * y]])
|
| 525 |
+
# assert julia_code(A[0, 0] ** 2 + A[0, 1] + A[0, 2]) == "x .^ 2 + x .* y + 2"
|
| 526 |
+
# A = MatrixSymbol('AA', 1, 3)
|
| 527 |
+
# assert julia_code(A) == "AA"
|
| 528 |
+
# assert julia_code(A[0, 0] ** 2 + sin(A[0, 1]) + A[0, 2]) == \
|
| 529 |
+
# "sin(AA[1,2]) + AA[1,1] .^ 2 + AA[1,3]"
|
| 530 |
+
# assert julia_code(sum(A)) == "AA[1,1] + AA[1,2] + AA[1,3]"
|
| 531 |
+
|
| 532 |
+
def test_smtlib_boolean():
|
| 533 |
+
with _check_warns([]) as w:
|
| 534 |
+
assert smtlib_code(True, auto_assert=False, log_warn=w) == 'true'
|
| 535 |
+
assert smtlib_code(True, log_warn=w) == '(assert true)'
|
| 536 |
+
assert smtlib_code(S.true, log_warn=w) == '(assert true)'
|
| 537 |
+
assert smtlib_code(S.false, log_warn=w) == '(assert false)'
|
| 538 |
+
assert smtlib_code(False, log_warn=w) == '(assert false)'
|
| 539 |
+
assert smtlib_code(False, auto_assert=False, log_warn=w) == 'false'
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
def test_not_supported():
|
| 543 |
+
f = Function('f')
|
| 544 |
+
with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w:
|
| 545 |
+
raises(KeyError, lambda: smtlib_code(f(x).diff(x), symbol_table={f: Callable[[float], float]}, log_warn=w))
|
| 546 |
+
with _check_warns([_W.WILL_NOT_ASSERT]) as w:
|
| 547 |
+
raises(KeyError, lambda: smtlib_code(S.ComplexInfinity, log_warn=w))
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
def test_Float():
|
| 551 |
+
assert smtlib_code(0.0) == "0.0"
|
| 552 |
+
assert smtlib_code(0.000000000000000003) == '(* 3.0 (pow 10 -18))'
|
| 553 |
+
assert smtlib_code(5.3) == "5.3"
|
lib/python3.12/site-packages/sympy/printing/tests/test_str.py
ADDED
|
@@ -0,0 +1,1199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy import MatAdd
|
| 2 |
+
from sympy.algebras.quaternion import Quaternion
|
| 3 |
+
from sympy.assumptions.ask import Q
|
| 4 |
+
from sympy.calculus.accumulationbounds import AccumBounds
|
| 5 |
+
from sympy.combinatorics.partitions import Partition
|
| 6 |
+
from sympy.concrete.summations import (Sum, summation)
|
| 7 |
+
from sympy.core.add import Add
|
| 8 |
+
from sympy.core.containers import (Dict, Tuple)
|
| 9 |
+
from sympy.core.expr import UnevaluatedExpr, Expr
|
| 10 |
+
from sympy.core.function import (Derivative, Function, Lambda, Subs, WildFunction)
|
| 11 |
+
from sympy.core.mul import Mul
|
| 12 |
+
from sympy.core import (Catalan, EulerGamma, GoldenRatio, TribonacciConstant)
|
| 13 |
+
from sympy.core.numbers import (E, Float, I, Integer, Rational, nan, oo, pi, zoo)
|
| 14 |
+
from sympy.core.parameters import _exp_is_pow
|
| 15 |
+
from sympy.core.power import Pow
|
| 16 |
+
from sympy.core.relational import (Eq, Rel, Ne)
|
| 17 |
+
from sympy.core.singleton import S
|
| 18 |
+
from sympy.core.symbol import (Dummy, Symbol, Wild, symbols)
|
| 19 |
+
from sympy.functions.combinatorial.factorials import (factorial, factorial2, subfactorial)
|
| 20 |
+
from sympy.functions.elementary.complexes import Abs
|
| 21 |
+
from sympy.functions.elementary.exponential import exp
|
| 22 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 23 |
+
from sympy.functions.elementary.trigonometric import (cos, sin)
|
| 24 |
+
from sympy.functions.special.delta_functions import Heaviside
|
| 25 |
+
from sympy.functions.special.zeta_functions import zeta
|
| 26 |
+
from sympy.integrals.integrals import Integral
|
| 27 |
+
from sympy.logic.boolalg import (Equivalent, false, true, Xor)
|
| 28 |
+
from sympy.matrices.dense import Matrix
|
| 29 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 30 |
+
from sympy.matrices.expressions import Identity
|
| 31 |
+
from sympy.matrices.expressions.slice import MatrixSlice
|
| 32 |
+
from sympy.matrices import SparseMatrix
|
| 33 |
+
from sympy.polys.polytools import factor
|
| 34 |
+
from sympy.series.limits import Limit
|
| 35 |
+
from sympy.series.order import O
|
| 36 |
+
from sympy.sets.sets import (Complement, FiniteSet, Interval, SymmetricDifference)
|
| 37 |
+
from sympy.stats import (Covariance, Expectation, Probability, Variance)
|
| 38 |
+
from sympy.stats.rv import RandomSymbol
|
| 39 |
+
from sympy.external import import_module
|
| 40 |
+
from sympy.physics.control.lti import TransferFunction, Series, Parallel, \
|
| 41 |
+
Feedback, TransferFunctionMatrix, MIMOSeries, MIMOParallel, MIMOFeedback
|
| 42 |
+
from sympy.physics.units import second, joule
|
| 43 |
+
from sympy.polys import (Poly, rootof, RootSum, groebner, ring, field, ZZ, QQ,
|
| 44 |
+
ZZ_I, QQ_I, lex, grlex)
|
| 45 |
+
from sympy.geometry import Point, Circle, Polygon, Ellipse, Triangle
|
| 46 |
+
from sympy.tensor import NDimArray
|
| 47 |
+
from sympy.tensor.array.expressions.array_expressions import ArraySymbol, ArrayElement
|
| 48 |
+
|
| 49 |
+
from sympy.testing.pytest import raises, warns_deprecated_sympy
|
| 50 |
+
|
| 51 |
+
from sympy.printing import sstr, sstrrepr, StrPrinter
|
| 52 |
+
from sympy.physics.quantum.trace import Tr
|
| 53 |
+
|
| 54 |
+
x, y, z, w, t = symbols('x,y,z,w,t')
|
| 55 |
+
d = Dummy('d')
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def test_printmethod():
|
| 59 |
+
class R(Abs):
|
| 60 |
+
def _sympystr(self, printer):
|
| 61 |
+
return "foo(%s)" % printer._print(self.args[0])
|
| 62 |
+
assert sstr(R(x)) == "foo(x)"
|
| 63 |
+
|
| 64 |
+
class R(Abs):
|
| 65 |
+
def _sympystr(self, printer):
|
| 66 |
+
return "foo"
|
| 67 |
+
assert sstr(R(x)) == "foo"
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_Abs():
|
| 71 |
+
assert str(Abs(x)) == "Abs(x)"
|
| 72 |
+
assert str(Abs(Rational(1, 6))) == "1/6"
|
| 73 |
+
assert str(Abs(Rational(-1, 6))) == "1/6"
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_Add():
|
| 77 |
+
assert str(x + y) == "x + y"
|
| 78 |
+
assert str(x + 1) == "x + 1"
|
| 79 |
+
assert str(x + x**2) == "x**2 + x"
|
| 80 |
+
assert str(Add(0, 1, evaluate=False)) == "0 + 1"
|
| 81 |
+
assert str(Add(0, 0, 1, evaluate=False)) == "0 + 0 + 1"
|
| 82 |
+
assert str(1.0*x) == "1.0*x"
|
| 83 |
+
assert str(5 + x + y + x*y + x**2 + y**2) == "x**2 + x*y + x + y**2 + y + 5"
|
| 84 |
+
assert str(1 + x + x**2/2 + x**3/3) == "x**3/3 + x**2/2 + x + 1"
|
| 85 |
+
assert str(2*x - 7*x**2 + 2 + 3*y) == "-7*x**2 + 2*x + 3*y + 2"
|
| 86 |
+
assert str(x - y) == "x - y"
|
| 87 |
+
assert str(2 - x) == "2 - x"
|
| 88 |
+
assert str(x - 2) == "x - 2"
|
| 89 |
+
assert str(x - y - z - w) == "-w + x - y - z"
|
| 90 |
+
assert str(x - z*y**2*z*w) == "-w*y**2*z**2 + x"
|
| 91 |
+
assert str(x - 1*y*x*y) == "-x*y**2 + x"
|
| 92 |
+
assert str(sin(x).series(x, 0, 15)) == "x - x**3/6 + x**5/120 - x**7/5040 + x**9/362880 - x**11/39916800 + x**13/6227020800 + O(x**15)"
|
| 93 |
+
assert str(Add(Add(-w, x, evaluate=False), Add(-y, z, evaluate=False), evaluate=False)) == "(-w + x) + (-y + z)"
|
| 94 |
+
assert str(Add(Add(-x, -y, evaluate=False), -z, evaluate=False)) == "-z + (-x - y)"
|
| 95 |
+
assert str(Add(Add(Add(-x, -y, evaluate=False), -z, evaluate=False), -t, evaluate=False)) == "-t + (-z + (-x - y))"
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def test_Catalan():
|
| 99 |
+
assert str(Catalan) == "Catalan"
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def test_ComplexInfinity():
|
| 103 |
+
assert str(zoo) == "zoo"
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def test_Derivative():
|
| 107 |
+
assert str(Derivative(x, y)) == "Derivative(x, y)"
|
| 108 |
+
assert str(Derivative(x**2, x, evaluate=False)) == "Derivative(x**2, x)"
|
| 109 |
+
assert str(Derivative(
|
| 110 |
+
x**2/y, x, y, evaluate=False)) == "Derivative(x**2/y, x, y)"
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def test_dict():
|
| 114 |
+
assert str({1: 1 + x}) == sstr({1: 1 + x}) == "{1: x + 1}"
|
| 115 |
+
assert str({1: x**2, 2: y*x}) in ("{1: x**2, 2: x*y}", "{2: x*y, 1: x**2}")
|
| 116 |
+
assert sstr({1: x**2, 2: y*x}) == "{1: x**2, 2: x*y}"
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def test_Dict():
|
| 120 |
+
assert str(Dict({1: 1 + x})) == sstr({1: 1 + x}) == "{1: x + 1}"
|
| 121 |
+
assert str(Dict({1: x**2, 2: y*x})) in (
|
| 122 |
+
"{1: x**2, 2: x*y}", "{2: x*y, 1: x**2}")
|
| 123 |
+
assert sstr(Dict({1: x**2, 2: y*x})) == "{1: x**2, 2: x*y}"
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def test_Dummy():
|
| 127 |
+
assert str(d) == "_d"
|
| 128 |
+
assert str(d + x) == "_d + x"
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def test_EulerGamma():
|
| 132 |
+
assert str(EulerGamma) == "EulerGamma"
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def test_Exp():
|
| 136 |
+
assert str(E) == "E"
|
| 137 |
+
with _exp_is_pow(True):
|
| 138 |
+
assert str(exp(x)) == "E**x"
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_factorial():
|
| 142 |
+
n = Symbol('n', integer=True)
|
| 143 |
+
assert str(factorial(-2)) == "zoo"
|
| 144 |
+
assert str(factorial(0)) == "1"
|
| 145 |
+
assert str(factorial(7)) == "5040"
|
| 146 |
+
assert str(factorial(n)) == "factorial(n)"
|
| 147 |
+
assert str(factorial(2*n)) == "factorial(2*n)"
|
| 148 |
+
assert str(factorial(factorial(n))) == 'factorial(factorial(n))'
|
| 149 |
+
assert str(factorial(factorial2(n))) == 'factorial(factorial2(n))'
|
| 150 |
+
assert str(factorial2(factorial(n))) == 'factorial2(factorial(n))'
|
| 151 |
+
assert str(factorial2(factorial2(n))) == 'factorial2(factorial2(n))'
|
| 152 |
+
assert str(subfactorial(3)) == "2"
|
| 153 |
+
assert str(subfactorial(n)) == "subfactorial(n)"
|
| 154 |
+
assert str(subfactorial(2*n)) == "subfactorial(2*n)"
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def test_Function():
|
| 158 |
+
f = Function('f')
|
| 159 |
+
fx = f(x)
|
| 160 |
+
w = WildFunction('w')
|
| 161 |
+
assert str(f) == "f"
|
| 162 |
+
assert str(fx) == "f(x)"
|
| 163 |
+
assert str(w) == "w_"
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def test_Geometry():
|
| 167 |
+
assert sstr(Point(0, 0)) == 'Point2D(0, 0)'
|
| 168 |
+
assert sstr(Circle(Point(0, 0), 3)) == 'Circle(Point2D(0, 0), 3)'
|
| 169 |
+
assert sstr(Ellipse(Point(1, 2), 3, 4)) == 'Ellipse(Point2D(1, 2), 3, 4)'
|
| 170 |
+
assert sstr(Triangle(Point(1, 1), Point(7, 8), Point(0, -1))) == \
|
| 171 |
+
'Triangle(Point2D(1, 1), Point2D(7, 8), Point2D(0, -1))'
|
| 172 |
+
assert sstr(Polygon(Point(5, 6), Point(-2, -3), Point(0, 0), Point(4, 7))) == \
|
| 173 |
+
'Polygon(Point2D(5, 6), Point2D(-2, -3), Point2D(0, 0), Point2D(4, 7))'
|
| 174 |
+
assert sstr(Triangle(Point(0, 0), Point(1, 0), Point(0, 1)), sympy_integers=True) == \
|
| 175 |
+
'Triangle(Point2D(S(0), S(0)), Point2D(S(1), S(0)), Point2D(S(0), S(1)))'
|
| 176 |
+
assert sstr(Ellipse(Point(1, 2), 3, 4), sympy_integers=True) == \
|
| 177 |
+
'Ellipse(Point2D(S(1), S(2)), S(3), S(4))'
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def test_GoldenRatio():
|
| 181 |
+
assert str(GoldenRatio) == "GoldenRatio"
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def test_Heaviside():
|
| 185 |
+
assert str(Heaviside(x)) == str(Heaviside(x, S.Half)) == "Heaviside(x)"
|
| 186 |
+
assert str(Heaviside(x, 1)) == "Heaviside(x, 1)"
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
def test_TribonacciConstant():
|
| 190 |
+
assert str(TribonacciConstant) == "TribonacciConstant"
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def test_ImaginaryUnit():
|
| 194 |
+
assert str(I) == "I"
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
def test_Infinity():
|
| 198 |
+
assert str(oo) == "oo"
|
| 199 |
+
assert str(oo*I) == "oo*I"
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def test_Integer():
|
| 203 |
+
assert str(Integer(-1)) == "-1"
|
| 204 |
+
assert str(Integer(1)) == "1"
|
| 205 |
+
assert str(Integer(-3)) == "-3"
|
| 206 |
+
assert str(Integer(0)) == "0"
|
| 207 |
+
assert str(Integer(25)) == "25"
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def test_Integral():
|
| 211 |
+
assert str(Integral(sin(x), y)) == "Integral(sin(x), y)"
|
| 212 |
+
assert str(Integral(sin(x), (y, 0, 1))) == "Integral(sin(x), (y, 0, 1))"
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def test_Interval():
|
| 216 |
+
n = (S.NegativeInfinity, 1, 2, S.Infinity)
|
| 217 |
+
for i in range(len(n)):
|
| 218 |
+
for j in range(i + 1, len(n)):
|
| 219 |
+
for l in (True, False):
|
| 220 |
+
for r in (True, False):
|
| 221 |
+
ival = Interval(n[i], n[j], l, r)
|
| 222 |
+
assert S(str(ival)) == ival
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def test_AccumBounds():
|
| 226 |
+
a = Symbol('a', real=True)
|
| 227 |
+
assert str(AccumBounds(0, a)) == "AccumBounds(0, a)"
|
| 228 |
+
assert str(AccumBounds(0, 1)) == "AccumBounds(0, 1)"
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def test_Lambda():
|
| 232 |
+
assert str(Lambda(d, d**2)) == "Lambda(_d, _d**2)"
|
| 233 |
+
# issue 2908
|
| 234 |
+
assert str(Lambda((), 1)) == "Lambda((), 1)"
|
| 235 |
+
assert str(Lambda((), x)) == "Lambda((), x)"
|
| 236 |
+
assert str(Lambda((x, y), x+y)) == "Lambda((x, y), x + y)"
|
| 237 |
+
assert str(Lambda(((x, y),), x+y)) == "Lambda(((x, y),), x + y)"
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
def test_Limit():
|
| 241 |
+
assert str(Limit(sin(x)/x, x, y)) == "Limit(sin(x)/x, x, y, dir='+')"
|
| 242 |
+
assert str(Limit(1/x, x, 0)) == "Limit(1/x, x, 0, dir='+')"
|
| 243 |
+
assert str(
|
| 244 |
+
Limit(sin(x)/x, x, y, dir="-")) == "Limit(sin(x)/x, x, y, dir='-')"
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def test_list():
|
| 248 |
+
assert str([x]) == sstr([x]) == "[x]"
|
| 249 |
+
assert str([x**2, x*y + 1]) == sstr([x**2, x*y + 1]) == "[x**2, x*y + 1]"
|
| 250 |
+
assert str([x**2, [y + x]]) == sstr([x**2, [y + x]]) == "[x**2, [x + y]]"
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def test_Matrix_str():
|
| 254 |
+
M = Matrix([[x**+1, 1], [y, x + y]])
|
| 255 |
+
assert str(M) == "Matrix([[x, 1], [y, x + y]])"
|
| 256 |
+
assert sstr(M) == "Matrix([\n[x, 1],\n[y, x + y]])"
|
| 257 |
+
M = Matrix([[1]])
|
| 258 |
+
assert str(M) == sstr(M) == "Matrix([[1]])"
|
| 259 |
+
M = Matrix([[1, 2]])
|
| 260 |
+
assert str(M) == sstr(M) == "Matrix([[1, 2]])"
|
| 261 |
+
M = Matrix()
|
| 262 |
+
assert str(M) == sstr(M) == "Matrix(0, 0, [])"
|
| 263 |
+
M = Matrix(0, 1, lambda i, j: 0)
|
| 264 |
+
assert str(M) == sstr(M) == "Matrix(0, 1, [])"
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
def test_Mul():
|
| 268 |
+
assert str(x/y) == "x/y"
|
| 269 |
+
assert str(y/x) == "y/x"
|
| 270 |
+
assert str(x/y/z) == "x/(y*z)"
|
| 271 |
+
assert str((x + 1)/(y + 2)) == "(x + 1)/(y + 2)"
|
| 272 |
+
assert str(2*x/3) == '2*x/3'
|
| 273 |
+
assert str(-2*x/3) == '-2*x/3'
|
| 274 |
+
assert str(-1.0*x) == '-1.0*x'
|
| 275 |
+
assert str(1.0*x) == '1.0*x'
|
| 276 |
+
assert str(Mul(0, 1, evaluate=False)) == '0*1'
|
| 277 |
+
assert str(Mul(1, 0, evaluate=False)) == '1*0'
|
| 278 |
+
assert str(Mul(1, 1, evaluate=False)) == '1*1'
|
| 279 |
+
assert str(Mul(1, 1, 1, evaluate=False)) == '1*1*1'
|
| 280 |
+
assert str(Mul(1, 2, evaluate=False)) == '1*2'
|
| 281 |
+
assert str(Mul(1, S.Half, evaluate=False)) == '1*(1/2)'
|
| 282 |
+
assert str(Mul(1, 1, S.Half, evaluate=False)) == '1*1*(1/2)'
|
| 283 |
+
assert str(Mul(1, 1, 2, 3, x, evaluate=False)) == '1*1*2*3*x'
|
| 284 |
+
assert str(Mul(1, -1, evaluate=False)) == '1*(-1)'
|
| 285 |
+
assert str(Mul(-1, 1, evaluate=False)) == '-1*1'
|
| 286 |
+
assert str(Mul(4, 3, 2, 1, 0, y, x, evaluate=False)) == '4*3*2*1*0*y*x'
|
| 287 |
+
assert str(Mul(4, 3, 2, 1+z, 0, y, x, evaluate=False)) == '4*3*2*(z + 1)*0*y*x'
|
| 288 |
+
assert str(Mul(Rational(2, 3), Rational(5, 7), evaluate=False)) == '(2/3)*(5/7)'
|
| 289 |
+
# For issue 14160
|
| 290 |
+
assert str(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False),
|
| 291 |
+
evaluate=False)) == '-2*x/(y*y)'
|
| 292 |
+
# issue 21537
|
| 293 |
+
assert str(Mul(x, Pow(1/y, -1, evaluate=False), evaluate=False)) == 'x/(1/y)'
|
| 294 |
+
|
| 295 |
+
# Issue 24108
|
| 296 |
+
from sympy.core.parameters import evaluate
|
| 297 |
+
with evaluate(False):
|
| 298 |
+
assert str(Mul(Pow(Integer(2), Integer(-1)), Add(Integer(-1), Mul(Integer(-1), Integer(1))))) == "(-1 - 1*1)/2"
|
| 299 |
+
|
| 300 |
+
class CustomClass1(Expr):
|
| 301 |
+
is_commutative = True
|
| 302 |
+
|
| 303 |
+
class CustomClass2(Expr):
|
| 304 |
+
is_commutative = True
|
| 305 |
+
cc1 = CustomClass1()
|
| 306 |
+
cc2 = CustomClass2()
|
| 307 |
+
assert str(Rational(2)*cc1) == '2*CustomClass1()'
|
| 308 |
+
assert str(cc1*Rational(2)) == '2*CustomClass1()'
|
| 309 |
+
assert str(cc1*Float("1.5")) == '1.5*CustomClass1()'
|
| 310 |
+
assert str(cc2*Rational(2)) == '2*CustomClass2()'
|
| 311 |
+
assert str(cc2*Rational(2)*cc1) == '2*CustomClass1()*CustomClass2()'
|
| 312 |
+
assert str(cc1*Rational(2)*cc2) == '2*CustomClass1()*CustomClass2()'
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
def test_NaN():
|
| 316 |
+
assert str(nan) == "nan"
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
def test_NegativeInfinity():
|
| 320 |
+
assert str(-oo) == "-oo"
|
| 321 |
+
|
| 322 |
+
def test_Order():
|
| 323 |
+
assert str(O(x)) == "O(x)"
|
| 324 |
+
assert str(O(x**2)) == "O(x**2)"
|
| 325 |
+
assert str(O(x*y)) == "O(x*y, x, y)"
|
| 326 |
+
assert str(O(x, x)) == "O(x)"
|
| 327 |
+
assert str(O(x, (x, 0))) == "O(x)"
|
| 328 |
+
assert str(O(x, (x, oo))) == "O(x, (x, oo))"
|
| 329 |
+
assert str(O(x, x, y)) == "O(x, x, y)"
|
| 330 |
+
assert str(O(x, x, y)) == "O(x, x, y)"
|
| 331 |
+
assert str(O(x, (x, oo), (y, oo))) == "O(x, (x, oo), (y, oo))"
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def test_Permutation_Cycle():
|
| 335 |
+
from sympy.combinatorics import Permutation, Cycle
|
| 336 |
+
|
| 337 |
+
# general principle: economically, canonically show all moved elements
|
| 338 |
+
# and the size of the permutation.
|
| 339 |
+
|
| 340 |
+
for p, s in [
|
| 341 |
+
(Cycle(),
|
| 342 |
+
'()'),
|
| 343 |
+
(Cycle(2),
|
| 344 |
+
'(2)'),
|
| 345 |
+
(Cycle(2, 1),
|
| 346 |
+
'(1 2)'),
|
| 347 |
+
(Cycle(1, 2)(5)(6, 7)(10),
|
| 348 |
+
'(1 2)(6 7)(10)'),
|
| 349 |
+
(Cycle(3, 4)(1, 2)(3, 4),
|
| 350 |
+
'(1 2)(4)'),
|
| 351 |
+
]:
|
| 352 |
+
assert sstr(p) == s
|
| 353 |
+
|
| 354 |
+
for p, s in [
|
| 355 |
+
(Permutation([]),
|
| 356 |
+
'Permutation([])'),
|
| 357 |
+
(Permutation([], size=1),
|
| 358 |
+
'Permutation([0])'),
|
| 359 |
+
(Permutation([], size=2),
|
| 360 |
+
'Permutation([0, 1])'),
|
| 361 |
+
(Permutation([], size=10),
|
| 362 |
+
'Permutation([], size=10)'),
|
| 363 |
+
(Permutation([1, 0, 2]),
|
| 364 |
+
'Permutation([1, 0, 2])'),
|
| 365 |
+
(Permutation([1, 0, 2, 3, 4, 5]),
|
| 366 |
+
'Permutation([1, 0], size=6)'),
|
| 367 |
+
(Permutation([1, 0, 2, 3, 4, 5], size=10),
|
| 368 |
+
'Permutation([1, 0], size=10)'),
|
| 369 |
+
]:
|
| 370 |
+
assert sstr(p, perm_cyclic=False) == s
|
| 371 |
+
|
| 372 |
+
for p, s in [
|
| 373 |
+
(Permutation([]),
|
| 374 |
+
'()'),
|
| 375 |
+
(Permutation([], size=1),
|
| 376 |
+
'(0)'),
|
| 377 |
+
(Permutation([], size=2),
|
| 378 |
+
'(1)'),
|
| 379 |
+
(Permutation([], size=10),
|
| 380 |
+
'(9)'),
|
| 381 |
+
(Permutation([1, 0, 2]),
|
| 382 |
+
'(2)(0 1)'),
|
| 383 |
+
(Permutation([1, 0, 2, 3, 4, 5]),
|
| 384 |
+
'(5)(0 1)'),
|
| 385 |
+
(Permutation([1, 0, 2, 3, 4, 5], size=10),
|
| 386 |
+
'(9)(0 1)'),
|
| 387 |
+
(Permutation([0, 1, 3, 2, 4, 5], size=10),
|
| 388 |
+
'(9)(2 3)'),
|
| 389 |
+
]:
|
| 390 |
+
assert sstr(p) == s
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
with warns_deprecated_sympy():
|
| 394 |
+
old_print_cyclic = Permutation.print_cyclic
|
| 395 |
+
Permutation.print_cyclic = False
|
| 396 |
+
assert sstr(Permutation([1, 0, 2])) == 'Permutation([1, 0, 2])'
|
| 397 |
+
Permutation.print_cyclic = old_print_cyclic
|
| 398 |
+
|
| 399 |
+
def test_Pi():
|
| 400 |
+
assert str(pi) == "pi"
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
def test_Poly():
|
| 404 |
+
assert str(Poly(0, x)) == "Poly(0, x, domain='ZZ')"
|
| 405 |
+
assert str(Poly(1, x)) == "Poly(1, x, domain='ZZ')"
|
| 406 |
+
assert str(Poly(x, x)) == "Poly(x, x, domain='ZZ')"
|
| 407 |
+
|
| 408 |
+
assert str(Poly(2*x + 1, x)) == "Poly(2*x + 1, x, domain='ZZ')"
|
| 409 |
+
assert str(Poly(2*x - 1, x)) == "Poly(2*x - 1, x, domain='ZZ')"
|
| 410 |
+
|
| 411 |
+
assert str(Poly(-1, x)) == "Poly(-1, x, domain='ZZ')"
|
| 412 |
+
assert str(Poly(-x, x)) == "Poly(-x, x, domain='ZZ')"
|
| 413 |
+
|
| 414 |
+
assert str(Poly(-2*x + 1, x)) == "Poly(-2*x + 1, x, domain='ZZ')"
|
| 415 |
+
assert str(Poly(-2*x - 1, x)) == "Poly(-2*x - 1, x, domain='ZZ')"
|
| 416 |
+
|
| 417 |
+
assert str(Poly(x - 1, x)) == "Poly(x - 1, x, domain='ZZ')"
|
| 418 |
+
assert str(Poly(2*x + x**5, x)) == "Poly(x**5 + 2*x, x, domain='ZZ')"
|
| 419 |
+
|
| 420 |
+
assert str(Poly(3**(2*x), 3**x)) == "Poly((3**x)**2, 3**x, domain='ZZ')"
|
| 421 |
+
assert str(Poly((x**2)**x)) == "Poly(((x**2)**x), (x**2)**x, domain='ZZ')"
|
| 422 |
+
|
| 423 |
+
assert str(Poly((x + y)**3, (x + y), expand=False)
|
| 424 |
+
) == "Poly((x + y)**3, x + y, domain='ZZ')"
|
| 425 |
+
assert str(Poly((x - 1)**2, (x - 1), expand=False)
|
| 426 |
+
) == "Poly((x - 1)**2, x - 1, domain='ZZ')"
|
| 427 |
+
|
| 428 |
+
assert str(
|
| 429 |
+
Poly(x**2 + 1 + y, x)) == "Poly(x**2 + y + 1, x, domain='ZZ[y]')"
|
| 430 |
+
assert str(
|
| 431 |
+
Poly(x**2 - 1 + y, x)) == "Poly(x**2 + y - 1, x, domain='ZZ[y]')"
|
| 432 |
+
|
| 433 |
+
assert str(Poly(x**2 + I*x, x)) == "Poly(x**2 + I*x, x, domain='ZZ_I')"
|
| 434 |
+
assert str(Poly(x**2 - I*x, x)) == "Poly(x**2 - I*x, x, domain='ZZ_I')"
|
| 435 |
+
|
| 436 |
+
assert str(Poly(-x*y*z + x*y - 1, x, y, z)
|
| 437 |
+
) == "Poly(-x*y*z + x*y - 1, x, y, z, domain='ZZ')"
|
| 438 |
+
assert str(Poly(-w*x**21*y**7*z + (1 + w)*z**3 - 2*x*z + 1, x, y, z)) == \
|
| 439 |
+
"Poly(-w*x**21*y**7*z - 2*x*z + (w + 1)*z**3 + 1, x, y, z, domain='ZZ[w]')"
|
| 440 |
+
|
| 441 |
+
assert str(Poly(x**2 + 1, x, modulus=2)) == "Poly(x**2 + 1, x, modulus=2)"
|
| 442 |
+
assert str(Poly(2*x**2 + 3*x + 4, x, modulus=17)) == "Poly(2*x**2 + 3*x + 4, x, modulus=17)"
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
def test_PolyRing():
|
| 446 |
+
assert str(ring("x", ZZ, lex)[0]) == "Polynomial ring in x over ZZ with lex order"
|
| 447 |
+
assert str(ring("x,y", QQ, grlex)[0]) == "Polynomial ring in x, y over QQ with grlex order"
|
| 448 |
+
assert str(ring("x,y,z", ZZ["t"], lex)[0]) == "Polynomial ring in x, y, z over ZZ[t] with lex order"
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
def test_FracField():
|
| 452 |
+
assert str(field("x", ZZ, lex)[0]) == "Rational function field in x over ZZ with lex order"
|
| 453 |
+
assert str(field("x,y", QQ, grlex)[0]) == "Rational function field in x, y over QQ with grlex order"
|
| 454 |
+
assert str(field("x,y,z", ZZ["t"], lex)[0]) == "Rational function field in x, y, z over ZZ[t] with lex order"
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def test_PolyElement():
|
| 458 |
+
Ruv, u,v = ring("u,v", ZZ)
|
| 459 |
+
Rxyz, x,y,z = ring("x,y,z", Ruv)
|
| 460 |
+
Rx_zzi, xz = ring("x", ZZ_I)
|
| 461 |
+
|
| 462 |
+
assert str(x - x) == "0"
|
| 463 |
+
assert str(x - 1) == "x - 1"
|
| 464 |
+
assert str(x + 1) == "x + 1"
|
| 465 |
+
assert str(x**2) == "x**2"
|
| 466 |
+
assert str(x**(-2)) == "x**(-2)"
|
| 467 |
+
assert str(x**QQ(1, 2)) == "x**(1/2)"
|
| 468 |
+
|
| 469 |
+
assert str((u**2 + 3*u*v + 1)*x**2*y + u + 1) == "(u**2 + 3*u*v + 1)*x**2*y + u + 1"
|
| 470 |
+
assert str((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x) == "(u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x"
|
| 471 |
+
assert str((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x + 1) == "(u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x + 1"
|
| 472 |
+
assert str((-u**2 + 3*u*v - 1)*x**2*y - (u + 1)*x - 1) == "-(u**2 - 3*u*v + 1)*x**2*y - (u + 1)*x - 1"
|
| 473 |
+
|
| 474 |
+
assert str(-(v**2 + v + 1)*x + 3*u*v + 1) == "-(v**2 + v + 1)*x + 3*u*v + 1"
|
| 475 |
+
assert str(-(v**2 + v + 1)*x - 3*u*v + 1) == "-(v**2 + v + 1)*x - 3*u*v + 1"
|
| 476 |
+
|
| 477 |
+
assert str((1+I)*xz + 2) == "(1 + 1*I)*x + (2 + 0*I)"
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
def test_FracElement():
|
| 481 |
+
Fuv, u,v = field("u,v", ZZ)
|
| 482 |
+
Fxyzt, x,y,z,t = field("x,y,z,t", Fuv)
|
| 483 |
+
Rx_zzi, xz = field("x", QQ_I)
|
| 484 |
+
i = QQ_I(0, 1)
|
| 485 |
+
|
| 486 |
+
assert str(x - x) == "0"
|
| 487 |
+
assert str(x - 1) == "x - 1"
|
| 488 |
+
assert str(x + 1) == "x + 1"
|
| 489 |
+
|
| 490 |
+
assert str(x/3) == "x/3"
|
| 491 |
+
assert str(x/z) == "x/z"
|
| 492 |
+
assert str(x*y/z) == "x*y/z"
|
| 493 |
+
assert str(x/(z*t)) == "x/(z*t)"
|
| 494 |
+
assert str(x*y/(z*t)) == "x*y/(z*t)"
|
| 495 |
+
|
| 496 |
+
assert str((x - 1)/y) == "(x - 1)/y"
|
| 497 |
+
assert str((x + 1)/y) == "(x + 1)/y"
|
| 498 |
+
assert str((-x - 1)/y) == "(-x - 1)/y"
|
| 499 |
+
assert str((x + 1)/(y*z)) == "(x + 1)/(y*z)"
|
| 500 |
+
assert str(-y/(x + 1)) == "-y/(x + 1)"
|
| 501 |
+
assert str(y*z/(x + 1)) == "y*z/(x + 1)"
|
| 502 |
+
|
| 503 |
+
assert str(((u + 1)*x*y + 1)/((v - 1)*z - 1)) == "((u + 1)*x*y + 1)/((v - 1)*z - 1)"
|
| 504 |
+
assert str(((u + 1)*x*y + 1)/((v - 1)*z - t*u*v - 1)) == "((u + 1)*x*y + 1)/((v - 1)*z - u*v*t - 1)"
|
| 505 |
+
|
| 506 |
+
assert str((1+i)/xz) == "(1 + 1*I)/x"
|
| 507 |
+
assert str(((1+i)*xz - i)/xz) == "((1 + 1*I)*x + (0 + -1*I))/x"
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
def test_GaussianInteger():
|
| 511 |
+
assert str(ZZ_I(1, 0)) == "1"
|
| 512 |
+
assert str(ZZ_I(-1, 0)) == "-1"
|
| 513 |
+
assert str(ZZ_I(0, 1)) == "I"
|
| 514 |
+
assert str(ZZ_I(0, -1)) == "-I"
|
| 515 |
+
assert str(ZZ_I(0, 2)) == "2*I"
|
| 516 |
+
assert str(ZZ_I(0, -2)) == "-2*I"
|
| 517 |
+
assert str(ZZ_I(1, 1)) == "1 + I"
|
| 518 |
+
assert str(ZZ_I(-1, -1)) == "-1 - I"
|
| 519 |
+
assert str(ZZ_I(-1, -2)) == "-1 - 2*I"
|
| 520 |
+
|
| 521 |
+
|
| 522 |
+
def test_GaussianRational():
|
| 523 |
+
assert str(QQ_I(1, 0)) == "1"
|
| 524 |
+
assert str(QQ_I(QQ(2, 3), 0)) == "2/3"
|
| 525 |
+
assert str(QQ_I(0, QQ(2, 3))) == "2*I/3"
|
| 526 |
+
assert str(QQ_I(QQ(1, 2), QQ(-2, 3))) == "1/2 - 2*I/3"
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
def test_Pow():
|
| 530 |
+
assert str(x**-1) == "1/x"
|
| 531 |
+
assert str(x**-2) == "x**(-2)"
|
| 532 |
+
assert str(x**2) == "x**2"
|
| 533 |
+
assert str((x + y)**-1) == "1/(x + y)"
|
| 534 |
+
assert str((x + y)**-2) == "(x + y)**(-2)"
|
| 535 |
+
assert str((x + y)**2) == "(x + y)**2"
|
| 536 |
+
assert str((x + y)**(1 + x)) == "(x + y)**(x + 1)"
|
| 537 |
+
assert str(x**Rational(1, 3)) == "x**(1/3)"
|
| 538 |
+
assert str(1/x**Rational(1, 3)) == "x**(-1/3)"
|
| 539 |
+
assert str(sqrt(sqrt(x))) == "x**(1/4)"
|
| 540 |
+
# not the same as x**-1
|
| 541 |
+
assert str(x**-1.0) == 'x**(-1.0)'
|
| 542 |
+
# see issue #2860
|
| 543 |
+
assert str(Pow(S(2), -1.0, evaluate=False)) == '2**(-1.0)'
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
def test_sqrt():
|
| 547 |
+
assert str(sqrt(x)) == "sqrt(x)"
|
| 548 |
+
assert str(sqrt(x**2)) == "sqrt(x**2)"
|
| 549 |
+
assert str(1/sqrt(x)) == "1/sqrt(x)"
|
| 550 |
+
assert str(1/sqrt(x**2)) == "1/sqrt(x**2)"
|
| 551 |
+
assert str(y/sqrt(x)) == "y/sqrt(x)"
|
| 552 |
+
assert str(x**0.5) == "x**0.5"
|
| 553 |
+
assert str(1/x**0.5) == "x**(-0.5)"
|
| 554 |
+
|
| 555 |
+
|
| 556 |
+
def test_Rational():
|
| 557 |
+
n1 = Rational(1, 4)
|
| 558 |
+
n2 = Rational(1, 3)
|
| 559 |
+
n3 = Rational(2, 4)
|
| 560 |
+
n4 = Rational(2, -4)
|
| 561 |
+
n5 = Rational(0)
|
| 562 |
+
n7 = Rational(3)
|
| 563 |
+
n8 = Rational(-3)
|
| 564 |
+
assert str(n1*n2) == "1/12"
|
| 565 |
+
assert str(n1*n2) == "1/12"
|
| 566 |
+
assert str(n3) == "1/2"
|
| 567 |
+
assert str(n1*n3) == "1/8"
|
| 568 |
+
assert str(n1 + n3) == "3/4"
|
| 569 |
+
assert str(n1 + n2) == "7/12"
|
| 570 |
+
assert str(n1 + n4) == "-1/4"
|
| 571 |
+
assert str(n4*n4) == "1/4"
|
| 572 |
+
assert str(n4 + n2) == "-1/6"
|
| 573 |
+
assert str(n4 + n5) == "-1/2"
|
| 574 |
+
assert str(n4*n5) == "0"
|
| 575 |
+
assert str(n3 + n4) == "0"
|
| 576 |
+
assert str(n1**n7) == "1/64"
|
| 577 |
+
assert str(n2**n7) == "1/27"
|
| 578 |
+
assert str(n2**n8) == "27"
|
| 579 |
+
assert str(n7**n8) == "1/27"
|
| 580 |
+
assert str(Rational("-25")) == "-25"
|
| 581 |
+
assert str(Rational("1.25")) == "5/4"
|
| 582 |
+
assert str(Rational("-2.6e-2")) == "-13/500"
|
| 583 |
+
assert str(S("25/7")) == "25/7"
|
| 584 |
+
assert str(S("-123/569")) == "-123/569"
|
| 585 |
+
assert str(S("0.1[23]", rational=1)) == "61/495"
|
| 586 |
+
assert str(S("5.1[666]", rational=1)) == "31/6"
|
| 587 |
+
assert str(S("-5.1[666]", rational=1)) == "-31/6"
|
| 588 |
+
assert str(S("0.[9]", rational=1)) == "1"
|
| 589 |
+
assert str(S("-0.[9]", rational=1)) == "-1"
|
| 590 |
+
|
| 591 |
+
assert str(sqrt(Rational(1, 4))) == "1/2"
|
| 592 |
+
assert str(sqrt(Rational(1, 36))) == "1/6"
|
| 593 |
+
|
| 594 |
+
assert str((123**25) ** Rational(1, 25)) == "123"
|
| 595 |
+
assert str((123**25 + 1)**Rational(1, 25)) != "123"
|
| 596 |
+
assert str((123**25 - 1)**Rational(1, 25)) != "123"
|
| 597 |
+
assert str((123**25 - 1)**Rational(1, 25)) != "122"
|
| 598 |
+
|
| 599 |
+
assert str(sqrt(Rational(81, 36))**3) == "27/8"
|
| 600 |
+
assert str(1/sqrt(Rational(81, 36))**3) == "8/27"
|
| 601 |
+
|
| 602 |
+
assert str(sqrt(-4)) == str(2*I)
|
| 603 |
+
assert str(2**Rational(1, 10**10)) == "2**(1/10000000000)"
|
| 604 |
+
|
| 605 |
+
assert sstr(Rational(2, 3), sympy_integers=True) == "S(2)/3"
|
| 606 |
+
x = Symbol("x")
|
| 607 |
+
assert sstr(x**Rational(2, 3), sympy_integers=True) == "x**(S(2)/3)"
|
| 608 |
+
assert sstr(Eq(x, Rational(2, 3)), sympy_integers=True) == "Eq(x, S(2)/3)"
|
| 609 |
+
assert sstr(Limit(x, x, Rational(7, 2)), sympy_integers=True) == \
|
| 610 |
+
"Limit(x, x, S(7)/2, dir='+')"
|
| 611 |
+
|
| 612 |
+
|
| 613 |
+
def test_Float():
|
| 614 |
+
# NOTE dps is the whole number of decimal digits
|
| 615 |
+
assert str(Float('1.23', dps=1 + 2)) == '1.23'
|
| 616 |
+
assert str(Float('1.23456789', dps=1 + 8)) == '1.23456789'
|
| 617 |
+
assert str(
|
| 618 |
+
Float('1.234567890123456789', dps=1 + 18)) == '1.234567890123456789'
|
| 619 |
+
assert str(pi.evalf(1 + 2)) == '3.14'
|
| 620 |
+
assert str(pi.evalf(1 + 14)) == '3.14159265358979'
|
| 621 |
+
assert str(pi.evalf(1 + 64)) == ('3.141592653589793238462643383279'
|
| 622 |
+
'5028841971693993751058209749445923')
|
| 623 |
+
assert str(pi.round(-1)) == '0.0'
|
| 624 |
+
assert str((pi**400 - (pi**400).round(1)).n(2)) == '-0.e+88'
|
| 625 |
+
assert sstr(Float("100"), full_prec=False, min=-2, max=2) == '1.0e+2'
|
| 626 |
+
assert sstr(Float("100"), full_prec=False, min=-2, max=3) == '100.0'
|
| 627 |
+
assert sstr(Float("0.1"), full_prec=False, min=-2, max=3) == '0.1'
|
| 628 |
+
assert sstr(Float("0.099"), min=-2, max=3) == '9.90000000000000e-2'
|
| 629 |
+
|
| 630 |
+
|
| 631 |
+
def test_Relational():
|
| 632 |
+
assert str(Rel(x, y, "<")) == "x < y"
|
| 633 |
+
assert str(Rel(x + y, y, "==")) == "Eq(x + y, y)"
|
| 634 |
+
assert str(Rel(x, y, "!=")) == "Ne(x, y)"
|
| 635 |
+
assert str(Eq(x, 1) | Eq(x, 2)) == "Eq(x, 1) | Eq(x, 2)"
|
| 636 |
+
assert str(Ne(x, 1) & Ne(x, 2)) == "Ne(x, 1) & Ne(x, 2)"
|
| 637 |
+
|
| 638 |
+
|
| 639 |
+
def test_AppliedBinaryRelation():
|
| 640 |
+
assert str(Q.eq(x, y)) == "Q.eq(x, y)"
|
| 641 |
+
assert str(Q.ne(x, y)) == "Q.ne(x, y)"
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
def test_CRootOf():
|
| 645 |
+
assert str(rootof(x**5 + 2*x - 1, 0)) == "CRootOf(x**5 + 2*x - 1, 0)"
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
def test_RootSum():
|
| 649 |
+
f = x**5 + 2*x - 1
|
| 650 |
+
|
| 651 |
+
assert str(
|
| 652 |
+
RootSum(f, Lambda(z, z), auto=False)) == "RootSum(x**5 + 2*x - 1)"
|
| 653 |
+
assert str(RootSum(f, Lambda(
|
| 654 |
+
z, z**2), auto=False)) == "RootSum(x**5 + 2*x - 1, Lambda(z, z**2))"
|
| 655 |
+
|
| 656 |
+
|
| 657 |
+
def test_GroebnerBasis():
|
| 658 |
+
assert str(groebner(
|
| 659 |
+
[], x, y)) == "GroebnerBasis([], x, y, domain='ZZ', order='lex')"
|
| 660 |
+
|
| 661 |
+
F = [x**2 - 3*y - x + 1, y**2 - 2*x + y - 1]
|
| 662 |
+
|
| 663 |
+
assert str(groebner(F, order='grlex')) == \
|
| 664 |
+
"GroebnerBasis([x**2 - x - 3*y + 1, y**2 - 2*x + y - 1], x, y, domain='ZZ', order='grlex')"
|
| 665 |
+
assert str(groebner(F, order='lex')) == \
|
| 666 |
+
"GroebnerBasis([2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7], x, y, domain='ZZ', order='lex')"
|
| 667 |
+
|
| 668 |
+
def test_set():
|
| 669 |
+
assert sstr(set()) == 'set()'
|
| 670 |
+
assert sstr(frozenset()) == 'frozenset()'
|
| 671 |
+
|
| 672 |
+
assert sstr({1}) == '{1}'
|
| 673 |
+
assert sstr(frozenset([1])) == 'frozenset({1})'
|
| 674 |
+
assert sstr({1, 2, 3}) == '{1, 2, 3}'
|
| 675 |
+
assert sstr(frozenset([1, 2, 3])) == 'frozenset({1, 2, 3})'
|
| 676 |
+
|
| 677 |
+
assert sstr(
|
| 678 |
+
{1, x, x**2, x**3, x**4}) == '{1, x, x**2, x**3, x**4}'
|
| 679 |
+
assert sstr(
|
| 680 |
+
frozenset([1, x, x**2, x**3, x**4])) == 'frozenset({1, x, x**2, x**3, x**4})'
|
| 681 |
+
|
| 682 |
+
|
| 683 |
+
def test_SparseMatrix():
|
| 684 |
+
M = SparseMatrix([[x**+1, 1], [y, x + y]])
|
| 685 |
+
assert str(M) == "Matrix([[x, 1], [y, x + y]])"
|
| 686 |
+
assert sstr(M) == "Matrix([\n[x, 1],\n[y, x + y]])"
|
| 687 |
+
|
| 688 |
+
|
| 689 |
+
def test_Sum():
|
| 690 |
+
assert str(summation(cos(3*z), (z, x, y))) == "Sum(cos(3*z), (z, x, y))"
|
| 691 |
+
assert str(Sum(x*y**2, (x, -2, 2), (y, -5, 5))) == \
|
| 692 |
+
"Sum(x*y**2, (x, -2, 2), (y, -5, 5))"
|
| 693 |
+
|
| 694 |
+
|
| 695 |
+
def test_Symbol():
|
| 696 |
+
assert str(y) == "y"
|
| 697 |
+
assert str(x) == "x"
|
| 698 |
+
e = x
|
| 699 |
+
assert str(e) == "x"
|
| 700 |
+
|
| 701 |
+
|
| 702 |
+
def test_tuple():
|
| 703 |
+
assert str((x,)) == sstr((x,)) == "(x,)"
|
| 704 |
+
assert str((x + y, 1 + x)) == sstr((x + y, 1 + x)) == "(x + y, x + 1)"
|
| 705 |
+
assert str((x + y, (
|
| 706 |
+
1 + x, x**2))) == sstr((x + y, (1 + x, x**2))) == "(x + y, (x + 1, x**2))"
|
| 707 |
+
|
| 708 |
+
|
| 709 |
+
def test_Series_str():
|
| 710 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 711 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 712 |
+
tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y)
|
| 713 |
+
assert str(Series(tf1, tf2)) == \
|
| 714 |
+
"Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y))"
|
| 715 |
+
assert str(Series(tf1, tf2, tf3)) == \
|
| 716 |
+
"Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y), TransferFunction(t*x**2 - t**w*x + w, t - y, y))"
|
| 717 |
+
assert str(Series(-tf2, tf1)) == \
|
| 718 |
+
"Series(TransferFunction(-x + y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y))"
|
| 719 |
+
|
| 720 |
+
|
| 721 |
+
def test_MIMOSeries_str():
|
| 722 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 723 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 724 |
+
tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]])
|
| 725 |
+
tfm_2 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]])
|
| 726 |
+
assert str(MIMOSeries(tfm_1, tfm_2)) == \
|
| 727 |
+
"MIMOSeries(TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), "\
|
| 728 |
+
"(TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)))), "\
|
| 729 |
+
"TransferFunctionMatrix(((TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)), "\
|
| 730 |
+
"(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)))))"
|
| 731 |
+
|
| 732 |
+
|
| 733 |
+
def test_TransferFunction_str():
|
| 734 |
+
tf1 = TransferFunction(x - 1, x + 1, x)
|
| 735 |
+
assert str(tf1) == "TransferFunction(x - 1, x + 1, x)"
|
| 736 |
+
tf2 = TransferFunction(x + 1, 2 - y, x)
|
| 737 |
+
assert str(tf2) == "TransferFunction(x + 1, 2 - y, x)"
|
| 738 |
+
tf3 = TransferFunction(y, y**2 + 2*y + 3, y)
|
| 739 |
+
assert str(tf3) == "TransferFunction(y, y**2 + 2*y + 3, y)"
|
| 740 |
+
|
| 741 |
+
|
| 742 |
+
def test_Parallel_str():
|
| 743 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 744 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 745 |
+
tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y)
|
| 746 |
+
assert str(Parallel(tf1, tf2)) == \
|
| 747 |
+
"Parallel(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y))"
|
| 748 |
+
assert str(Parallel(tf1, tf2, tf3)) == \
|
| 749 |
+
"Parallel(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y), TransferFunction(t*x**2 - t**w*x + w, t - y, y))"
|
| 750 |
+
assert str(Parallel(-tf2, tf1)) == \
|
| 751 |
+
"Parallel(TransferFunction(-x + y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y))"
|
| 752 |
+
|
| 753 |
+
|
| 754 |
+
def test_MIMOParallel_str():
|
| 755 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 756 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 757 |
+
tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]])
|
| 758 |
+
tfm_2 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]])
|
| 759 |
+
assert str(MIMOParallel(tfm_1, tfm_2)) == \
|
| 760 |
+
"MIMOParallel(TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), "\
|
| 761 |
+
"(TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)))), "\
|
| 762 |
+
"TransferFunctionMatrix(((TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)), "\
|
| 763 |
+
"(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)))))"
|
| 764 |
+
|
| 765 |
+
|
| 766 |
+
def test_Feedback_str():
|
| 767 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 768 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 769 |
+
tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y)
|
| 770 |
+
assert str(Feedback(tf1*tf2, tf3)) == \
|
| 771 |
+
"Feedback(Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), " \
|
| 772 |
+
"TransferFunction(t*x**2 - t**w*x + w, t - y, y), -1)"
|
| 773 |
+
assert str(Feedback(tf1, TransferFunction(1, 1, y), 1)) == \
|
| 774 |
+
"Feedback(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(1, 1, y), 1)"
|
| 775 |
+
|
| 776 |
+
|
| 777 |
+
def test_MIMOFeedback_str():
|
| 778 |
+
tf1 = TransferFunction(x**2 - y**3, y - z, x)
|
| 779 |
+
tf2 = TransferFunction(y - x, z + y, x)
|
| 780 |
+
tfm_1 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]])
|
| 781 |
+
tfm_2 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]])
|
| 782 |
+
assert (str(MIMOFeedback(tfm_1, tfm_2)) \
|
| 783 |
+
== "MIMOFeedback(TransferFunctionMatrix(((TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x))," \
|
| 784 |
+
" (TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)))), " \
|
| 785 |
+
"TransferFunctionMatrix(((TransferFunction(x**2 - y**3, y - z, x), " \
|
| 786 |
+
"TransferFunction(-x + y, y + z, x)), (TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)))), -1)")
|
| 787 |
+
assert (str(MIMOFeedback(tfm_1, tfm_2, 1)) \
|
| 788 |
+
== "MIMOFeedback(TransferFunctionMatrix(((TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)), " \
|
| 789 |
+
"(TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)))), " \
|
| 790 |
+
"TransferFunctionMatrix(((TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)), "\
|
| 791 |
+
"(TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)))), 1)")
|
| 792 |
+
|
| 793 |
+
|
| 794 |
+
def test_TransferFunctionMatrix_str():
|
| 795 |
+
tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y)
|
| 796 |
+
tf2 = TransferFunction(x - y, x + y, y)
|
| 797 |
+
tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y)
|
| 798 |
+
assert str(TransferFunctionMatrix([[tf1], [tf2]])) == \
|
| 799 |
+
"TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y),), (TransferFunction(x - y, x + y, y),)))"
|
| 800 |
+
assert str(TransferFunctionMatrix([[tf1, tf2], [tf3, tf2]])) == \
|
| 801 |
+
"TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), (TransferFunction(t*x**2 - t**w*x + w, t - y, y), TransferFunction(x - y, x + y, y))))"
|
| 802 |
+
|
| 803 |
+
|
| 804 |
+
def test_Quaternion_str_printer():
|
| 805 |
+
q = Quaternion(x, y, z, t)
|
| 806 |
+
assert str(q) == "x + y*i + z*j + t*k"
|
| 807 |
+
q = Quaternion(x,y,z,x*t)
|
| 808 |
+
assert str(q) == "x + y*i + z*j + t*x*k"
|
| 809 |
+
q = Quaternion(x,y,z,x+t)
|
| 810 |
+
assert str(q) == "x + y*i + z*j + (t + x)*k"
|
| 811 |
+
|
| 812 |
+
|
| 813 |
+
def test_Quantity_str():
|
| 814 |
+
assert sstr(second, abbrev=True) == "s"
|
| 815 |
+
assert sstr(joule, abbrev=True) == "J"
|
| 816 |
+
assert str(second) == "second"
|
| 817 |
+
assert str(joule) == "joule"
|
| 818 |
+
|
| 819 |
+
|
| 820 |
+
def test_wild_str():
|
| 821 |
+
# Check expressions containing Wild not causing infinite recursion
|
| 822 |
+
w = Wild('x')
|
| 823 |
+
assert str(w + 1) == 'x_ + 1'
|
| 824 |
+
assert str(exp(2**w) + 5) == 'exp(2**x_) + 5'
|
| 825 |
+
assert str(3*w + 1) == '3*x_ + 1'
|
| 826 |
+
assert str(1/w + 1) == '1 + 1/x_'
|
| 827 |
+
assert str(w**2 + 1) == 'x_**2 + 1'
|
| 828 |
+
assert str(1/(1 - w)) == '1/(1 - x_)'
|
| 829 |
+
|
| 830 |
+
|
| 831 |
+
def test_wild_matchpy():
|
| 832 |
+
from sympy.utilities.matchpy_connector import WildDot, WildPlus, WildStar
|
| 833 |
+
|
| 834 |
+
matchpy = import_module("matchpy")
|
| 835 |
+
|
| 836 |
+
if matchpy is None:
|
| 837 |
+
return
|
| 838 |
+
|
| 839 |
+
wd = WildDot('w_')
|
| 840 |
+
wp = WildPlus('w__')
|
| 841 |
+
ws = WildStar('w___')
|
| 842 |
+
|
| 843 |
+
assert str(wd) == 'w_'
|
| 844 |
+
assert str(wp) == 'w__'
|
| 845 |
+
assert str(ws) == 'w___'
|
| 846 |
+
|
| 847 |
+
assert str(wp/ws + 2**wd) == '2**w_ + w__/w___'
|
| 848 |
+
assert str(sin(wd)*cos(wp)*sqrt(ws)) == 'sqrt(w___)*sin(w_)*cos(w__)'
|
| 849 |
+
|
| 850 |
+
|
| 851 |
+
def test_zeta():
|
| 852 |
+
assert str(zeta(3)) == "zeta(3)"
|
| 853 |
+
|
| 854 |
+
|
| 855 |
+
def test_issue_3101():
|
| 856 |
+
e = x - y
|
| 857 |
+
a = str(e)
|
| 858 |
+
b = str(e)
|
| 859 |
+
assert a == b
|
| 860 |
+
|
| 861 |
+
|
| 862 |
+
def test_issue_3103():
|
| 863 |
+
e = -2*sqrt(x) - y/sqrt(x)/2
|
| 864 |
+
assert str(e) not in ["(-2)*x**1/2(-1/2)*x**(-1/2)*y",
|
| 865 |
+
"-2*x**1/2(-1/2)*x**(-1/2)*y", "-2*x**1/2-1/2*x**-1/2*w"]
|
| 866 |
+
assert str(e) == "-2*sqrt(x) - y/(2*sqrt(x))"
|
| 867 |
+
|
| 868 |
+
|
| 869 |
+
def test_issue_4021():
|
| 870 |
+
e = Integral(x, x) + 1
|
| 871 |
+
assert str(e) == 'Integral(x, x) + 1'
|
| 872 |
+
|
| 873 |
+
|
| 874 |
+
def test_sstrrepr():
|
| 875 |
+
assert sstr('abc') == 'abc'
|
| 876 |
+
assert sstrrepr('abc') == "'abc'"
|
| 877 |
+
|
| 878 |
+
e = ['a', 'b', 'c', x]
|
| 879 |
+
assert sstr(e) == "[a, b, c, x]"
|
| 880 |
+
assert sstrrepr(e) == "['a', 'b', 'c', x]"
|
| 881 |
+
|
| 882 |
+
|
| 883 |
+
def test_infinity():
|
| 884 |
+
assert sstr(oo*I) == "oo*I"
|
| 885 |
+
|
| 886 |
+
|
| 887 |
+
def test_full_prec():
|
| 888 |
+
assert sstr(S("0.3"), full_prec=True) == "0.300000000000000"
|
| 889 |
+
assert sstr(S("0.3"), full_prec="auto") == "0.300000000000000"
|
| 890 |
+
assert sstr(S("0.3"), full_prec=False) == "0.3"
|
| 891 |
+
assert sstr(S("0.3")*x, full_prec=True) in [
|
| 892 |
+
"0.300000000000000*x",
|
| 893 |
+
"x*0.300000000000000"
|
| 894 |
+
]
|
| 895 |
+
assert sstr(S("0.3")*x, full_prec="auto") in [
|
| 896 |
+
"0.3*x",
|
| 897 |
+
"x*0.3"
|
| 898 |
+
]
|
| 899 |
+
assert sstr(S("0.3")*x, full_prec=False) in [
|
| 900 |
+
"0.3*x",
|
| 901 |
+
"x*0.3"
|
| 902 |
+
]
|
| 903 |
+
|
| 904 |
+
|
| 905 |
+
def test_noncommutative():
|
| 906 |
+
A, B, C = symbols('A,B,C', commutative=False)
|
| 907 |
+
|
| 908 |
+
assert sstr(A*B*C**-1) == "A*B*C**(-1)"
|
| 909 |
+
assert sstr(C**-1*A*B) == "C**(-1)*A*B"
|
| 910 |
+
assert sstr(A*C**-1*B) == "A*C**(-1)*B"
|
| 911 |
+
assert sstr(sqrt(A)) == "sqrt(A)"
|
| 912 |
+
assert sstr(1/sqrt(A)) == "A**(-1/2)"
|
| 913 |
+
|
| 914 |
+
|
| 915 |
+
def test_empty_printer():
|
| 916 |
+
str_printer = StrPrinter()
|
| 917 |
+
assert str_printer.emptyPrinter("foo") == "foo"
|
| 918 |
+
assert str_printer.emptyPrinter(x*y) == "x*y"
|
| 919 |
+
assert str_printer.emptyPrinter(32) == "32"
|
| 920 |
+
|
| 921 |
+
|
| 922 |
+
def test_settings():
|
| 923 |
+
raises(TypeError, lambda: sstr(S(4), method="garbage"))
|
| 924 |
+
|
| 925 |
+
|
| 926 |
+
def test_RandomDomain():
|
| 927 |
+
from sympy.stats import Normal, Die, Exponential, pspace, where
|
| 928 |
+
X = Normal('x1', 0, 1)
|
| 929 |
+
assert str(where(X > 0)) == "Domain: (0 < x1) & (x1 < oo)"
|
| 930 |
+
|
| 931 |
+
D = Die('d1', 6)
|
| 932 |
+
assert str(where(D > 4)) == "Domain: Eq(d1, 5) | Eq(d1, 6)"
|
| 933 |
+
|
| 934 |
+
A = Exponential('a', 1)
|
| 935 |
+
B = Exponential('b', 1)
|
| 936 |
+
assert str(pspace(Tuple(A, B)).domain) == "Domain: (0 <= a) & (0 <= b) & (a < oo) & (b < oo)"
|
| 937 |
+
|
| 938 |
+
|
| 939 |
+
def test_FiniteSet():
|
| 940 |
+
assert str(FiniteSet(*range(1, 51))) == (
|
| 941 |
+
'{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,'
|
| 942 |
+
' 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,'
|
| 943 |
+
' 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}'
|
| 944 |
+
)
|
| 945 |
+
assert str(FiniteSet(*range(1, 6))) == '{1, 2, 3, 4, 5}'
|
| 946 |
+
assert str(FiniteSet(*[x*y, x**2])) == '{x**2, x*y}'
|
| 947 |
+
assert str(FiniteSet(FiniteSet(FiniteSet(x, y), 5), FiniteSet(x,y), 5)
|
| 948 |
+
) == 'FiniteSet(5, FiniteSet(5, {x, y}), {x, y})'
|
| 949 |
+
|
| 950 |
+
|
| 951 |
+
def test_Partition():
|
| 952 |
+
assert str(Partition(FiniteSet(x, y), {z})) == 'Partition({z}, {x, y})'
|
| 953 |
+
|
| 954 |
+
def test_UniversalSet():
|
| 955 |
+
assert str(S.UniversalSet) == 'UniversalSet'
|
| 956 |
+
|
| 957 |
+
|
| 958 |
+
def test_PrettyPoly():
|
| 959 |
+
F = QQ.frac_field(x, y)
|
| 960 |
+
R = QQ[x, y]
|
| 961 |
+
assert sstr(F.convert(x/(x + y))) == sstr(x/(x + y))
|
| 962 |
+
assert sstr(R.convert(x + y)) == sstr(x + y)
|
| 963 |
+
|
| 964 |
+
|
| 965 |
+
def test_categories():
|
| 966 |
+
from sympy.categories import (Object, NamedMorphism,
|
| 967 |
+
IdentityMorphism, Category)
|
| 968 |
+
|
| 969 |
+
A = Object("A")
|
| 970 |
+
B = Object("B")
|
| 971 |
+
|
| 972 |
+
f = NamedMorphism(A, B, "f")
|
| 973 |
+
id_A = IdentityMorphism(A)
|
| 974 |
+
|
| 975 |
+
K = Category("K")
|
| 976 |
+
|
| 977 |
+
assert str(A) == 'Object("A")'
|
| 978 |
+
assert str(f) == 'NamedMorphism(Object("A"), Object("B"), "f")'
|
| 979 |
+
assert str(id_A) == 'IdentityMorphism(Object("A"))'
|
| 980 |
+
|
| 981 |
+
assert str(K) == 'Category("K")'
|
| 982 |
+
|
| 983 |
+
|
| 984 |
+
def test_Tr():
|
| 985 |
+
A, B = symbols('A B', commutative=False)
|
| 986 |
+
t = Tr(A*B)
|
| 987 |
+
assert str(t) == 'Tr(A*B)'
|
| 988 |
+
|
| 989 |
+
|
| 990 |
+
def test_issue_6387():
|
| 991 |
+
assert str(factor(-3.0*z + 3)) == '-3.0*(1.0*z - 1.0)'
|
| 992 |
+
|
| 993 |
+
|
| 994 |
+
def test_MatMul_MatAdd():
|
| 995 |
+
X, Y = MatrixSymbol("X", 2, 2), MatrixSymbol("Y", 2, 2)
|
| 996 |
+
assert str(2*(X + Y)) == "2*X + 2*Y"
|
| 997 |
+
|
| 998 |
+
assert str(I*X) == "I*X"
|
| 999 |
+
assert str(-I*X) == "-I*X"
|
| 1000 |
+
assert str((1 + I)*X) == '(1 + I)*X'
|
| 1001 |
+
assert str(-(1 + I)*X) == '(-1 - I)*X'
|
| 1002 |
+
assert str(MatAdd(MatAdd(X, Y), MatAdd(X, Y))) == '(X + Y) + (X + Y)'
|
| 1003 |
+
|
| 1004 |
+
|
| 1005 |
+
def test_MatrixSlice():
|
| 1006 |
+
n = Symbol('n', integer=True)
|
| 1007 |
+
X = MatrixSymbol('X', n, n)
|
| 1008 |
+
Y = MatrixSymbol('Y', 10, 10)
|
| 1009 |
+
Z = MatrixSymbol('Z', 10, 10)
|
| 1010 |
+
|
| 1011 |
+
assert str(MatrixSlice(X, (None, None, None), (None, None, None))) == 'X[:, :]'
|
| 1012 |
+
assert str(X[x:x + 1, y:y + 1]) == 'X[x:x + 1, y:y + 1]'
|
| 1013 |
+
assert str(X[x:x + 1:2, y:y + 1:2]) == 'X[x:x + 1:2, y:y + 1:2]'
|
| 1014 |
+
assert str(X[:x, y:]) == 'X[:x, y:]'
|
| 1015 |
+
assert str(X[:x, y:]) == 'X[:x, y:]'
|
| 1016 |
+
assert str(X[x:, :y]) == 'X[x:, :y]'
|
| 1017 |
+
assert str(X[x:y, z:w]) == 'X[x:y, z:w]'
|
| 1018 |
+
assert str(X[x:y:t, w:t:x]) == 'X[x:y:t, w:t:x]'
|
| 1019 |
+
assert str(X[x::y, t::w]) == 'X[x::y, t::w]'
|
| 1020 |
+
assert str(X[:x:y, :t:w]) == 'X[:x:y, :t:w]'
|
| 1021 |
+
assert str(X[::x, ::y]) == 'X[::x, ::y]'
|
| 1022 |
+
assert str(MatrixSlice(X, (0, None, None), (0, None, None))) == 'X[:, :]'
|
| 1023 |
+
assert str(MatrixSlice(X, (None, n, None), (None, n, None))) == 'X[:, :]'
|
| 1024 |
+
assert str(MatrixSlice(X, (0, n, None), (0, n, None))) == 'X[:, :]'
|
| 1025 |
+
assert str(MatrixSlice(X, (0, n, 2), (0, n, 2))) == 'X[::2, ::2]'
|
| 1026 |
+
assert str(X[1:2:3, 4:5:6]) == 'X[1:2:3, 4:5:6]'
|
| 1027 |
+
assert str(X[1:3:5, 4:6:8]) == 'X[1:3:5, 4:6:8]'
|
| 1028 |
+
assert str(X[1:10:2]) == 'X[1:10:2, :]'
|
| 1029 |
+
assert str(Y[:5, 1:9:2]) == 'Y[:5, 1:9:2]'
|
| 1030 |
+
assert str(Y[:5, 1:10:2]) == 'Y[:5, 1::2]'
|
| 1031 |
+
assert str(Y[5, :5:2]) == 'Y[5:6, :5:2]'
|
| 1032 |
+
assert str(X[0:1, 0:1]) == 'X[:1, :1]'
|
| 1033 |
+
assert str(X[0:1:2, 0:1:2]) == 'X[:1:2, :1:2]'
|
| 1034 |
+
assert str((Y + Z)[2:, 2:]) == '(Y + Z)[2:, 2:]'
|
| 1035 |
+
|
| 1036 |
+
def test_true_false():
|
| 1037 |
+
assert str(true) == repr(true) == sstr(true) == "True"
|
| 1038 |
+
assert str(false) == repr(false) == sstr(false) == "False"
|
| 1039 |
+
|
| 1040 |
+
def test_Equivalent():
|
| 1041 |
+
assert str(Equivalent(y, x)) == "Equivalent(x, y)"
|
| 1042 |
+
|
| 1043 |
+
def test_Xor():
|
| 1044 |
+
assert str(Xor(y, x, evaluate=False)) == "x ^ y"
|
| 1045 |
+
|
| 1046 |
+
def test_Complement():
|
| 1047 |
+
assert str(Complement(S.Reals, S.Naturals)) == 'Complement(Reals, Naturals)'
|
| 1048 |
+
|
| 1049 |
+
def test_SymmetricDifference():
|
| 1050 |
+
assert str(SymmetricDifference(Interval(2, 3), Interval(3, 4),evaluate=False)) == \
|
| 1051 |
+
'SymmetricDifference(Interval(2, 3), Interval(3, 4))'
|
| 1052 |
+
|
| 1053 |
+
|
| 1054 |
+
def test_UnevaluatedExpr():
|
| 1055 |
+
a, b = symbols("a b")
|
| 1056 |
+
expr1 = 2*UnevaluatedExpr(a+b)
|
| 1057 |
+
assert str(expr1) == "2*(a + b)"
|
| 1058 |
+
|
| 1059 |
+
|
| 1060 |
+
def test_MatrixElement_printing():
|
| 1061 |
+
# test cases for issue #11821
|
| 1062 |
+
A = MatrixSymbol("A", 1, 3)
|
| 1063 |
+
B = MatrixSymbol("B", 1, 3)
|
| 1064 |
+
C = MatrixSymbol("C", 1, 3)
|
| 1065 |
+
|
| 1066 |
+
assert(str(A[0, 0]) == "A[0, 0]")
|
| 1067 |
+
assert(str(3 * A[0, 0]) == "3*A[0, 0]")
|
| 1068 |
+
|
| 1069 |
+
F = C[0, 0].subs(C, A - B)
|
| 1070 |
+
assert str(F) == "(A - B)[0, 0]"
|
| 1071 |
+
|
| 1072 |
+
|
| 1073 |
+
def test_MatrixSymbol_printing():
|
| 1074 |
+
A = MatrixSymbol("A", 3, 3)
|
| 1075 |
+
B = MatrixSymbol("B", 3, 3)
|
| 1076 |
+
|
| 1077 |
+
assert str(A - A*B - B) == "A - A*B - B"
|
| 1078 |
+
assert str(A*B - (A+B)) == "-A + A*B - B"
|
| 1079 |
+
assert str(A**(-1)) == "A**(-1)"
|
| 1080 |
+
assert str(A**3) == "A**3"
|
| 1081 |
+
|
| 1082 |
+
|
| 1083 |
+
def test_MatrixExpressions():
|
| 1084 |
+
n = Symbol('n', integer=True)
|
| 1085 |
+
X = MatrixSymbol('X', n, n)
|
| 1086 |
+
|
| 1087 |
+
assert str(X) == "X"
|
| 1088 |
+
|
| 1089 |
+
# Apply function elementwise (`ElementwiseApplyFunc`):
|
| 1090 |
+
|
| 1091 |
+
expr = (X.T*X).applyfunc(sin)
|
| 1092 |
+
assert str(expr) == 'Lambda(_d, sin(_d)).(X.T*X)'
|
| 1093 |
+
|
| 1094 |
+
lamda = Lambda(x, 1/x)
|
| 1095 |
+
expr = (n*X).applyfunc(lamda)
|
| 1096 |
+
assert str(expr) == 'Lambda(x, 1/x).(n*X)'
|
| 1097 |
+
|
| 1098 |
+
|
| 1099 |
+
def test_Subs_printing():
|
| 1100 |
+
assert str(Subs(x, (x,), (1,))) == 'Subs(x, x, 1)'
|
| 1101 |
+
assert str(Subs(x + y, (x, y), (1, 2))) == 'Subs(x + y, (x, y), (1, 2))'
|
| 1102 |
+
|
| 1103 |
+
|
| 1104 |
+
def test_issue_15716():
|
| 1105 |
+
e = Integral(factorial(x), (x, -oo, oo))
|
| 1106 |
+
assert e.as_terms() == ([(e, ((1.0, 0.0), (1,), ()))], [e])
|
| 1107 |
+
|
| 1108 |
+
|
| 1109 |
+
def test_str_special_matrices():
|
| 1110 |
+
from sympy.matrices import Identity, ZeroMatrix, OneMatrix
|
| 1111 |
+
assert str(Identity(4)) == 'I'
|
| 1112 |
+
assert str(ZeroMatrix(2, 2)) == '0'
|
| 1113 |
+
assert str(OneMatrix(2, 2)) == '1'
|
| 1114 |
+
|
| 1115 |
+
|
| 1116 |
+
def test_issue_14567():
|
| 1117 |
+
assert factorial(Sum(-1, (x, 0, 0))) + y # doesn't raise an error
|
| 1118 |
+
|
| 1119 |
+
|
| 1120 |
+
def test_issue_21823():
|
| 1121 |
+
assert str(Partition([1, 2])) == 'Partition({1, 2})'
|
| 1122 |
+
assert str(Partition({1, 2})) == 'Partition({1, 2})'
|
| 1123 |
+
|
| 1124 |
+
|
| 1125 |
+
def test_issue_22689():
|
| 1126 |
+
assert str(Mul(Pow(x,-2, evaluate=False), Pow(3,-1,evaluate=False), evaluate=False)) == "1/(x**2*3)"
|
| 1127 |
+
|
| 1128 |
+
|
| 1129 |
+
def test_issue_21119_21460():
|
| 1130 |
+
ss = lambda x: str(S(x, evaluate=False))
|
| 1131 |
+
assert ss('4/2') == '4/2'
|
| 1132 |
+
assert ss('4/-2') == '4/(-2)'
|
| 1133 |
+
assert ss('-4/2') == '-4/2'
|
| 1134 |
+
assert ss('-4/-2') == '-4/(-2)'
|
| 1135 |
+
assert ss('-2*3/-1') == '-2*3/(-1)'
|
| 1136 |
+
assert ss('-2*3/-1/2') == '-2*3/(-1*2)'
|
| 1137 |
+
assert ss('4/2/1') == '4/(2*1)'
|
| 1138 |
+
assert ss('-2/-1/2') == '-2/(-1*2)'
|
| 1139 |
+
assert ss('2*3*4**(-2*3)') == '2*3/4**(2*3)'
|
| 1140 |
+
assert ss('2*3*1*4**(-2*3)') == '2*3*1/4**(2*3)'
|
| 1141 |
+
|
| 1142 |
+
|
| 1143 |
+
def test_Str():
|
| 1144 |
+
from sympy.core.symbol import Str
|
| 1145 |
+
assert str(Str('x')) == 'x'
|
| 1146 |
+
assert sstrrepr(Str('x')) == "Str('x')"
|
| 1147 |
+
|
| 1148 |
+
|
| 1149 |
+
def test_diffgeom():
|
| 1150 |
+
from sympy.diffgeom import Manifold, Patch, CoordSystem, BaseScalarField
|
| 1151 |
+
x,y = symbols('x y', real=True)
|
| 1152 |
+
m = Manifold('M', 2)
|
| 1153 |
+
assert str(m) == "M"
|
| 1154 |
+
p = Patch('P', m)
|
| 1155 |
+
assert str(p) == "P"
|
| 1156 |
+
rect = CoordSystem('rect', p, [x, y])
|
| 1157 |
+
assert str(rect) == "rect"
|
| 1158 |
+
b = BaseScalarField(rect, 0)
|
| 1159 |
+
assert str(b) == "x"
|
| 1160 |
+
|
| 1161 |
+
def test_NDimArray():
|
| 1162 |
+
assert sstr(NDimArray(1.0), full_prec=True) == '1.00000000000000'
|
| 1163 |
+
assert sstr(NDimArray(1.0), full_prec=False) == '1.0'
|
| 1164 |
+
assert sstr(NDimArray([1.0, 2.0]), full_prec=True) == '[1.00000000000000, 2.00000000000000]'
|
| 1165 |
+
assert sstr(NDimArray([1.0, 2.0]), full_prec=False) == '[1.0, 2.0]'
|
| 1166 |
+
|
| 1167 |
+
def test_Predicate():
|
| 1168 |
+
assert sstr(Q.even) == 'Q.even'
|
| 1169 |
+
|
| 1170 |
+
def test_AppliedPredicate():
|
| 1171 |
+
assert sstr(Q.even(x)) == 'Q.even(x)'
|
| 1172 |
+
|
| 1173 |
+
def test_printing_str_array_expressions():
|
| 1174 |
+
assert sstr(ArraySymbol("A", (2, 3, 4))) == "A"
|
| 1175 |
+
assert sstr(ArrayElement("A", (2, 1/(1-x), 0))) == "A[2, 1/(1 - x), 0]"
|
| 1176 |
+
M = MatrixSymbol("M", 3, 3)
|
| 1177 |
+
N = MatrixSymbol("N", 3, 3)
|
| 1178 |
+
assert sstr(ArrayElement(M*N, [x, 0])) == "(M*N)[x, 0]"
|
| 1179 |
+
|
| 1180 |
+
def test_printing_stats():
|
| 1181 |
+
# issue 24132
|
| 1182 |
+
x = RandomSymbol("x")
|
| 1183 |
+
y = RandomSymbol("y")
|
| 1184 |
+
z1 = Probability(x > 0)*Identity(2)
|
| 1185 |
+
z2 = Expectation(x)*Identity(2)
|
| 1186 |
+
z3 = Variance(x)*Identity(2)
|
| 1187 |
+
z4 = Covariance(x, y) * Identity(2)
|
| 1188 |
+
|
| 1189 |
+
assert str(z1) == "Probability(x > 0)*I"
|
| 1190 |
+
assert str(z2) == "Expectation(x)*I"
|
| 1191 |
+
assert str(z3) == "Variance(x)*I"
|
| 1192 |
+
assert str(z4) == "Covariance(x, y)*I"
|
| 1193 |
+
assert z1.is_commutative == False
|
| 1194 |
+
assert z2.is_commutative == False
|
| 1195 |
+
assert z3.is_commutative == False
|
| 1196 |
+
assert z4.is_commutative == False
|
| 1197 |
+
assert z2._eval_is_commutative() == False
|
| 1198 |
+
assert z3._eval_is_commutative() == False
|
| 1199 |
+
assert z4._eval_is_commutative() == False
|
lib/python3.12/site-packages/sympy/printing/tests/test_tree.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.printing.tree import tree
|
| 2 |
+
from sympy.testing.pytest import XFAIL
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
# Remove this flag after making _assumptions cache deterministic.
|
| 6 |
+
@XFAIL
|
| 7 |
+
def test_print_tree_MatAdd():
|
| 8 |
+
from sympy.matrices.expressions import MatrixSymbol
|
| 9 |
+
A = MatrixSymbol('A', 3, 3)
|
| 10 |
+
B = MatrixSymbol('B', 3, 3)
|
| 11 |
+
|
| 12 |
+
test_str = [
|
| 13 |
+
'MatAdd: A + B\n',
|
| 14 |
+
'algebraic: False\n',
|
| 15 |
+
'commutative: False\n',
|
| 16 |
+
'complex: False\n',
|
| 17 |
+
'composite: False\n',
|
| 18 |
+
'even: False\n',
|
| 19 |
+
'extended_negative: False\n',
|
| 20 |
+
'extended_nonnegative: False\n',
|
| 21 |
+
'extended_nonpositive: False\n',
|
| 22 |
+
'extended_nonzero: False\n',
|
| 23 |
+
'extended_positive: False\n',
|
| 24 |
+
'extended_real: False\n',
|
| 25 |
+
'imaginary: False\n',
|
| 26 |
+
'integer: False\n',
|
| 27 |
+
'irrational: False\n',
|
| 28 |
+
'negative: False\n',
|
| 29 |
+
'noninteger: False\n',
|
| 30 |
+
'nonnegative: False\n',
|
| 31 |
+
'nonpositive: False\n',
|
| 32 |
+
'nonzero: False\n',
|
| 33 |
+
'odd: False\n',
|
| 34 |
+
'positive: False\n',
|
| 35 |
+
'prime: False\n',
|
| 36 |
+
'rational: False\n',
|
| 37 |
+
'real: False\n',
|
| 38 |
+
'transcendental: False\n',
|
| 39 |
+
'zero: False\n',
|
| 40 |
+
'+-MatrixSymbol: A\n',
|
| 41 |
+
'| algebraic: False\n',
|
| 42 |
+
'| commutative: False\n',
|
| 43 |
+
'| complex: False\n',
|
| 44 |
+
'| composite: False\n',
|
| 45 |
+
'| even: False\n',
|
| 46 |
+
'| extended_negative: False\n',
|
| 47 |
+
'| extended_nonnegative: False\n',
|
| 48 |
+
'| extended_nonpositive: False\n',
|
| 49 |
+
'| extended_nonzero: False\n',
|
| 50 |
+
'| extended_positive: False\n',
|
| 51 |
+
'| extended_real: False\n',
|
| 52 |
+
'| imaginary: False\n',
|
| 53 |
+
'| integer: False\n',
|
| 54 |
+
'| irrational: False\n',
|
| 55 |
+
'| negative: False\n',
|
| 56 |
+
'| noninteger: False\n',
|
| 57 |
+
'| nonnegative: False\n',
|
| 58 |
+
'| nonpositive: False\n',
|
| 59 |
+
'| nonzero: False\n',
|
| 60 |
+
'| odd: False\n',
|
| 61 |
+
'| positive: False\n',
|
| 62 |
+
'| prime: False\n',
|
| 63 |
+
'| rational: False\n',
|
| 64 |
+
'| real: False\n',
|
| 65 |
+
'| transcendental: False\n',
|
| 66 |
+
'| zero: False\n',
|
| 67 |
+
'| +-Symbol: A\n',
|
| 68 |
+
'| | commutative: True\n',
|
| 69 |
+
'| +-Integer: 3\n',
|
| 70 |
+
'| | algebraic: True\n',
|
| 71 |
+
'| | commutative: True\n',
|
| 72 |
+
'| | complex: True\n',
|
| 73 |
+
'| | extended_negative: False\n',
|
| 74 |
+
'| | extended_nonnegative: True\n',
|
| 75 |
+
'| | extended_real: True\n',
|
| 76 |
+
'| | finite: True\n',
|
| 77 |
+
'| | hermitian: True\n',
|
| 78 |
+
'| | imaginary: False\n',
|
| 79 |
+
'| | infinite: False\n',
|
| 80 |
+
'| | integer: True\n',
|
| 81 |
+
'| | irrational: False\n',
|
| 82 |
+
'| | negative: False\n',
|
| 83 |
+
'| | noninteger: False\n',
|
| 84 |
+
'| | nonnegative: True\n',
|
| 85 |
+
'| | rational: True\n',
|
| 86 |
+
'| | real: True\n',
|
| 87 |
+
'| | transcendental: False\n',
|
| 88 |
+
'| +-Integer: 3\n',
|
| 89 |
+
'| algebraic: True\n',
|
| 90 |
+
'| commutative: True\n',
|
| 91 |
+
'| complex: True\n',
|
| 92 |
+
'| extended_negative: False\n',
|
| 93 |
+
'| extended_nonnegative: True\n',
|
| 94 |
+
'| extended_real: True\n',
|
| 95 |
+
'| finite: True\n',
|
| 96 |
+
'| hermitian: True\n',
|
| 97 |
+
'| imaginary: False\n',
|
| 98 |
+
'| infinite: False\n',
|
| 99 |
+
'| integer: True\n',
|
| 100 |
+
'| irrational: False\n',
|
| 101 |
+
'| negative: False\n',
|
| 102 |
+
'| noninteger: False\n',
|
| 103 |
+
'| nonnegative: True\n',
|
| 104 |
+
'| rational: True\n',
|
| 105 |
+
'| real: True\n',
|
| 106 |
+
'| transcendental: False\n',
|
| 107 |
+
'+-MatrixSymbol: B\n',
|
| 108 |
+
' algebraic: False\n',
|
| 109 |
+
' commutative: False\n',
|
| 110 |
+
' complex: False\n',
|
| 111 |
+
' composite: False\n',
|
| 112 |
+
' even: False\n',
|
| 113 |
+
' extended_negative: False\n',
|
| 114 |
+
' extended_nonnegative: False\n',
|
| 115 |
+
' extended_nonpositive: False\n',
|
| 116 |
+
' extended_nonzero: False\n',
|
| 117 |
+
' extended_positive: False\n',
|
| 118 |
+
' extended_real: False\n',
|
| 119 |
+
' imaginary: False\n',
|
| 120 |
+
' integer: False\n',
|
| 121 |
+
' irrational: False\n',
|
| 122 |
+
' negative: False\n',
|
| 123 |
+
' noninteger: False\n',
|
| 124 |
+
' nonnegative: False\n',
|
| 125 |
+
' nonpositive: False\n',
|
| 126 |
+
' nonzero: False\n',
|
| 127 |
+
' odd: False\n',
|
| 128 |
+
' positive: False\n',
|
| 129 |
+
' prime: False\n',
|
| 130 |
+
' rational: False\n',
|
| 131 |
+
' real: False\n',
|
| 132 |
+
' transcendental: False\n',
|
| 133 |
+
' zero: False\n',
|
| 134 |
+
' +-Symbol: B\n',
|
| 135 |
+
' | commutative: True\n',
|
| 136 |
+
' +-Integer: 3\n',
|
| 137 |
+
' | algebraic: True\n',
|
| 138 |
+
' | commutative: True\n',
|
| 139 |
+
' | complex: True\n',
|
| 140 |
+
' | extended_negative: False\n',
|
| 141 |
+
' | extended_nonnegative: True\n',
|
| 142 |
+
' | extended_real: True\n',
|
| 143 |
+
' | finite: True\n',
|
| 144 |
+
' | hermitian: True\n',
|
| 145 |
+
' | imaginary: False\n',
|
| 146 |
+
' | infinite: False\n',
|
| 147 |
+
' | integer: True\n',
|
| 148 |
+
' | irrational: False\n',
|
| 149 |
+
' | negative: False\n',
|
| 150 |
+
' | noninteger: False\n',
|
| 151 |
+
' | nonnegative: True\n',
|
| 152 |
+
' | rational: True\n',
|
| 153 |
+
' | real: True\n',
|
| 154 |
+
' | transcendental: False\n',
|
| 155 |
+
' +-Integer: 3\n',
|
| 156 |
+
' algebraic: True\n',
|
| 157 |
+
' commutative: True\n',
|
| 158 |
+
' complex: True\n',
|
| 159 |
+
' extended_negative: False\n',
|
| 160 |
+
' extended_nonnegative: True\n',
|
| 161 |
+
' extended_real: True\n',
|
| 162 |
+
' finite: True\n',
|
| 163 |
+
' hermitian: True\n',
|
| 164 |
+
' imaginary: False\n',
|
| 165 |
+
' infinite: False\n',
|
| 166 |
+
' integer: True\n',
|
| 167 |
+
' irrational: False\n',
|
| 168 |
+
' negative: False\n',
|
| 169 |
+
' noninteger: False\n',
|
| 170 |
+
' nonnegative: True\n',
|
| 171 |
+
' rational: True\n',
|
| 172 |
+
' real: True\n',
|
| 173 |
+
' transcendental: False\n'
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
assert tree(A + B) == "".join(test_str)
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def test_print_tree_MatAdd_noassumptions():
|
| 180 |
+
from sympy.matrices.expressions import MatrixSymbol
|
| 181 |
+
A = MatrixSymbol('A', 3, 3)
|
| 182 |
+
B = MatrixSymbol('B', 3, 3)
|
| 183 |
+
|
| 184 |
+
test_str = \
|
| 185 |
+
"""MatAdd: A + B
|
| 186 |
+
+-MatrixSymbol: A
|
| 187 |
+
| +-Str: A
|
| 188 |
+
| +-Integer: 3
|
| 189 |
+
| +-Integer: 3
|
| 190 |
+
+-MatrixSymbol: B
|
| 191 |
+
+-Str: B
|
| 192 |
+
+-Integer: 3
|
| 193 |
+
+-Integer: 3
|
| 194 |
+
"""
|
| 195 |
+
|
| 196 |
+
assert tree(A + B, assumptions=False) == test_str
|