Spaces:
Sleeping
Sleeping
Upload 3077 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/AUTHORS +1317 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/INSTALLER +1 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/LICENSE +153 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/METADATA +304 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/RECORD +0 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/WHEEL +5 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/entry_points.txt +2 -0
- MLPY/Lib/site-packages/sympy-1.13.1.dist-info/top_level.txt +2 -0
- MLPY/Lib/site-packages/sympy/__init__.py +542 -0
- MLPY/Lib/site-packages/sympy/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/__pycache__/abc.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/__pycache__/conftest.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/__pycache__/galgebra.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/__pycache__/release.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/__pycache__/this.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/abc.py +111 -0
- MLPY/Lib/site-packages/sympy/algebras/__init__.py +3 -0
- MLPY/Lib/site-packages/sympy/algebras/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/algebras/__pycache__/quaternion.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/algebras/quaternion.py +1667 -0
- MLPY/Lib/site-packages/sympy/algebras/tests/__init__.py +0 -0
- MLPY/Lib/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/algebras/tests/test_quaternion.py +428 -0
- MLPY/Lib/site-packages/sympy/assumptions/__init__.py +18 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/ask.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/ask_generated.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/assume.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/cnf.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/facts.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/lra_satask.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/refine.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/satask.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/sathandlers.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/__pycache__/wrapper.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/ask.py +651 -0
- MLPY/Lib/site-packages/sympy/assumptions/ask_generated.py +352 -0
- MLPY/Lib/site-packages/sympy/assumptions/assume.py +485 -0
- MLPY/Lib/site-packages/sympy/assumptions/cnf.py +445 -0
- MLPY/Lib/site-packages/sympy/assumptions/facts.py +270 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__init__.py +13 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/calculus.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/common.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/matrices.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/ntheory.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/order.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/sets.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/sympy/assumptions/handlers/calculus.py +258 -0
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/AUTHORS
ADDED
@@ -0,0 +1,1317 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
All people who contributed to SymPy by sending at least a patch or
|
2 |
+
more (in the order of the date of their first contribution), except
|
3 |
+
those who explicitly didn't want to be mentioned. People with a * next
|
4 |
+
to their names are not found in the metadata of the git history. This
|
5 |
+
file is generated automatically by running `./bin/authors_update.py`.
|
6 |
+
|
7 |
+
There are a total of 1309 authors.
|
8 |
+
|
9 |
+
Ondřej Čertík <ondrej@certik.cz>
|
10 |
+
Fabian Pedregosa <fabian@fseoane.net>
|
11 |
+
Jurjen N.E. Bos <jnebos@gmail.com>
|
12 |
+
Mateusz Paprocki <mattpap@gmail.com>
|
13 |
+
*Marc-Etienne M.Leveille <protonyc@gmail.com>
|
14 |
+
Brian Jorgensen <brian.jorgensen@gmail.com>
|
15 |
+
Jason Gedge <inferno1386@gmail.com>
|
16 |
+
Robert Schwarz <lethargo@googlemail.com>
|
17 |
+
Pearu Peterson <pearu.peterson@gmail.com>
|
18 |
+
Fredrik Johansson <fredrik.johansson@gmail.com>
|
19 |
+
Chris Wu <chris.wu@gmail.com>
|
20 |
+
*Ulrich Hecht <ulrich.hecht@gmail.com>
|
21 |
+
Goutham Lakshminarayan <dl.goutham@gmail.com>
|
22 |
+
David Lawrence <dmlawrence@gmail.com>
|
23 |
+
Jaroslaw Tworek <dev.jrx@gmail.com>
|
24 |
+
David Marek <h4wk.cz@gmail.com>
|
25 |
+
Bernhard R. Link <brlink@debian.org>
|
26 |
+
Andrej Tokarčík <androsis@gmail.com>
|
27 |
+
Or Dvory <gidesa@gmail.com>
|
28 |
+
Saroj Adhikari <adh.saroj@gmail.com>
|
29 |
+
Pauli Virtanen <pav@iki.fi>
|
30 |
+
Robert Kern <robert.kern@gmail.com>
|
31 |
+
James Aspnes <aspnes@cs.yale.edu>
|
32 |
+
Nimish Telang <ntelang@gmail.com>
|
33 |
+
Abderrahim Kitouni <a.kitouni@gmail.com>
|
34 |
+
Pan Peng <pengpanster@gmail.com>
|
35 |
+
Friedrich Hagedorn <friedrich_h@gmx.de>
|
36 |
+
Elrond der Elbenfuerst <elrond+sympy.org@samba-tng.org>
|
37 |
+
Rizgar Mella <rizgar.mella@gmail.com>
|
38 |
+
Felix Kaiser <felix.kaiser@fxkr.net>
|
39 |
+
Roberto Nobrega <rwnobrega@gmail.com>
|
40 |
+
David Roberts <dvdr18@gmail.com>
|
41 |
+
Sebastian Krämer <basti.kr@gmail.com>
|
42 |
+
Vinzent Steinberg <vinzent.steinberg@gmail.com>
|
43 |
+
Riccardo Gori <goriccardo@gmail.com>
|
44 |
+
Case Van Horsen <casevh@gmail.com>
|
45 |
+
Stepan Roucka <stepan@roucka.eu>
|
46 |
+
Ali Raza Syed <arsyed@gmail.com>
|
47 |
+
Stefano Maggiolo <s.maggiolo@gmail.com>
|
48 |
+
Robert Cimrman <cimrman3@ntc.zcu.cz>
|
49 |
+
Bastian Weber <bastian.weber@gmx-topmail.de>
|
50 |
+
Sebastian Krause <sebastian.krause@gmx.de>
|
51 |
+
Sebastian Kreft <skreft@gmail.com>
|
52 |
+
*Dan <coolg49964@gmail.com>
|
53 |
+
Alan Bromborsky <abrombo@verizon.net>
|
54 |
+
Boris Timokhin <qoqenator@gmail.com>
|
55 |
+
Robert <average.programmer@gmail.com>
|
56 |
+
Andy R. Terrel <aterrel@uchicago.edu>
|
57 |
+
Hubert Tsang <intsangity@gmail.com>
|
58 |
+
Konrad Meyer <konrad.meyer@gmail.com>
|
59 |
+
Henrik Johansson <henjo2006@gmail.com>
|
60 |
+
Priit Laes <plaes@plaes.org>
|
61 |
+
Freddie Witherden <freddie@witherden.org>
|
62 |
+
Brian E. Granger <ellisonbg@gmail.com>
|
63 |
+
Andrew Straw <strawman@astraw.com>
|
64 |
+
Kaifeng Zhu <cafeeee@gmail.com>
|
65 |
+
Ted Horst <ted.horst@earthlink.net>
|
66 |
+
Andrew Docherty <andrewd@maths.usyd.edu.au>
|
67 |
+
Akshay Srinivasan <akshaysrinivasan@gmail.com>
|
68 |
+
Aaron Meurer <asmeurer@gmail.com>
|
69 |
+
Barry Wardell <barry.wardell@gmail.com>
|
70 |
+
Tomasz Buchert <thinred@gmail.com>
|
71 |
+
Vinay Kumar <gnulinooks@gmail.com>
|
72 |
+
Johann Cohen-Tanugi <johann.cohentanugi@gmail.com>
|
73 |
+
Jochen Voss <voss@seehuhn.de>
|
74 |
+
Luke Peterson <hazelnusse@gmail.com>
|
75 |
+
Chris Smith <smichr@gmail.com>
|
76 |
+
Thomas Sidoti <TSidoti@gmail.com>
|
77 |
+
Florian Mickler <florian@mickler.org>
|
78 |
+
Nicolas Pourcelot <nicolas.pourcelot@gmail.com>
|
79 |
+
Ben Goodrich <goodrich.ben@gmail.com>
|
80 |
+
Toon Verstraelen <Toon.Verstraelen@UGent.be>
|
81 |
+
Ronan Lamy <ronan.lamy@gmail.com>
|
82 |
+
James Abbatiello <abbeyj@gmail.com>
|
83 |
+
Ryan Krauss <ryanlists@gmail.com>
|
84 |
+
Bill Flynn <wflynny@gmail.com>
|
85 |
+
Kevin Goodsell <kevin-opensource@omegacrash.net>
|
86 |
+
Jorn Baayen <jorn.baayen@gmail.com>
|
87 |
+
Eh Tan <tan2tan2@gmail.com>
|
88 |
+
Renato Coutinho <renato.coutinho@gmail.com>
|
89 |
+
Oscar Benjamin <oscar.j.benjamin@gmail.com>
|
90 |
+
Øyvind Jensen <jensen.oyvind@gmail.com>
|
91 |
+
Julio Idichekop Filho <idichekop@yahoo.com.br>
|
92 |
+
Łukasz Pankowski <lukpank@o2.pl>
|
93 |
+
*Chu-Ching Huang <cchuang@mail.cgu.edu.tw>
|
94 |
+
Fernando Perez <Fernando.Perez@berkeley.edu>
|
95 |
+
Raffaele De Feo <alberthilbert@gmail.com>
|
96 |
+
Christian Muise <christian.muise@gmail.com>
|
97 |
+
Matt Curry <mattjcurry@gmail.com>
|
98 |
+
Kazuo Thow <kazuo.thow@gmail.com>
|
99 |
+
Christian Schubert <chr.schubert@gmx.de>
|
100 |
+
Jezreel Ng <jezreel@gmail.com>
|
101 |
+
James Pearson <xiong.chiamiov@gmail.com>
|
102 |
+
Matthew Brett <matthew.brett@gmail.com>
|
103 |
+
Addison Cugini <ajcugini@gmail.com>
|
104 |
+
Nicholas J.S. Kinar <n.kinar@usask.ca>
|
105 |
+
Harold Erbin <harold.erbin@gmail.com>
|
106 |
+
Thomas Dixon <thom@thomdixon.org>
|
107 |
+
Cristóvão Sousa <crisjss@gmail.com>
|
108 |
+
Andre de Fortier Smit <freevryheid@gmail.com>
|
109 |
+
Mark Dewing <markdewing@gmail.com>
|
110 |
+
Alexey U. Gudchenko <proga@goodok.ru>
|
111 |
+
Gary Kerr <gary.kerr@blueyonder.co.uk>
|
112 |
+
Sherjil Ozair <sherjilozair@gmail.com>
|
113 |
+
Oleksandr Gituliar <gituliar@gmail.com>
|
114 |
+
Sean Vig <sean.v.775@gmail.com>
|
115 |
+
Prafullkumar P. Tale <hector1618@gmail.com>
|
116 |
+
Vladimir Perić <vlada.peric@gmail.com>
|
117 |
+
Tom Bachmann <e_mc_h2@web.de>
|
118 |
+
Yuri Karadzhov <yuri.karadzhov@gmail.com>
|
119 |
+
Vladimir Lagunov <werehuman@gmail.com>
|
120 |
+
Matthew Rocklin <mrocklin@cs.uchicago.edu>
|
121 |
+
Saptarshi Mandal <sapta.iitkgp@gmail.com>
|
122 |
+
Gilbert Gede <gilbertgede@gmail.com>
|
123 |
+
Anatolii Koval <weralwolf@gmail.com>
|
124 |
+
Tomo Lazovich <lazovich@gmail.com>
|
125 |
+
Pavel Fedotov <fedotovp@gmail.com>
|
126 |
+
Jack McCaffery <jpmccaffery@gmail.com>
|
127 |
+
Jeremias Yehdegho <j.yehdegho@gmail.com>
|
128 |
+
Kibeom Kim <kk1674@nyu.edu>
|
129 |
+
Gregory Ksionda <ksiondag846@gmail.com>
|
130 |
+
Tomáš Bambas <tomas.bambas@gmail.com>
|
131 |
+
Raymond Wong <rayman_407@yahoo.com>
|
132 |
+
Luca Weihs <astronomicalcuriosity@gmail.com>
|
133 |
+
Shai 'Deshe' Wyborski <shaide@cs.huji.ac.il>
|
134 |
+
Thomas Wiecki <thomas.wiecki@gmail.com>
|
135 |
+
Óscar Nájera <najera.oscar@gmail.com>
|
136 |
+
Mario Pernici <mario.pernici@gmail.com>
|
137 |
+
Benjamin McDonald <mcdonald.ben@gmail.com>
|
138 |
+
Sam Magura <samtheman132@gmail.com>
|
139 |
+
Stefan Krastanov <krastanov.stefan@gmail.com>
|
140 |
+
Bradley Froehle <brad.froehle@gmail.com>
|
141 |
+
Min Ragan-Kelley <benjaminrk@gmail.com>
|
142 |
+
Emma Hogan <ehogan@gemini.edu>
|
143 |
+
Nikhil Sarda <diff.operator@gmail.com>
|
144 |
+
Julien Rioux <julien.rioux@gmail.com>
|
145 |
+
Roberto Colistete, Jr. <roberto.colistete@gmail.com>
|
146 |
+
Raoul Bourquin <raoulb@bluewin.ch>
|
147 |
+
Gert-Ludwig Ingold <gert.ingold@physik.uni-augsburg.de>
|
148 |
+
Srinivas Vasudevan <srvasude@gmail.com>
|
149 |
+
Jason Moore <moorepants@gmail.com>
|
150 |
+
Miha Marolt <tloramus@gmail.com>
|
151 |
+
Tim Lahey <tim.lahey@gmail.com>
|
152 |
+
Luis Garcia <ppn.online@me.com>
|
153 |
+
Matt Rajca <matt.rajca@me.com>
|
154 |
+
David Li <l33tnerd.li@gmail.com>
|
155 |
+
Alexandr Gudulin <alexandr.gudulin@gmail.com>
|
156 |
+
Bilal Akhtar <bilalakhtar@ubuntu.com>
|
157 |
+
Grzegorz Świrski <sognat@gmail.com>
|
158 |
+
Matt Habel <habelinc@gmail.com>
|
159 |
+
David Ju <Sgtmook314@gmail.com>
|
160 |
+
Nichita Utiu <nikita.utiu+github@gmail.com>
|
161 |
+
Nikolay Lazarov <qwerqwerqwer@abv.bg>
|
162 |
+
Steve Anton <anxuiz.nx@gmail.com>
|
163 |
+
Imran Ahmed Manzoor <imran.manzoor31@gmail.com>
|
164 |
+
Ljubiša Moćić <3rdslasher@gmail.com>
|
165 |
+
Piotr Korgul <p.korgul@gmail.com>
|
166 |
+
Jim Zhang <Hyriodula@gmail.com>
|
167 |
+
Sam Sleight <samuel.sleight@gmail.com>
|
168 |
+
tborisova <ts.borisova3@gmail.com>
|
169 |
+
Chancellor Arkantos <Chancellor_Arkantos@hotmail.co.uk>
|
170 |
+
Stepan Simsa <simsa.st@gmail.com>
|
171 |
+
Tobias Lenz <t_lenz94@web.de>
|
172 |
+
Siddhanathan Shanmugam <siddhanathan@gmail.com>
|
173 |
+
Tiffany Zhu <bubble.wubble.303@gmail.com>
|
174 |
+
Tristan Hume <tris.hume@gmail.com>
|
175 |
+
Alexey Subach <alexey.subach@gmail.com>
|
176 |
+
Joan Creus <joan.creus.c@gmail.com>
|
177 |
+
Geoffry Song <goffrie@gmail.com>
|
178 |
+
Puneeth Chaganti <punchagan@gmail.com>
|
179 |
+
Marcin Kostrzewa <>
|
180 |
+
Natalia Nawara <fankalemura@gmail.com>
|
181 |
+
vishal <vishal.panjwani15@gmail.com>
|
182 |
+
Shruti Mangipudi <shruti2395@gmail.com>
|
183 |
+
Davy Mao <e_equals_mass_speed_light_squared@hotmail.com>
|
184 |
+
Swapnil Agarwal <swapnilag29@gmail.com>
|
185 |
+
Dhia Kennouche <kendhia@gmail.com>
|
186 |
+
jerryma1121 <jerryma1121@gmail.com>
|
187 |
+
Joachim Durchholz <jo@durchholz.org>
|
188 |
+
Martin Povišer <martin.povik@gmail.com>
|
189 |
+
Siddhant Jain <getsiddhant@gmail.com>
|
190 |
+
Kevin Hunter <hunteke@earlham.edu>
|
191 |
+
Michael Mayorov <marchael@kb.csu.ru>
|
192 |
+
Nathan Alison <nathan.f.alison@gmail.com>
|
193 |
+
Christian Bühler <christian@cbuehler.de>
|
194 |
+
Carsten Knoll <CarstenKnoll@gmx.de>
|
195 |
+
Bharath M R <catchmrbharath@gmail.com>
|
196 |
+
Matthias Toews <mat.toews@googlemail.com>
|
197 |
+
Sergiu Ivanov <unlimitedscolobb@gmail.com>
|
198 |
+
Jorge E. Cardona <jorgeecardona@gmail.com>
|
199 |
+
Sanket Agarwal <sanket@sanketagarwal.com>
|
200 |
+
Manoj Babu K. <manoj.babu2378@gmail.com>
|
201 |
+
Sai Nikhil <tsnlegend@gmail.com>
|
202 |
+
Aleksandar Makelov <amakelov@college.harvard.edu>
|
203 |
+
Sachin Irukula <sachin.irukula@gmail.com>
|
204 |
+
Raphael Michel <webmaster@raphaelmichel.de>
|
205 |
+
Ashwini Oruganti <ashwini.oruganti@gmail.com>
|
206 |
+
Andreas Klöckner <inform@tiker.net>
|
207 |
+
Prateek Papriwal <papriwalprateek@gmail.com>
|
208 |
+
Arpit Goyal <agmps18@gmail.com>
|
209 |
+
Angadh Nanjangud <angadh.n@gmail.com>
|
210 |
+
Comer Duncan <comer.duncan@gmail.com>
|
211 |
+
Jens H. Nielsen <jenshnielsen@gmail.com>
|
212 |
+
Joseph Dougherty <Github@JWDougherty.com>
|
213 |
+
Elliot Marshall <Marshall2389@gmail.com>
|
214 |
+
Guru Devanla <grdvnl@gmail.com>
|
215 |
+
George Waksman <waksman@gwax.com>
|
216 |
+
Alexandr Popov <alexandr.s.popov@gmail.com>
|
217 |
+
Tarun Gaba <tarun.gaba7@gmail.com>
|
218 |
+
Takafumi Arakaki <aka.tkf@gmail.com>
|
219 |
+
Saurabh Jha <saurabh.jhaa@gmail.com>
|
220 |
+
Rom le Clair <jacen.guardian@gmail.com>
|
221 |
+
Angus Griffith <16sn6uv@gmail.com>
|
222 |
+
Timothy Reluga <treluga@math.psu.edu>
|
223 |
+
Brian Stephanik <xoedusk@gmail.com>
|
224 |
+
Alexander Eberspächer <alex.eberspaecher@gmail.com>
|
225 |
+
Sachin Joglekar <srjoglekar246@gmail.com>
|
226 |
+
Tyler Pirtle <teeler@gmail.com>
|
227 |
+
Vasily Povalyaev <vapovalyaev@gmail.com>
|
228 |
+
Colleen Lee <colleenclee@gmail.com>
|
229 |
+
Matthew Hoff <mhoff14@gmail.com>
|
230 |
+
Niklas Thörne <notrupertthorne@gmail.com>
|
231 |
+
Huijun Mai <m.maihuijun@gmail.com>
|
232 |
+
Marek Šuppa <mr@shu.io>
|
233 |
+
Ramana Venkata <idlike2dream@gmail.com>
|
234 |
+
Prasoon Shukla <prasoon92.iitr@gmail.com>
|
235 |
+
Stefen Yin <zqyin@ucdavis.edu>
|
236 |
+
Thomas Hisch <t.hisch@gmail.com>
|
237 |
+
Madeleine Ball <mpball@gmail.com>
|
238 |
+
Mary Clark <mary.spriteling@gmail.com>
|
239 |
+
Rishabh Dixit <rishabhdixit11@gmail.com>
|
240 |
+
Manoj Kumar <manojkumarsivaraj334@gmail.com>
|
241 |
+
Akshit Agarwal <akshit.jiit@gmail.com>
|
242 |
+
CJ Carey <perimosocordiae@gmail.com>
|
243 |
+
Patrick Lacasse <patrick.m.lacasse@gmail.com>
|
244 |
+
Ananya H <ananyaha93@gmail.com>
|
245 |
+
Tarang Patel <tarangrockr@gmail.com>
|
246 |
+
Christopher Dembia <cld72@cornell.edu>
|
247 |
+
Benjamin Fishbein <fishbeinb@gmail.com>
|
248 |
+
Sean Ge <seange727@gmail.com>
|
249 |
+
Amit Jamadagni <bitsjamadagni@gmail.com>
|
250 |
+
Ankit Agrawal <aaaagrawal@iitb.ac.in>
|
251 |
+
Björn Dahlgren <bjodah@gmail.com>
|
252 |
+
Christophe Saint-Jean <christophe.saint-jean@univ-lr.fr>
|
253 |
+
Demian Wassermann <demian@bwh.harvard.edu>
|
254 |
+
Khagesh Patel <khageshpatel93@gmail.com>
|
255 |
+
Stephen Loo <shikil@yahoo.com>
|
256 |
+
hm <hacman0@gmail.com>
|
257 |
+
Patrick Poitras <acebulf@gmail.com>
|
258 |
+
Katja Sophie Hotz <katja.sophie.hotz@student.tuwien.ac.at>
|
259 |
+
Varun Joshi <joshi.142@osu.edu>
|
260 |
+
Chetna Gupta <cheta.gup@gmail.com>
|
261 |
+
Thilina Rathnayake <thilinarmtb@gmail.com>
|
262 |
+
Max Hutchinson <maxhutch@gmail.com>
|
263 |
+
Shravas K Rao <shravas@gmail.com>
|
264 |
+
Matthew Tadd <matt.tadd@gmail.com>
|
265 |
+
Alexander Hirzel <alex@hirzel.us>
|
266 |
+
Randy Heydon <randy.heydon@clockworklab.net>
|
267 |
+
Oliver Lee <oliverzlee@gmail.com>
|
268 |
+
Seshagiri Prabhu <seshagiriprabhu@gmail.com>
|
269 |
+
Pradyumna <pradyu1993@gmail.com>
|
270 |
+
Erik Welch <erik.n.welch@gmail.com>
|
271 |
+
Eric Nelson <eric.the.red.XLII@gmail.com>
|
272 |
+
Roland Puntaier <roland.puntaier@chello.at>
|
273 |
+
Chris Conley <chrisconley15@gmail.com>
|
274 |
+
Tim Swast <tswast@gmail.com>
|
275 |
+
Dmitry Batkovich <batya239@gmail.com>
|
276 |
+
Francesco Bonazzi <franz.bonazzi@gmail.com>
|
277 |
+
Yuriy Demidov <iurii.demidov@gmail.com>
|
278 |
+
Rick Muller <rpmuller@gmail.com>
|
279 |
+
Manish Gill <gill.manish90@gmail.com>
|
280 |
+
Markus Müller <markus.mueller.1.g@googlemail.com>
|
281 |
+
Amit Saha <amitsaha.in@gmail.com>
|
282 |
+
Jeremy <twobitlogic@gmail.com>
|
283 |
+
QuaBoo <kisonchristian@gmail.com>
|
284 |
+
Stefan van der Walt <stefan@sun.ac.za>
|
285 |
+
David Joyner <wdjoyner@gmail.com>
|
286 |
+
Lars Buitinck <larsmans@gmail.com>
|
287 |
+
Alkiviadis G. Akritas <akritas@uth.gr>
|
288 |
+
Vinit Ravishankar <vinit.ravishankar@gmail.com>
|
289 |
+
Mike Boyle <boyle@astro.cornell.edu>
|
290 |
+
Heiner Kirchhoffer <Heiner.Kirchhoffer@gmail.com>
|
291 |
+
Pablo Puente <ppuedom@gmail.com>
|
292 |
+
James Fiedler <jrfiedler@gmail.com>
|
293 |
+
Harsh Gupta <mail@hargup.in>
|
294 |
+
Tuomas Airaksinen <tuomas.airaksinen@gmail.com>
|
295 |
+
Paul Strickland <p.e.strickland@gmail.com>
|
296 |
+
James Goppert <james.goppert@gmail.com>
|
297 |
+
rathmann <rathmann.os@gmail.com>
|
298 |
+
Avichal Dayal <avichal.dayal@gmail.com>
|
299 |
+
Paul Scott <paul.scott@nicta.com.au>
|
300 |
+
Shipra Banga <bangashipra@gmail.com>
|
301 |
+
Pramod Ch <pramodch14@gmail.com>
|
302 |
+
Akshay <akshaynukala95@gmail.com>
|
303 |
+
Buck Shlegeris <buck2@bruceh15.anu.edu.au>
|
304 |
+
Jonathan Miller <jdmiller93@gmail.com>
|
305 |
+
Edward Schembor <eschemb1@jhu.edu>
|
306 |
+
Rajath Shashidhara <rajaths.rajaths@gmail.com>
|
307 |
+
Zamrath Nizam <zamiguy_ni@yahoo.com>
|
308 |
+
Aditya Shah <adityashah30@gmail.com>
|
309 |
+
Rajat Aggarwal <rajataggarwal1975@gmail.com>
|
310 |
+
Sambuddha Basu <sammygamer@live.com>
|
311 |
+
Zeel Shah <kshah215@gmail.com>
|
312 |
+
Abhinav Chanda <abhinavchanda01@gmail.com>
|
313 |
+
Jim Crist <crist042@umn.edu>
|
314 |
+
Sudhanshu Mishra <mrsud94@gmail.com>
|
315 |
+
Anurag Sharma <anurags92@gmail.com>
|
316 |
+
Soumya Dipta Biswas <sdb1323@gmail.com>
|
317 |
+
Sushant Hiray <hiraysushant@gmail.com>
|
318 |
+
Ben Lucato <ben.lucato@gmail.com>
|
319 |
+
Kunal Arora <kunalarora.135@gmail.com>
|
320 |
+
Henry Gebhardt <hsggebhardt@gmail.com>
|
321 |
+
Dammina Sahabandu <dmsahabandu@gmail.com>
|
322 |
+
Manish Shukla <manish.shukla393@gmail>
|
323 |
+
Ralph Bean <rbean@redhat.com>
|
324 |
+
richierichrawr <richierichrawr@users.noreply.github.com>
|
325 |
+
John Connor <john.theman.connor@gmail.com>
|
326 |
+
Juan Luis Cano Rodríguez <juanlu001@gmail.com>
|
327 |
+
Sahil Shekhawat <sahilshekhawat01@gmail.com>
|
328 |
+
Kundan Kumar <kundankumar18581@gmail.com>
|
329 |
+
Stas Kelvich <stanconn@gmail.com>
|
330 |
+
sevaader <sevaader@gmail.com>
|
331 |
+
Dhruvesh Vijay Parikh <parikhdhruvesh1@gmail.com>
|
332 |
+
Venkatesh Halli <venkatesh.fatality@gmail.com>
|
333 |
+
Lennart Fricke <lennart@die-frickes.eu>
|
334 |
+
Vlad Seghete <vlad.seghete@gmail.com>
|
335 |
+
Shashank Agarwal <shashank.agarwal94@gmail.com>
|
336 |
+
carstimon <carstimon@gmail.com>
|
337 |
+
Pierre Haessig <pierre.haessig@crans.org>
|
338 |
+
Maciej Baranski <getrox.sc@gmail.com>
|
339 |
+
Benjamin Gudehus <hastebrot@gmail.com>
|
340 |
+
Faisal Anees <faisal.iiit@gmail.com>
|
341 |
+
Mark Shoulson <mark@kli.org>
|
342 |
+
Robert Johansson <jrjohansson@gmail.com>
|
343 |
+
Kalevi Suominen <jksuom@gmail.com>
|
344 |
+
Kaushik Varanasi <kaushik.varanasi1@gmail.com>
|
345 |
+
Fawaz Alazemi <Mba7eth@gmail.com>
|
346 |
+
Ambar Mehrotra <mehrotraambar@gmail.com>
|
347 |
+
David P. Sanders <dpsanders@gmail.com>
|
348 |
+
Peter Brady <petertbrady@gmail.com>
|
349 |
+
John V. Siratt <jvsiratt@gmail.com>
|
350 |
+
Sarwar Chahal <chahal.sarwar98@gmail.com>
|
351 |
+
Nathan Woods <charlesnwoods@gmail.com>
|
352 |
+
Colin B. Macdonald <cbm@m.fsf.org>
|
353 |
+
Marcus Näslund <naslundx@gmail.com>
|
354 |
+
Clemens Novak <clemens@familie-novak.net>
|
355 |
+
Mridul Seth <seth.mridul@gmail.com>
|
356 |
+
Craig A. Stoudt <craig.stoudt@gmail.com>
|
357 |
+
Raj <raj454raj@gmail.com>
|
358 |
+
Mihai A. Ionescu <ionescu.a.mihai@gmail.com>
|
359 |
+
immerrr <immerrr@gmail.com>
|
360 |
+
Chai Wah Wu <cwwuieee@gmail.com>
|
361 |
+
Leonid Blouvshtein <leonidbl91@gmail.com>
|
362 |
+
Peleg Michaeli <freepeleg@gmail.com>
|
363 |
+
ck Lux <lux.r.ck@gmail.com>
|
364 |
+
zsc347 <zsc347@gmail.com>
|
365 |
+
Hamish Dickson <hamish.dickson@gmail.com>
|
366 |
+
Michael Gallaspy <gallaspy.michael@gmail.com>
|
367 |
+
Roman Inflianskas <infroma@gmail.com>
|
368 |
+
Duane Nykamp <nykamp@umn.edu>
|
369 |
+
Ted Dokos <tdokos@gmail.com>
|
370 |
+
Sunny Aggarwal <sunnyaggarwal1994@gmail.com>
|
371 |
+
Victor Brebenar <v.brebenar@gmail.com>
|
372 |
+
Akshat Jain <akshat.jain@students.iiit.ac.in>
|
373 |
+
Shivam Vats <shivamvats.iitkgp@gmail.com>
|
374 |
+
Longqi Wang <iqgnol@gmail.com>
|
375 |
+
Juan Felipe Osorio <jfosorio@gmail.com>
|
376 |
+
Ray Cathcart <github@cathcart.us>
|
377 |
+
Lukas Zorich <lukas.zorich@gmail.com>
|
378 |
+
Eric Miller <emiller42@gmail.com>
|
379 |
+
Cody Herbst <cyherbst@gmail.com>
|
380 |
+
Nishith Shah <nishithshah.2211@gmail.com>
|
381 |
+
Amit Kumar <dtu.amit@gmail.com>
|
382 |
+
Yury G. Kudryashov <urkud.urkud@gmail.com>
|
383 |
+
Guillaume Gay <contact@damcb.com>
|
384 |
+
Mihir Wadwekar <m.mihirw@gmail.com>
|
385 |
+
Tuan Manh Lai <laituan245@gmail.com>
|
386 |
+
Asish Panda <asishrocks95@gmail.com>
|
387 |
+
Darshan Chaudhary <deathbullet@gmail.com>
|
388 |
+
Alec Kalinin <alec.kalinin@gmail.com>
|
389 |
+
Ralf Stephan <ralf@ark.in-berlin.de>
|
390 |
+
Aaditya Nair <aadityanair6494@gmail.com>
|
391 |
+
Jayesh Lahori <jlahori92@gmail.com>
|
392 |
+
Harshil Goel <harshil158@gmail.com>
|
393 |
+
Luv Agarwal <agarwal.iiit@gmail.com>
|
394 |
+
Jason Ly <jason.ly@gmail.com>
|
395 |
+
Lokesh Sharma <lokeshhsharma@gmail.com>
|
396 |
+
Sartaj Singh <singhsartaj94@gmail.com>
|
397 |
+
Chris Swierczewski <cswiercz@gmail.com>
|
398 |
+
Konstantin Togoi <konstantin.togoi@gmail.com>
|
399 |
+
Param Singh <paramsingh258@gmail.com>
|
400 |
+
Sumith Kulal <sumith1896@gmail.com>
|
401 |
+
Juha Remes <jremes@outlook.com>
|
402 |
+
Philippe Bouafia <philippe.bouafia@ensea.fr>
|
403 |
+
Peter Schmidt <peter@peterjs.com>
|
404 |
+
Jiaxing Liang <liangjiaxing57@gmail.com>
|
405 |
+
Lucas Jones <lucas@lucasjones.co.uk>
|
406 |
+
Gregory Ashton <gash789@gmail.com>
|
407 |
+
Jennifer White <jcrw122@googlemail.com>
|
408 |
+
Renato Orsino <renato.orsino@gmail.com>
|
409 |
+
Michael Boyle <michael.oliver.boyle@gmail.com>
|
410 |
+
Alistair Lynn <arplynn@gmail.com>
|
411 |
+
Govind Sahai <gsiitbhu@gmail.com>
|
412 |
+
Adam Bloomston <adam@glitterfram.es>
|
413 |
+
Kyle McDaniel <mcdanie5@illinois.edu>
|
414 |
+
Nguyen Truong Duy <truongduy134@yahoo.com>
|
415 |
+
Alex Lindsay <adlinds3@ncsu.edu>
|
416 |
+
Mathew Chong <mathewchong.dev@gmail.com>
|
417 |
+
Jason Siefken <siefkenj@gmail.com>
|
418 |
+
Gaurav Dhingra <gauravdhingra.gxyd@gmail.com>
|
419 |
+
Gao, Xiang <qasdfgtyuiop@gmail.com>
|
420 |
+
Kevin Ventullo <kevin.ventullo@gmail.com>
|
421 |
+
mao8 <thisisma08@gmail.com>
|
422 |
+
Isuru Fernando <isuruf@gmail.com>
|
423 |
+
Shivam Tyagi <shivam.tyagi.apm13@itbhu.ac.in>
|
424 |
+
Richard Otis <richard.otis@outlook.com>
|
425 |
+
Rich LaSota <rjlasota@gmail.com>
|
426 |
+
dustyrockpyle <dustyrockpyle@gmail.com>
|
427 |
+
Anton Akhmerov <anton.akhmerov@gmail.com>
|
428 |
+
Michael Zingale <michael.zingale@stonybrook.edu>
|
429 |
+
Chak-Pong Chung <chakpongchung@gmail.com>
|
430 |
+
David T <derDavidT@users.noreply.github.com>
|
431 |
+
Phil Ruffwind <rf@rufflewind.com>
|
432 |
+
Sebastian Koslowski <koslowski@kit.edu>
|
433 |
+
Kumar Krishna Agrawal <kumar.1994.14@gmail.com>
|
434 |
+
Dustin Gadal <Dustin.Gadal@gmail.com>
|
435 |
+
João Moura <operte@gmail.com>
|
436 |
+
Yu Kobayashi <yukoba@accelart.jp>
|
437 |
+
Shashank Kumar <shashank.kumar.apc13@iitbhu.ac.in>
|
438 |
+
Timothy Cyrus <tcyrus@users.noreply.github.com>
|
439 |
+
Devyani Kota <devyanikota@gmail.com>
|
440 |
+
Keval Shah <kevalshah_96@yahoo.co.in>
|
441 |
+
Dzhelil Rufat <drufat@caltech.edu>
|
442 |
+
Pastafarianist <mr.pastafarianist@gmail.com>
|
443 |
+
Sourav Singh <souravsingh@users.noreply.github.com>
|
444 |
+
Jacob Garber <jgarber1@ualberta.ca>
|
445 |
+
Vinay Singh <csvinay.d@gmail.com>
|
446 |
+
GolimarOurHero <metalera94@hotmail.com>
|
447 |
+
Prashant Tyagi <prashanttyagi221295@gmail.com>
|
448 |
+
Matthew Davis <davisml.md@gmail.com>
|
449 |
+
Tschijnmo TSCHAU <tschijnmotschau@gmail.com>
|
450 |
+
Alexander Bentkamp <bentkamp@gmail.com>
|
451 |
+
Jack Kemp <metaknightdrake-git@yahoo.co.uk>
|
452 |
+
Kshitij Saraogi <KshitijSaraogi@gmail.com>
|
453 |
+
Thomas Baruchel <baruchel@gmx.com>
|
454 |
+
Nicolás Guarín-Zapata <nicoguarin@gmail.com>
|
455 |
+
Jens Jørgen Mortensen <jj@smoerhul.dk>
|
456 |
+
Sampad Kumar Saha <sampadsaha5@gmail.com>
|
457 |
+
Eva Charlotte Mayer <eva-charlotte.mayer@posteo.de>
|
458 |
+
Laura Domine <temigo@gmx.com>
|
459 |
+
Justin Blythe <jblythe29@gmail.com>
|
460 |
+
Meghana Madhyastha <meghana.madhyastha@gmail.com>
|
461 |
+
Tanu Hari Dixit <tokencolour@gmail.com>
|
462 |
+
Shekhar Prasad Rajak <shekharrajak@live.com>
|
463 |
+
Aqnouch Mohammed <aqnouch.mohammed@gmail.com>
|
464 |
+
Arafat Dad Khan <arafat.da.khan@gmail.com>
|
465 |
+
Boris Atamanovskiy <shaomoron@gmail.com>
|
466 |
+
Sam Tygier <sam.tygier@hep.manchester.ac.uk>
|
467 |
+
Jai Luthra <me@jailuthra.in>
|
468 |
+
Guo Xingjian <Seeker1995@gmail.com>
|
469 |
+
Sandeep Veethu <sandeep.veethu@gmail.com>
|
470 |
+
Archit Verma <architv07@gmail.com>
|
471 |
+
Shubham Tibra <shubh.tibra@gmail.com>
|
472 |
+
Ashutosh Saboo <ashutosh.saboo96@gmail.com>
|
473 |
+
Michael S. Hansen <michael.hansen@nih.gov>
|
474 |
+
Anish Shah <shah.anish07@gmail.com>
|
475 |
+
Guillaume Jacquenot <guillaume.jacquenot@gmail.com>
|
476 |
+
Bhautik Mavani <mavanibhautik@gmail.com>
|
477 |
+
Michał Radwański <enedil.isildur@gmail.com>
|
478 |
+
Jerry Li <jerry@jerryli.ca>
|
479 |
+
Pablo Zubieta <pabloferz@yahoo.com.mx>
|
480 |
+
Shivam Agarwal <knowthyself2503@gmail.com>
|
481 |
+
Chaitanya Sai Alaparthi <achaitanyasai@gmail.com>
|
482 |
+
Arihant Parsoya <parsoyaarihant@gmail.com>
|
483 |
+
Ruslan Pisarev <rpisarev@cloudlinux.com>
|
484 |
+
Akash Trehan <akash.trehan123@gmail.com>
|
485 |
+
Nishant Nikhil <nishantiam@gmail.com>
|
486 |
+
Vladimir Poluhsin <vovapolu@gmail.com>
|
487 |
+
Akshay Nagar <awesomeay13@yahoo.com>
|
488 |
+
James Brandon Milam <jmilam343@gmail.com>
|
489 |
+
Abhinav Agarwal <abhinavagarwal1996@gmail.com>
|
490 |
+
Rishabh Daal <rishabhdaal@gmail.com>
|
491 |
+
Sanya Khurana <sanya@monica.in>
|
492 |
+
Aman Deep <amandeep1024@gmail.com>
|
493 |
+
Aravind Reddy <aravindreddy255@gmail.com>
|
494 |
+
Abhishek Verma <iamvermaabhishek@gmail.com>
|
495 |
+
Matthew Parnell <matt@parnmatt.co.uk>
|
496 |
+
Thomas Hickman <Thomas.Hickman42@gmail.com>
|
497 |
+
Akshay Siramdas <akshaysiramdas@gmail.com>
|
498 |
+
YiDing Jiang <yidinggjiangg@gmail.com>
|
499 |
+
Jatin Yadav <jatinyadav25@gmail.com>
|
500 |
+
Matthew Thomas <mnmt@users.noreply.github.com>
|
501 |
+
Rehas Sachdeva <aquannie@gmail.com>
|
502 |
+
Michael Mueller <michaeldmueller7@gmail.com>
|
503 |
+
Srajan Garg <srajan.garg@gmail.com>
|
504 |
+
Prabhjot Singh <prabhjot.nith@gmail.com>
|
505 |
+
Haruki Moriguchi <harukimoriguchi@gmail.com>
|
506 |
+
Tom Gijselinck <tomgijselinck@gmail.com>
|
507 |
+
Nitin Chaudhary <nitinmax1000@gmail.com>
|
508 |
+
Alex Argunov <sajkoooo@gmail.com>
|
509 |
+
Nathan Musoke <nathan.musoke@gmail.com>
|
510 |
+
Abhishek Garg <abhishekgarg119@gmail.com>
|
511 |
+
Dana Jacobsen <dana@acm.org>
|
512 |
+
Vasiliy Dommes <vasdommes@gmail.com>
|
513 |
+
Phillip Berndt <phillip.berndt@googlemail.com>
|
514 |
+
Haimo Zhang <zh.hammer.dev@gmail.com>
|
515 |
+
Anthony Scopatz <scopatz@gmail.com>
|
516 |
+
bluebrook <perl4logic@gmail.com>
|
517 |
+
Leonid Kovalev <leonidvkovalev@gmail.com>
|
518 |
+
Josh Burkart <jburkart@gmail.com>
|
519 |
+
Dimitra Konomi <t8130064@dias.aueb.gr>
|
520 |
+
Christina Zografou <t8130048@dias.aueb.gr>
|
521 |
+
Fiach Antaw <fiach.antaw+github@gmail.com>
|
522 |
+
Langston Barrett <langston.barrett@gmail.com>
|
523 |
+
Krit Karan <kritkaran.b13@iiits.in>
|
524 |
+
G. D. McBain <gdmcbain@protonmail.com>
|
525 |
+
Prempal Singh <prempal.42@gmail.com>
|
526 |
+
Gabriel Orisaka <orisaka@gmail.com>
|
527 |
+
Matthias Bussonnier <bussonniermatthias@gmail.com>
|
528 |
+
rahuldan <rahul02013@gmail.com>
|
529 |
+
Colin Marquardt <github@marquardt-home.de>
|
530 |
+
Andrew Taber <andrew.e.taber@gmail.com>
|
531 |
+
Yash Reddy <write2yashreddy@gmail.com>
|
532 |
+
Peter Stangl <peter.stangl@ph.tum.de>
|
533 |
+
elvis-sik <e.sikora@grad.ufsc.br>
|
534 |
+
Nikos Karagiannakis <nikoskaragiannakis@gmail.com>
|
535 |
+
Jainul Vaghasia <jainulvaghasia@gmail.com>
|
536 |
+
Dennis Meckel <meckel@datenschuppen.de>
|
537 |
+
Harshil Meena <harshil.7535@gmail.com>
|
538 |
+
Micky <mickydroch@gmail.com>
|
539 |
+
Nick Curtis <nicholas.curtis@uconn.edu>
|
540 |
+
Michele Zaffalon <michele.zaffalon@gmail.com>
|
541 |
+
Martha Giannoudovardi <maapxa@gmail.com>
|
542 |
+
Devang Kulshreshtha <devang.kulshreshtha.cse14@itbhu.ac.in>
|
543 |
+
Steph Papanik <spapanik21@gmail.com>
|
544 |
+
Mohammad Sadeq Dousti <msdousti@gmail.com>
|
545 |
+
Arif Ahmed <arif.ahmed.5.10.1995@gmail.com>
|
546 |
+
Abdullah Javed Nesar <abduljaved1994@gmail.com>
|
547 |
+
Lakshya Agrawal <zeeshan.lakshya@gmail.com>
|
548 |
+
shruti <shrutishrm512@gmail.com>
|
549 |
+
Rohit Rango <rohit.rango@gmail.com>
|
550 |
+
Hong Xu <hong@topbug.net>
|
551 |
+
Ivan Petuhov <ivan@ostrovok.ru>
|
552 |
+
Alsheh <alsheh@rpi.edu>
|
553 |
+
Marcel Stimberg <marcel.stimberg@ens.fr>
|
554 |
+
Alexey Pakhocmhik <cool.Bakov@yandex.ru>
|
555 |
+
Tommy Olofsson <tommy.olofsson.90@gmail.com>
|
556 |
+
Zulfikar <zulfikar97@gmail.com>
|
557 |
+
Blair Azzopardi <blairuk@gmail.com>
|
558 |
+
Danny Hermes <daniel.j.hermes@gmail.com>
|
559 |
+
Sergey Pestov <pestov-sa@yandex.ru>
|
560 |
+
Mohit Chandra <mohit.chandra@research.iiit.ac.in>
|
561 |
+
Karthik Chintapalli <karthik.chintapalli@students.iiit.ac.in>
|
562 |
+
Marcin Briański <marcin.brianski@student.uj.edu.pl>
|
563 |
+
andreo <andrey.torba@gmail.com>
|
564 |
+
Flamy Owl <flamyowl@protonmail.ch>
|
565 |
+
Yicong Guo <guoyicong100@gmail.com>
|
566 |
+
Varun Garg <varun.garg03@gmail.com>
|
567 |
+
Rishabh Madan <rishabhmadan96@gmail.com>
|
568 |
+
Aditya Kapoor <aditya.kapoor.apm12@itbhu.ac.in>
|
569 |
+
Karan Sharma <karan1276@gmail.com>
|
570 |
+
Vedant Rathore <vedantr1998@gmail.com>
|
571 |
+
Johan Blåbäck <johan_bluecreek@riseup.net>
|
572 |
+
Pranjal Tale <pranjaltale16@gmail.com>
|
573 |
+
Jason Tokayer <jason.tokayer@gmail.com>
|
574 |
+
Raghav Jajodia <jajodia.raghav@gmail.com>
|
575 |
+
Rajat Thakur <rajatthakur1997@gmail.com>
|
576 |
+
Dhruv Bhanushali <dhruv_b@live.com>
|
577 |
+
Anjul Kumar Tyagi <anjul.ten@gmail.com>
|
578 |
+
Barun Parruck <barun.parruck@gmail.com>
|
579 |
+
Bao Chau <chauquocbao0907@gmail.com>
|
580 |
+
Tanay Agrawal <tanay_agrawal@hotmail.com>
|
581 |
+
Ranjith Kumar <ranjith.dakshana2015@gmail.com>
|
582 |
+
Shikhar Makhija <shikharmakhija2@gmail.com>
|
583 |
+
Yathartha Joshi <yathartha32@gmail.com>
|
584 |
+
Valeriia Gladkova <valeriia.gladkova@gmail.com>
|
585 |
+
Sagar Bharadwaj <sagarbharadwaj50@gmail.com>
|
586 |
+
Daniel Mahler <dmahler@gmail.com>
|
587 |
+
Ka Yi <chua.kayi@yahoo.com.sg>
|
588 |
+
Rishat Iskhakov <iskhakov@frtk.ru>
|
589 |
+
Szymon Mieszczak <szymon.mieszczak@gmail.com>
|
590 |
+
Sachin Agarwal <sachinagarwal0499@gmail.com>
|
591 |
+
Priyank Patel <pspbot7@gmail.com>
|
592 |
+
Satya Prakash Dwibedi <akash581050@gmail.com>
|
593 |
+
tools4origins <tools4origins@gmail.com>
|
594 |
+
Nico Schlömer <nico.schloemer@gmail.com>
|
595 |
+
Fermi Paradox <FermiParadox@users.noreply.github.com>
|
596 |
+
Ekansh Purohit <purohit.e15@gmail.com>
|
597 |
+
Vedarth Sharma <vedarth.sharma@gmail.com>
|
598 |
+
Peeyush Kushwaha <peeyush.p97@gmail.com>
|
599 |
+
Jayjayyy <vfhsln8s3l4b87t4c3@byom.de>
|
600 |
+
Christopher J. Wright <cjwright4242gh@gmail.com>
|
601 |
+
Jakub Wilk <jwilk@jwilk.net>
|
602 |
+
Mauro Garavello <mauro.garavello@unimib.it>
|
603 |
+
Chris Tefer <ctefer@gmail.com>
|
604 |
+
Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
605 |
+
Chiu-Hsiang Hsu <wdv4758h@gmail.com>
|
606 |
+
Carlos Cordoba <ccordoba12@gmail.com>
|
607 |
+
Fabian Ball <fabian.ball@kit.edu>
|
608 |
+
Yerniyaz <yerniyaz.nurgabylov@nu.edu.kz>
|
609 |
+
Christiano Anderson <canderson@riseup.net>
|
610 |
+
Robin Neatherway <robin.neatherway@gmail.com>
|
611 |
+
Thomas Hunt <thomashunt13@gmail.com>
|
612 |
+
Theodore Han <theodorehan@hotmail.com>
|
613 |
+
Duc-Minh Phan <alephvn@gmail.com>
|
614 |
+
Lejla Metohajrova <l.metohajrova@gmail.com>
|
615 |
+
Samyak Jain <samyak.jain2016a@vitstudent.ac.in>
|
616 |
+
Aditya Rohan <riyuzakiiitk@gmail.com>
|
617 |
+
Vincent Delecroix <vincent.delecroix@labri.fr>
|
618 |
+
Michael Sparapany <msparapa@purdue.edu>
|
619 |
+
Harsh Jain <harshjniitr@gmail.com>
|
620 |
+
Nathan Goldbaum <ngoldbau@illinois.edu>
|
621 |
+
latot <felipematas@yahoo.com>
|
622 |
+
Kenneth Lyons <ixjlyons@gmail.com>
|
623 |
+
Stan Schymanski <stan.schymanski@env.ethz.ch>
|
624 |
+
David Daly <david.daly12@kzoo.edu>
|
625 |
+
Ayush Shridhar <ayush.shridhar1999@gmail.com>
|
626 |
+
Javed Nissar <javednissar@gmail.com>
|
627 |
+
Jiri Kuncar <jiri.kuncar@gmail.com>
|
628 |
+
vedantc98 <vedantc98@gmail.com>
|
629 |
+
Rupesh Harode <rupeshharode@gmail.com>
|
630 |
+
Rob Zinkov <rob@zinkov.com>
|
631 |
+
James Harrop <ebc121@gmail.com>
|
632 |
+
James Taylor <user234683@tutanota.com>
|
633 |
+
Ishan Joshi <ishanaj98@gmail.com>
|
634 |
+
Marco Mancini <marco.mancini@obspm.fr>
|
635 |
+
Boris Ettinger <ettinger.boris@gmail.com>
|
636 |
+
Micah Fitch <micahscopes@gmail.com>
|
637 |
+
Daniel Wennberg <daniel.wennberg@gmail.com>
|
638 |
+
ylemkimon <ylemkimon@naver.com>
|
639 |
+
Akash Vaish <akash.9712@gmail.com>
|
640 |
+
Peter Enenkel <peter.enenkel+git@gmail.com>
|
641 |
+
Waldir Pimenta <waldyrious@gmail.com>
|
642 |
+
Jithin D. George <jithindgeorge93@gmail.com>
|
643 |
+
Lev Chelyadinov <leva181777@gmail.com>
|
644 |
+
Lucas Wiman <lucas.wiman@gmail.com>
|
645 |
+
Rhea Parekh <rheaparekh12@gmail.com>
|
646 |
+
James Cotton <peabody124@gmail.com>
|
647 |
+
Robert Pollak <robert.pollak@posteo.net>
|
648 |
+
anca-mc <anca-mc@users.noreply.github.com>
|
649 |
+
Sourav Ghosh <souravghosh2197@gmail.com>
|
650 |
+
Jonathan Allan <jjallan@users.noreply.github.com>
|
651 |
+
Nikhil Pappu <nkhlpappu@gmail.com>
|
652 |
+
Ethan Ward <etkewa@gmail.com>
|
653 |
+
Cezary Marczak <zeddq1@gmail.com>
|
654 |
+
dps7ud <dps7ud@virginia.edu>
|
655 |
+
Nilabja Bhattacharya <nilabja10201992@gmail.com>
|
656 |
+
Itay4 <31018228+Itay4@users.noreply.github.com>
|
657 |
+
Poom Chiarawongse <eight1911@gmail.com>
|
658 |
+
Yang Yang <wdscxsj@gmail.com>
|
659 |
+
Cavendish McKay <cmckay@tachycline.com>
|
660 |
+
Bradley Gannon <bradley.m.gannon@gmail.com>
|
661 |
+
B McG <bmcg0890@gmail.com>
|
662 |
+
Rob Drynkin <rob.drynkin@gmail.com>
|
663 |
+
Seth Ebner <murgrehk@gmail.com>
|
664 |
+
Akash Kundu <sk.sayakkundu1997@gmail.com>
|
665 |
+
Mark Jeromin <mark.jeromin@sysfrog.net>
|
666 |
+
Roberto Díaz Pérez <r.r.1994a@gmail.com>
|
667 |
+
Gleb Siroki <g.shiroki@gmail.com>
|
668 |
+
Segev Finer <segev208@gmail.com>
|
669 |
+
Alex Lubbock <code@alexlubbock.com>
|
670 |
+
Ayodeji Ige <ayodeji18@outlook.com>
|
671 |
+
Matthew Wardrop <matthew.wardrop@airbnb.com>
|
672 |
+
Hugo van Kemenade <hugovk@users.noreply.github.com>
|
673 |
+
Austin Palmer <ap4000@nyu.edu>
|
674 |
+
der-blaue-elefant <github@kklein.de>
|
675 |
+
Filip Gokstorp <filip@gokstorp.se>
|
676 |
+
Yuki Matsuda <yuki.matsuda.w@gmail.com>
|
677 |
+
Aaron Miller <acmiller273@gmail.com>
|
678 |
+
Salil Vishnu Kapur <salilvishnukapur@gmail.com>
|
679 |
+
Atharva Khare <khareatharva@gmail.com>
|
680 |
+
Shubham Maheshwari <rmaheshwari05@gmail.com>
|
681 |
+
Pavel Tkachenko <paveltkachenko@email.com>
|
682 |
+
Ashish Kumar Gaurav <ashishkg0022@gmail.com>
|
683 |
+
Rajeev Singh <rajs2010@gmail.com>
|
684 |
+
Keno Goertz <keno@goertz-berlin.com>
|
685 |
+
Lucas Gallindo <lgallindo@gmail.com>
|
686 |
+
Himanshu <hs80941@gmail.com>
|
687 |
+
David Menéndez Hurtado <david.menendez.hurtado@scilifelab.se>
|
688 |
+
Amit Manchanda <amitdelhi1995@gmail.com>
|
689 |
+
Rohit Jain <rohitjain3241@gmail.com>
|
690 |
+
Jonathan A. Gross <jarthurgross@gmail.com>
|
691 |
+
Unknown <kunda@scribus.net>
|
692 |
+
Sayan Goswami <Sayan98@users.noreply.github.com>
|
693 |
+
Subhash Saurabh <subhashsaurabh419@gmail.com>
|
694 |
+
Rastislav Rabatin <rastislav.rabatin@gmail.com>
|
695 |
+
Vishal <vishalg2235@gmail.com>
|
696 |
+
Jeremey Gluck <jeremygluck@yahoo.com>
|
697 |
+
Akshat Maheshwari <akshat14714@gmail.com>
|
698 |
+
symbolique <symbolique@users.noreply.github.com>
|
699 |
+
Saloni Jain <tosalonijain@gmail.com>
|
700 |
+
Arighna Chakrabarty <arighna.chakrabarty100@gmail.com>
|
701 |
+
Abhigyan Khaund <mail@abhigyan.xyz>
|
702 |
+
Jashanpreet Singh <jashansingh.4398@gmail.com>
|
703 |
+
Saurabh Agarwal <shourabh.agarwal@gmail.com>
|
704 |
+
luzpaz <luzpaz@users.noreply.github.com>
|
705 |
+
P. Sai Prasanth <psai.prasanth.min16@itbhu.ac.in>
|
706 |
+
Nirmal Sarswat <nirmalsarswat400@gmail.com>
|
707 |
+
Cristian Di Pietrantonio <cristiandipietrantonio@gmail.com>
|
708 |
+
Ravi charan <ravicharan.vsp@gmail.com>
|
709 |
+
Nityananda Gohain <nityanandagohain@gmail.com>
|
710 |
+
Cédric Travelletti <cedrictravelletti@gmail.com>
|
711 |
+
Nicholas Bollweg <nick.bollweg@gmail.com>
|
712 |
+
Himanshu Ladia <hladia199811@gmail.com>
|
713 |
+
Adwait Baokar <adwaitbaokar18@gmail.com>
|
714 |
+
Mihail Tarigradschi <m.tarigradschi@gmail.com>
|
715 |
+
Saketh <alurusaisaketh@gmail.com>
|
716 |
+
rushyam <rushyamsonu@gmail.com>
|
717 |
+
sfoo <sfoohei@gmail.com>
|
718 |
+
Rahil Hastu <rahilhastu@gmail.com>
|
719 |
+
Zach Raines <raineszm@gmail.com>
|
720 |
+
Sidhant Nagpal <sidhantnagpal97@gmail.com>
|
721 |
+
Gagandeep Singh <singh.23@iitj.ac.in>
|
722 |
+
Rishav Chakraborty <annonymousxyz@outlook.com>
|
723 |
+
Malkhan Singh <malkhansinghrathaur@gmail.com>
|
724 |
+
Joaquim Monserrat <qmonserrat@mailoo.org>
|
725 |
+
Mayank Singh <mayank.singh081997@gmail.com>
|
726 |
+
Rémy Léone <rleone@online.net>
|
727 |
+
Maxence Mayrand <35958639+maxencemayrand@users.noreply.github.com>
|
728 |
+
Nikoleta Glynatsi <GlynatsiNE@cardiff.ac.uk>
|
729 |
+
helo9 <helo9@users.noreply.github.com>
|
730 |
+
Ken Wakita <wakita@is.titech.ac.jp>
|
731 |
+
Carl Sandrock <carl.sandrock@up.ac.za>
|
732 |
+
Fredrik Eriksson <freeriks@student.chalmers.se>
|
733 |
+
Ian Swire <oversizedpenguin@gmail.com>
|
734 |
+
Bulat <daianovich@mail.ru>
|
735 |
+
Ehren Metcalfe <ehren.m@gmail.com>
|
736 |
+
Dmitry Savransky <dsavransky@gmail.com>
|
737 |
+
Kiyohito Yamazaki <kyamaz@openql.org>
|
738 |
+
Caley Finn <caleyreuben@gmail.com>
|
739 |
+
Zhi-Qiang Zhou <zzq_890709@hotmail.com>
|
740 |
+
Alexander Pozdneev <pozdneev@users.noreply.github.com>
|
741 |
+
Wes Turner <50891+westurner@users.noreply.github.com>
|
742 |
+
JMSS-Unknown <31131631+JMSS-Unknown@users.noreply.github.com>
|
743 |
+
Arshdeep Singh <singh.arshdeep1999@gmail.com>
|
744 |
+
cym1 <16437732+cym1@users.noreply.github.com>
|
745 |
+
Stewart Wadsworth <stewart.wadsworth@gmail.com>
|
746 |
+
Jared Lumpe <mjlumpe@gmail.com>
|
747 |
+
Avi Shrivastava <shrivastavaavi123@gmail.com>
|
748 |
+
ramvenkat98 <ramvenkat98@gmail.com>
|
749 |
+
Bilal Ahmed <b.ahmed0918@gmail.com>
|
750 |
+
Dimas Abreu Archanjo Dutra <dimasad@ufmg.br>
|
751 |
+
Yatna Verma <yatnavermaa@gmail.com>
|
752 |
+
S.Y. Lee <sylee957@gmail.com>
|
753 |
+
Miro Hrončok <miro@hroncok.cz>
|
754 |
+
Sudarshan Kamath <sudarshan.kamath97@gmail.com>
|
755 |
+
Ayushman Koul <ayushmankoul4570@gmail.com>
|
756 |
+
Robert Dougherty-Bliss <robert.w.bliss@gmail.com>
|
757 |
+
Andrey Grozin <A.G.Grozin@inp.nsk.su>
|
758 |
+
Bavish Kulur <bavishkulur@gmail.com>
|
759 |
+
Arun Singh <arunsin997@gmail.com>
|
760 |
+
sirnicolaf <43586954+sirnicolaf@users.noreply.github.com>
|
761 |
+
Zachariah Etienne <zachetie@gmail.com>
|
762 |
+
Prayush Dawda <35144226+iamprayush@users.noreply.github.com>
|
763 |
+
2torus <boris.ettinger@gmail.com>
|
764 |
+
Faisal Riyaz <faisalriyaz011@gmail.com>
|
765 |
+
Martin Roelfs <u0114255@kuleuven.be>
|
766 |
+
SirJohnFranklin <sirjfu@googlemail.com>
|
767 |
+
Anthony Sottile <asottile@umich.edu>
|
768 |
+
ViacheslavP <public.viacheslav@gmail.com>
|
769 |
+
Safiya03 <safiyanesar@gmail.com>
|
770 |
+
Alexander Dunlap <alexander.dunlap@gmail.com>
|
771 |
+
Rohit Sharma <31184621+rohitx007@users.noreply.github.com>
|
772 |
+
Jonathan Warner <warnerjon12@gmail.com>
|
773 |
+
Mohit Balwani <mohitbalwani.ict17@gmail.com>
|
774 |
+
Marduk Bolaños <mardukbp@mac.com>
|
775 |
+
amsuhane <ayushsuhane99@iitkgp.ac.in>
|
776 |
+
Matthias Geier <Matthias.Geier@gmail.com>
|
777 |
+
klaasvanaarsen <44929042+klaasvanaarsen@users.noreply.github.com>
|
778 |
+
Shubham Kumar Jha <skjha832@gmail.com>
|
779 |
+
rationa-kunal <kunalgk1999@gmail.com>
|
780 |
+
Animesh Sinha <animeshsinha1309@gmail.com>
|
781 |
+
Gaurang Tandon <1gaurangtandon@gmail.com>
|
782 |
+
Matthew Craven <clyring@users.noreply.github.com>
|
783 |
+
Daniel Ingram <ingramds@appstate.edu>
|
784 |
+
Jogi Miglani <jmig5776@gmail.com>
|
785 |
+
Takumasa Nakamura <n.takumasa@gmail.com>
|
786 |
+
Ritu Raj Singh <RituRajSingh878@gmail.com>
|
787 |
+
Rajiv Ranjan Singh <rajivperfect007@gmail.com>
|
788 |
+
Vera Lozhkina <veralozhkina@gmail.com>
|
789 |
+
adhoc-king <46354827+adhoc-king@users.noreply.github.com>
|
790 |
+
Mikel Rouco <mikel.mrm@gmail.com>
|
791 |
+
Oscar Gustafsson <oscar.gustafsson@gmail.com>
|
792 |
+
damianos <damianos@semmle.com>
|
793 |
+
Supreet Agrawal <supreet11agrawal@gmail.com>
|
794 |
+
shiksha11 <shiksharawat01@gmail.com>
|
795 |
+
Martin Ueding <dev@martin-ueding.de>
|
796 |
+
sharma-kunal <kunalsharma6914@gmail.com>
|
797 |
+
Divyanshu Thakur <divyanshu@iiitmanipur.ac.in>
|
798 |
+
Susumu Ishizuka <susumu.ishizuka@kii.com>
|
799 |
+
Samnan Rahee <namanush.rsr.16@gmail.com>
|
800 |
+
Fredrik Andersson <fredrik.andersson@fcc.chalmers.se>
|
801 |
+
Bhavya Srivastava <bhavya17037@iiitd.ac.in>
|
802 |
+
Alpesh Jamgade <alpeshjamgade21@gmail.com>
|
803 |
+
Shubham Abhang <shubhamabhang77@gmail.com>
|
804 |
+
Vishesh Mangla <manglavishesh64@gmail.com>
|
805 |
+
Nicko van Someren <nicko@nicko.org>
|
806 |
+
dandiez <47832466+dandiez@users.noreply.github.com>
|
807 |
+
Frédéric Chapoton <fchapoton2@gmail.com>
|
808 |
+
jhanwar <f2015463@pilani.bits-pilani.ac.in>
|
809 |
+
Noumbissi valere Gille Geovan <noumbissivalere@gmail.com>
|
810 |
+
Salmista-94 <alejandrogroso@hotmail.com>
|
811 |
+
Shivani Kohli <shivanikohli.09@gmail.com>
|
812 |
+
Parker Berry <parkereberry@gmail.com>
|
813 |
+
Pragyan Mehrotra <pragyan18168@iiitd.ac.in>
|
814 |
+
Nabanita Dash <dashnabanita@gmail.com>
|
815 |
+
Gaetano Guerriero <x.guerriero@tin.it>
|
816 |
+
Ankit Raj Pandey <pandeyan@grinnell.edu>
|
817 |
+
Ritesh Kumar <ritesh99rakesh@gmail.com>
|
818 |
+
kangzhiq <709563092@qq.com>
|
819 |
+
Jun Lin <junlin0604@gmail.com>
|
820 |
+
Petr Kungurtsev <corwinat@gmail.com>
|
821 |
+
Anway De <anway1756@gmail.com>
|
822 |
+
znxftw <vishnu2101@gmail.com>
|
823 |
+
Denis Ivanenko <ivanenko@ucu.edu.ua>
|
824 |
+
Orestis Vaggelis <orestisvaggelis@mail.com>
|
825 |
+
Nikhil Maan <nikhilmaan22@gmail.com>
|
826 |
+
Abhinav Anand <abhinav.anand2807@gmail.com>
|
827 |
+
Qingsha Shi <googol.sqs@gmail.com>
|
828 |
+
Juan Barbosa <js.barbosa10@uniandes.edu.co>
|
829 |
+
Prionti Nasir <pdn3628@rit.edu>
|
830 |
+
Bharat Raghunathan <bharatraghunthan9767@gmail.com>
|
831 |
+
arooshiverma <av22@iitbbs.ac.in>
|
832 |
+
Christoph Gohle <ctg@mpq.mpg.de>
|
833 |
+
Charalampos Tsiagkalis <ctsiagkalis@uth.gr>
|
834 |
+
Daniel Sears <highpost@users.noreply.github.com>
|
835 |
+
Megan Ly <megan.ly@learnosity.com>
|
836 |
+
Sean P. Cornelius <spcornelius@gmail.com>
|
837 |
+
Erik R. Gomez <gomez@kth.se>
|
838 |
+
Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
|
839 |
+
Henry Metlov <genrih.metlov@gmail.com>
|
840 |
+
pekochun <hamburg_hamburger2000@yahoo.co.jp>
|
841 |
+
Bendik Samseth <b.samseth@gmail.com>
|
842 |
+
Vighnesh Shenoy <vighneshq@gmail.com>
|
843 |
+
Versus Void <versusvoid@gmail.com>
|
844 |
+
Denys Rybalka <rybalka.denis@gmail.com>
|
845 |
+
Mark Dickinson <dickinsm@gmail.com>
|
846 |
+
Rimi <rimibis@umich.edu>
|
847 |
+
rimibis <33387803+rimibis@users.noreply.github.com>
|
848 |
+
Steven Lee <stevenlee123@protonmail.com>
|
849 |
+
Gilles Schintgen <gschintgen@hambier.lu>
|
850 |
+
Abhi58 <abhijithbharadwaj58@gmail.com>
|
851 |
+
Tomasz Pytel <tompytel@gmail.com>
|
852 |
+
Aadit Kamat <aadit.k12@gmail.com>
|
853 |
+
Samesh <samesh.lakhotia@gmail.com>
|
854 |
+
Velibor Zeli <velibor@mech.kth.se>
|
855 |
+
Gabriel Bernardino <gabriel.bernardino@upf.edu>
|
856 |
+
Joseph Redfern <joseph@redfern.me>
|
857 |
+
Evelyn King <evelyn.cameron.king@gmail.com>
|
858 |
+
Miguel Marco <mmarco@unizar.es>
|
859 |
+
David Hagen <david@drhagen.com>
|
860 |
+
Hannah Kari <hannah.kari@marquette.edu>
|
861 |
+
Soniya Nayak <soniyanayak51@gmail.com>
|
862 |
+
Harsh Agarwal <hagarwal9200@gmail.com>
|
863 |
+
Enric Florit <efz1005@gmail.com>
|
864 |
+
Yogesh Mishra <ymishra013@gmail.com>
|
865 |
+
Denis Rykov <rykovd@gmail.com>
|
866 |
+
Ivan Tkachenko <me@ratijas.tk>
|
867 |
+
Kenneth Emeka Odoh <kenneth.odoh@gmail.com>
|
868 |
+
Stephan Seitz <stephan.seitz@fau.de>
|
869 |
+
Yeshwanth N <yeshsurya@gmail.com>
|
870 |
+
Oscar Gerardo Lazo Arjona <oscar.lazoarjona@physics.ox.ac.uk>
|
871 |
+
Srinivasa Arun Yeragudipati <ysarun1999@gmail.com>
|
872 |
+
Kirtan Mali <kirtanmali555@gmail.com>
|
873 |
+
TitanSnow <sweeto@live.cn>
|
874 |
+
Pengning Chao <8857165+PengningChao@users.noreply.github.com>
|
875 |
+
Louis Abraham <louis.abraham@yahoo.fr>
|
876 |
+
Morten Olsen Lysgaard <morten@lysgaard.no>
|
877 |
+
Akash Nagaraj (akasnaga) <akasnaga@cisco.com>
|
878 |
+
Akash Nagaraj <grassknoted@gmail.com>
|
879 |
+
Lauren Glattly <laurenglattly@gmail.com>
|
880 |
+
Hou-Rui <houruinus@gmail.com>
|
881 |
+
George Korepanov <gkorepanov.gk@gmail.com>
|
882 |
+
dranknight09 <cbhaavan@gmail.com>
|
883 |
+
aditisingh2362 <aditisingh2362@gmail.com>
|
884 |
+
Gina <Dr-G@users.noreply.github.com>
|
885 |
+
gregmedlock <gmedlo@gmail.com>
|
886 |
+
Georgios Giapitzakis Tzintanos <giorgosgiapis@mail.com>
|
887 |
+
Eric Wieser <wieser.eric@gmail.com>
|
888 |
+
Bradley Dowling <34559056+btdow@users.noreply.github.com>
|
889 |
+
Maria Marginean <33810762+mmargin@users.noreply.github.com>
|
890 |
+
Akash Agrawall <akash.wanted@gmail.com>
|
891 |
+
jgulian <josephdgulian@gmail.com>
|
892 |
+
Sourav Goyal <souravgl0@gmail.com>
|
893 |
+
Zlatan Vasović <zlatanvasovic@gmail.com>
|
894 |
+
Alex Meiburg <timeroot.alex@gmail.com>
|
895 |
+
Smit Lunagariya <smitlunagariya.mat18@itbhu.ac.in>
|
896 |
+
Naman Gera <namangera15@gmail.com>
|
897 |
+
Julien Palard <julien@palard.fr>
|
898 |
+
Dhruv Mendiratta <dhruvmendiratta6@gmail.com>
|
899 |
+
erdOne <36414270+erdOne@users.noreply.github.com>
|
900 |
+
risubaba <risubhjain1010@gmail.com>
|
901 |
+
abhinav28071999 <41710346+abhinav28071999@users.noreply.github.com>
|
902 |
+
Jisoo Song <jeesoo9595@snu.ac.kr>
|
903 |
+
Jaime R <38530589+Jaime02@users.noreply.github.com>
|
904 |
+
Vikrant Malik <vikrantmalik051@gmail.com>
|
905 |
+
Hardik Saini <43683678+Guardianofgotham@users.noreply.github.com>
|
906 |
+
Abhishek <uchiha@pop-os.localdomain>
|
907 |
+
Johannes Hartung <joha2@gmx.net>
|
908 |
+
Milan Jolly <milan.cs16@iitp.ac.in>
|
909 |
+
faizan2700 <syedfaizan824@gmail.com>
|
910 |
+
mohit <39158356+mohitacecode@users.noreply.github.com>
|
911 |
+
Mohit Gupta <mohitgupta@gmail.com>
|
912 |
+
Psycho-Pirate <prakharsaxena.civ18@iitbhu.ac.in>
|
913 |
+
Chanakya-Ekbote <ca10@iitbbs.ac.in>
|
914 |
+
Rashmi Shehana <rashmi.watagedara@syscolabs.com>
|
915 |
+
Jonty16117 <jonty@DESKTOP-J1O6ANP.localdomain>
|
916 |
+
Anubhav Gupta <anubhav.gupta.cse19@itbhu.ac.in>
|
917 |
+
Michal Grňo <m93a.cz@gmail.com>
|
918 |
+
vezeli <37907135+vezeli@users.noreply.github.com>
|
919 |
+
Tim Gates <tim.gates@iress.com>
|
920 |
+
Sandeep Murthy <smurthy@protonmail.ch>
|
921 |
+
Neil <mistersheik@gmail.com>
|
922 |
+
V1krant <46847915+V1krant@users.noreply.github.com>
|
923 |
+
alejandro <amartinhernan@gmail.com>
|
924 |
+
Riyan Dhiman <Riyandhiman14@gmail.com>
|
925 |
+
sbt4104 <sthorat661@gmail.com>
|
926 |
+
Seth Troisi <sethtroisi@google.com>
|
927 |
+
Bhaskar Gupta <guptabhanu1999@gmail.com>
|
928 |
+
Smit Gajjar <smitgajjar.gs@gmail.com>
|
929 |
+
rbl <rlee@grove.co>
|
930 |
+
Ilya Pchelintsev <ilya.pchelintsev@outlook.com>
|
931 |
+
Omar Wagih <o.wagih.ow@gmail.com>
|
932 |
+
prshnt19 <prashant.rawat216@gmail.com>
|
933 |
+
Johan Guzman <jguzm022@ucr.edu>
|
934 |
+
Vasileios Kalos <kalosbasileios@gmail.com>
|
935 |
+
BasileiosKal <61801875+BasileiosKal@users.noreply.github.com>
|
936 |
+
Shubham Thorat <37049710+sbt4104@users.noreply.github.com>
|
937 |
+
Arpan Chattopadhyay <f20180319@pilani.bits-pilani.ac.in>
|
938 |
+
Ashutosh Hathidara <ashutoshhathidara98@gmail.com>
|
939 |
+
Moses Paul R <iammosespaulr@gmail.com>
|
940 |
+
Saanidhya vats <saanidhyavats@gmail.com>
|
941 |
+
tnzl <you@example.com>
|
942 |
+
Vatsal Srivastava <alstav.trivas.sava@gmail.com>
|
943 |
+
Jean-Luc Herren <jlh@gmx.ch>
|
944 |
+
Dhruv Kothari <dhruvkothari22@gmail.com>
|
945 |
+
seadavis <45022599+seadavis@users.noreply.github.com>
|
946 |
+
kamimura <kamimura@live.jp>
|
947 |
+
slacker404 <pchantza@gmail.com>
|
948 |
+
Jaime Resano <gemailpersonal02@gmail.com>
|
949 |
+
Ebrahim Byagowi <ebrahim@gnu.org>
|
950 |
+
wuyudi <wuyudi119@163.com>
|
951 |
+
Akira Kyle <ak@akirakyle.com>
|
952 |
+
Calvin Jay Ross <calvinjayross@gmail.com>
|
953 |
+
Martin Thoma <info@martin-thoma.de>
|
954 |
+
Thomas A Caswell <tcaswell@gmail.com>
|
955 |
+
Lagaras Stelios <stel.lag@hotmail.com>
|
956 |
+
Jerry James <loganjerry@gmail.com>
|
957 |
+
Jan Kruse <janckruse@t-online.de>
|
958 |
+
Nathan Taylor <pecan.pine@gmail.com>
|
959 |
+
Vaishnav Damani <vaishnavdamani3496@gmail.com>
|
960 |
+
Mohit Shah <mohitshah3111999@gmail.com>
|
961 |
+
Mathias Louboutin <mathias.louboutin@gmail.com>
|
962 |
+
Marijan Smetko <marijansmetko123@gmail.com>
|
963 |
+
Dave Witte Morris <Dave.Morris@uleth.ca>
|
964 |
+
soumi7 <soumibardhan10@gmail.com>
|
965 |
+
Zhongshi <zj495@nyu.edu>
|
966 |
+
Wes Galbraith <galbwe92@gmail.com>
|
967 |
+
KaustubhDamania <kaustubh.damania@gmail.com>
|
968 |
+
w495 <w495@yandex-team.ru>
|
969 |
+
Akhil Rajput <akh1lrjput@gmail.com>
|
970 |
+
Markus Mohrhard <markus.mohrhard@googlemail.com>
|
971 |
+
Benjamin Wolba <mail@benjaminwolba.com>
|
972 |
+
彭于斌 <1931127624@qq.com>
|
973 |
+
Rudr Tiwari <rudrtiwari@gmail.com>
|
974 |
+
Aaryan Dewan <aaryandewan@yahoo.com>
|
975 |
+
Benedikt Placke <benedikt.placke@outlook.com>
|
976 |
+
Sneha Goddu <s.goddu@wustl.edu>
|
977 |
+
goddus <39923708+goddus@users.noreply.github.com>
|
978 |
+
Shivang Dubey <shivangdubey8@gmail.com>
|
979 |
+
Michael Greminger <michael.greminger@gmail.com>
|
980 |
+
Peter Cock <p.j.a.cock@googlemail.com>
|
981 |
+
Willem Melching <willem.melching@gmail.com>
|
982 |
+
Elias Basler <e.e.basler@protonmail.com>
|
983 |
+
Brandon David <brandon.david@zoho.com>
|
984 |
+
Abhay_Dhiman <abhaysdhimans@gmail.com>
|
985 |
+
Tasha Kim <jae_young_kim@brown.edu>
|
986 |
+
Ayush Malik <ayushmalik779@gmail.com>
|
987 |
+
Devesh Sawant <devesh47cool@gmail.com>
|
988 |
+
Wolfgang Stöcher <wolfgang@stoecher.com>
|
989 |
+
Sudeep Sidhu <sudeepmanilsidhu@gmail.com>
|
990 |
+
foice <foice.news@gmail.com>
|
991 |
+
Ben Payne <ben.is.located@gmail.com>
|
992 |
+
Muskan Kumar <31043527+muskanvk@users.noreply.github.com>
|
993 |
+
noam simcha finkelstein <noam.finkelstein@protonmail.com>
|
994 |
+
Garrett Folbe <gmfolbe@yahoo.com>
|
995 |
+
Islam Mansour <is3mansour@gmail.com>
|
996 |
+
Sayandip Halder <sayandiph4@gmail.com>
|
997 |
+
Shubham Agrawal <shubham.ag6845@gmail.com>
|
998 |
+
numbermaniac <5206120+numbermaniac@users.noreply.github.com>
|
999 |
+
Sakirul Alam <binarysakir@gmail.com>
|
1000 |
+
Mohammed Bilal <r.mohammedbilal@gmail.com>
|
1001 |
+
Chris du Plessis <christopherjonduplessis@gmail.com>
|
1002 |
+
Coder-RG <rgoel1999@gmail.com>
|
1003 |
+
Ansh Mishra <anshmishra471@gmail.com>
|
1004 |
+
Alex Malins <github@alexmalins.com>
|
1005 |
+
Lorenzo Contento <lorenzo.contento@gmail.com>
|
1006 |
+
Naveen Sai <naveensaisreenivas@gmail.com>
|
1007 |
+
Shital Mule <shitalmule04@gmail.com>
|
1008 |
+
Amanda Dsouza <meezamanda@yahoo.com>
|
1009 |
+
Nijso Beishuizen <nijso@koolmees.numerically-related.com>
|
1010 |
+
Harry Zheng <harry@harryzheng.com>
|
1011 |
+
Felix Yan <felixonmars@archlinux.org>
|
1012 |
+
Constantin Mateescu <costica1234@me.com>
|
1013 |
+
Eva Tiwari <eva.tiwari@gmail.com>
|
1014 |
+
Aditya Kumar Sinha <adityakumar113141@gmail.com>
|
1015 |
+
Soumi Bardhan <51290447+Soumi7@users.noreply.github.com>
|
1016 |
+
Kaustubh Chaudhari <ckaustubhm06@gmail.com>
|
1017 |
+
Kristian Brünn <hello@kristianbrunn.com>
|
1018 |
+
Neel Gorasiya <mgorasiya1974@gmail.com>
|
1019 |
+
Akshat Sood <68052998+akshatsood2249@users.noreply.github.com>
|
1020 |
+
Jose M. Gomez <chemoki@gmail.com>
|
1021 |
+
Stefan Petrea <stefan@garage-coding.com>
|
1022 |
+
Praveen Sahu <povinsahu@gmail.com>
|
1023 |
+
Mark Bell <mark00bell@googlemail.com>
|
1024 |
+
AlexCQY <alex_chua@u.nus.edu>
|
1025 |
+
Fabian Froehlich <fabian@schaluck.com>
|
1026 |
+
Nikhil Gopalam <gopalamn@umich.edu>
|
1027 |
+
Kartik Sethi <kartiks31416@gmail.com>
|
1028 |
+
Muhammed Abdul Quadir Owais <quadirowais200@gmail.com>
|
1029 |
+
Harshit Yadav <harshityadav2k@gmail.com>
|
1030 |
+
Sidharth Mundhra <sidharthmundhra16@gmail.com>
|
1031 |
+
Suryam Arnav Kalra <suryamkalra35@gmail.com>
|
1032 |
+
Prince Gupta <codemastercpp@gmail.com>
|
1033 |
+
Kunal Singh <ksingh19136@gmail.com>
|
1034 |
+
Mayank Raj <mayank_1901cs35@iitp.ac.in>
|
1035 |
+
Achal Jain <2achaljain@gmail.com>
|
1036 |
+
Mario Maio <mario.maio@aruba.it>
|
1037 |
+
Aaron Stiff <69512633+AaronStiff@users.noreply.github.com>
|
1038 |
+
Wyatt Peak <wyattpeak@gmail.com>
|
1039 |
+
Bhaskar Joshi <bhaskar.joshi@research.iiit.ac.in>
|
1040 |
+
Aditya Jindal <jaditya8889@gmail.com>
|
1041 |
+
Vaibhav Bhat <vaibhav.bhat2097@gmail.com>
|
1042 |
+
Priyansh Rathi <techiepriyansh@gmail.com>
|
1043 |
+
Saket Kumar Singh <saketkumar1202@gmail.com>
|
1044 |
+
Yukai Chou <muzimuzhi@gmail.com>
|
1045 |
+
Qijia Liu <liumeo@pku.edu.cn>
|
1046 |
+
Paul Mandel <paulmandel@google.com>
|
1047 |
+
Nisarg Chaudhari <54911392+Nisarg-Chaudhari@users.noreply.github.com>
|
1048 |
+
Dominik Stańczak <stanczakdominik@gmail.com>
|
1049 |
+
Rodrigo Luger <rodluger@gmail.com>
|
1050 |
+
Marco Antônio Habitzreuter <mahabitzreuter@gmail.com>
|
1051 |
+
Ayush Bisht <bisht.ayush2001@gmail.com>
|
1052 |
+
Akshansh Bhatt <akshansh@tuta.io>
|
1053 |
+
Brandon T. Willard <brandonwillard@users.noreply.github.com>
|
1054 |
+
Thomas Aarholt <thomasaarholt@gmail.com>
|
1055 |
+
Hiren Chalodiya <hirenchalodiya99@gmail.com>
|
1056 |
+
Roland Dixon <rols121@gmail.com>
|
1057 |
+
dimasvq <dimas.vq.2020@bristol.ac.uk>
|
1058 |
+
Sagar231 <sagarfeb298@gmail.com>
|
1059 |
+
Michael Chu <michael02chu@gmail.com>
|
1060 |
+
Abby Ng <abigailjng@gmail.com>
|
1061 |
+
Angad Sandhu <55819847+angadsinghsandhu@users.noreply.github.com>
|
1062 |
+
Alexander Cockburn <alexander_cockburn12@hotmail.com>
|
1063 |
+
Yaser AlOsh <yaseralosh@outlook.com>
|
1064 |
+
Davide Sandonà <sandona.davide@gmail.com>
|
1065 |
+
Jonathan Gutow <gutow@uwosh.edu>
|
1066 |
+
Nihir Agarwal <f20180701@pilani.bits-pilani.ac.in>
|
1067 |
+
Lee Johnston <lee.johnston.100@gmail.com>
|
1068 |
+
Zach Carmichael <20629897+craymichael@users.noreply.github.com>
|
1069 |
+
Vijairam Ganesh Moorthy <vijairamg@gmail.com>
|
1070 |
+
Hanspeter Schmid <hanspeter.schmid@fhnw.ch>
|
1071 |
+
Ben Oostendorp <oostben@umich.edu>
|
1072 |
+
Nikita <nikita.student.cse19@itbhu.ac.in>
|
1073 |
+
Aman <amanmourya295@gmail.com>
|
1074 |
+
Shashank KS <shashankks0987@gmail.com>
|
1075 |
+
Aman Sharma <amansharma110603@gmail.com>
|
1076 |
+
Anup Parikh <parikhanupk@gmail.com>
|
1077 |
+
Lucy Mountain <lucymountain1@icloud.com>
|
1078 |
+
Miguel Torres Costa <miguelptcosta1995@gmail.com>
|
1079 |
+
Rikard Nordgren <rikard.nordgren@farmaci.uu.se>
|
1080 |
+
Arun sanganal <74652697+ArunSanganal@users.noreply.github.com>
|
1081 |
+
Kamlesh Joshi <72374645+kamleshjoshi8102@users.noreply.github.com>
|
1082 |
+
Joseph Rance <56409230+Joseph-Rance@users.noreply.github.com>
|
1083 |
+
Huangduirong <huangduirong@huawei.com>
|
1084 |
+
Nils Schulte <47043622+Schnilz@users.noreply.github.com>
|
1085 |
+
Matt Bogosian <matt@bogosian.net>
|
1086 |
+
Elisha Hollander <just4now666666@gmail.com>
|
1087 |
+
Aditya Ravuri <infprobscix@gmail.com>
|
1088 |
+
Mamidi Ratna Praneeth <praneethratna@gmail.com>
|
1089 |
+
Jeffrey Ryan <jeffaryan7@gmail.com>
|
1090 |
+
Jonathan Daniel <36337649+jond01@users.noreply.github.com>
|
1091 |
+
Robin Richard <raisin@ecomail.fr>
|
1092 |
+
Gautam Menghani <gum3ng@protonmail.com>
|
1093 |
+
Remco de Boer <29308176+redeboer@users.noreply.github.com>
|
1094 |
+
Sebastian East <sebastianeast@ymail.com>
|
1095 |
+
Evani Balasubramanyam <balasubramanyam.evani@gmail.com>
|
1096 |
+
Rahil Parikh <r.parikh@somaiya.edu>
|
1097 |
+
Jason Ross <jasonross1024@gmail.com>
|
1098 |
+
Joannah Nanjekye <joannah.nanjekye@ibm.com>
|
1099 |
+
Ayush Kumar <ayushk7102@gmail.com>
|
1100 |
+
Kshitij <kshitijparwani.mat18@itbhu.ac.in>
|
1101 |
+
Daniel Hyams <dhyams@gmail.com>
|
1102 |
+
alijosephine <alijosephine@gmail.com>
|
1103 |
+
Matthias Köppe <mkoeppe@math.ucdavis.edu>
|
1104 |
+
mohajain <mohajain99@gmail.com>
|
1105 |
+
Anibal M. Medina-Mardones <ammedmar@gmail.com>
|
1106 |
+
Travis Ens <ens.travis@gmail.com>
|
1107 |
+
Evgenia Karunus <lakesare@gmail.com>
|
1108 |
+
Risiraj Dey <risirajdey@gmail.com>
|
1109 |
+
lastcodestanding <rohang71604@gmail.com>
|
1110 |
+
Andrey Lekar <andrey_lekar@adoriasoft.com>
|
1111 |
+
Abbas Mohammed <42001049+iam-abbas@users.noreply.github.com>
|
1112 |
+
anutosh491 <andersonbhat491@gmail.com>
|
1113 |
+
Steve Kieffer <sk@skieffer.info>
|
1114 |
+
Paul Spiering <paul@spiering.org>
|
1115 |
+
Pieter Gijsbers <p.gijsbers@tue.nl>
|
1116 |
+
Wang Ran (汪然) <wangr@smail.nju.edu.cn>
|
1117 |
+
naelsondouglas <naelson17@gmail.com>
|
1118 |
+
Aman Thakur <thakuraman22july@gmail.com>
|
1119 |
+
S. Hanko <suzy.hanko@gmail.com>
|
1120 |
+
Dennis Sweeney <sweeney.427@osu.edu>
|
1121 |
+
Gurpartap Singh <dhaliwal.gurpartap@gmail.com>
|
1122 |
+
Hampus Malmberg <hampus.malmberg88@gmail.com>
|
1123 |
+
scimax <max.kellermeier@hotmail.de>
|
1124 |
+
Nikhil Date <nikhil.s.date@gmail.com>
|
1125 |
+
Kuldeep Borkar Jr <kuldeepborkarjr765@gmail.com>
|
1126 |
+
AkuBrain <76952313+Franck2111@users.noreply.github.com>
|
1127 |
+
Leo Battle <leowbattle@gmail.com>
|
1128 |
+
Advait Pote <apote2050@gmail.com>
|
1129 |
+
Anurag Bhat <bhat.1@iitj.ac.in>
|
1130 |
+
Jeremy Monat <jemonat@calalum.org>
|
1131 |
+
Diane Tchuindjo <dtchuindjo@gmail.com>
|
1132 |
+
Tom Fryers <61272761+TomFryers@users.noreply.github.com>
|
1133 |
+
Zouhair <zouhair.mahboubi@gmail.com>
|
1134 |
+
zzj <29055749+zjzh@users.noreply.github.com>
|
1135 |
+
shubhayu09 <guptashubhayu601@gmail.com>
|
1136 |
+
Siddhant Jain <siddhantashoknagar@gmail.com>
|
1137 |
+
Tirthankar Mazumder <63574588+wermos@users.noreply.github.com>
|
1138 |
+
Sumit Kumar <mr.sumitkrr@gmail.com>
|
1139 |
+
Shivam Sagar <technoshivam12@gmail.com>
|
1140 |
+
Gaurav Jain <gjain369@gmail.com>
|
1141 |
+
Andrii Oriekhov <andriyorehov@gmail.com>
|
1142 |
+
Luis Talavera <luisfertalavera15@gmail.com>
|
1143 |
+
Arie Bovenberg <a.c.bovenberg@gmail.com>
|
1144 |
+
Carson McManus <carson.mcmanus1@gmail.com>
|
1145 |
+
Jack Schmidt <1107865+jackschmidt@users.noreply.github.com>
|
1146 |
+
Riley Britten <nrb1324@hotmail.com>
|
1147 |
+
Georges Khaznadar <georgesk@debian.org>
|
1148 |
+
Donald Wilson <donwilson1029@gmail.com>
|
1149 |
+
Timo Stienstra <timostienstra00@gmail.com>
|
1150 |
+
dispasha <dispasha@users.noreply.github.com>
|
1151 |
+
Saksham Alok <sakshamalok13@gmail.com>
|
1152 |
+
Varenyam Bhardwaj <varenyambhardwaj123@gmail.com>
|
1153 |
+
oittaa <8972248+oittaa@users.noreply.github.com>
|
1154 |
+
Omkaar <79257339+Pysics@users.noreply.github.com>
|
1155 |
+
Islem BOUZENIA <fi_bouzenia@esi.dz>
|
1156 |
+
extraymond <extraymond@gmail.com>
|
1157 |
+
Alexander Behrens <alex.git@gmx.net>
|
1158 |
+
user202729 <25191436+user202729@users.noreply.github.com>
|
1159 |
+
Pieter Eendebak <pieter.eendebak@gmail.com>
|
1160 |
+
Zaz Brown <zazbrown@zazbrown.com>
|
1161 |
+
ritikBhandari <ritikbhandari68@gmail.com>
|
1162 |
+
viocha <66580331+viocha@users.noreply.github.com>
|
1163 |
+
Arthur Ryman <arthur.ryman@gmail.com>
|
1164 |
+
Xiang Wu <hsiangwu@fb.com>
|
1165 |
+
tttc3 <T.Coxon2@lboro.ac.uk>
|
1166 |
+
Seth Poulsen <poulsenseth@yahoo.com>
|
1167 |
+
cocolato <haiizhu@outlook.com>
|
1168 |
+
Anton Golovanov <agolovanov256@gmail.com>
|
1169 |
+
Gareth Ma <grhkm21@gmail.com>
|
1170 |
+
Clément M.T. Robert <cr52@protonmail.com>
|
1171 |
+
Glenn Horton-Smith <glenn.hortonsmith@gmail.com>
|
1172 |
+
Karan <grgkaran03@gmail.com>
|
1173 |
+
Stefan Behnle <84378403+behnle@users.noreply.github.com>
|
1174 |
+
Shreyash Mishra <72146041+Shreyash-cyber@users.noreply.github.com>
|
1175 |
+
Arthur Milchior <arthur@milchior.fr>
|
1176 |
+
NotWearingPants <26556598+NotWearingPants@users.noreply.github.com>
|
1177 |
+
Ishan Pandhare <ishan9096137017@gmail.com>
|
1178 |
+
Carlos García Montoro <TrilceAC@gmail.com>
|
1179 |
+
Parcly Taxel <reddeloostw@gmail.com>
|
1180 |
+
Saicharan <saicharanhahaha@gmail.com>
|
1181 |
+
Kunal Sheth <kunal@kunalsheth.info>
|
1182 |
+
Biswadeep Purkayastha <98874428+metabiswadeep@users.noreply.github.com>
|
1183 |
+
Jyn Spring 琴春 <me@vx.st>
|
1184 |
+
Phil LeMaitre <phil_lemaitre@live.ca>
|
1185 |
+
Chris Kerr <chris.kerr@mykolab.ch>
|
1186 |
+
José Senart <jose.senart@gmail.com>
|
1187 |
+
Uwe L. Korn <uwelk@xhochy.com>
|
1188 |
+
ForeverHaibara <69423537+ForeverHaibara@users.noreply.github.com>
|
1189 |
+
Yves Tumushimire <yvestumushimire@gmail.com>
|
1190 |
+
wookie184 <wookie1840@gmail.com>
|
1191 |
+
Costor <pcs2009@web.de>
|
1192 |
+
Klaus Rettinghaus <klaus.rettinghaus@enote.com>
|
1193 |
+
Sam Brockie <sambrockie@icloud.com>
|
1194 |
+
Abhishek Patidar <1e9abhi1e10@gmail.com>
|
1195 |
+
Eric Demer <demer@mailbox.org>
|
1196 |
+
Pontus von Brömssen <pontus.vonbromssen+github@gmail.com>
|
1197 |
+
Victor Immanuel <chrollolucilfer1402@gmail.com>
|
1198 |
+
Evandro Bernardes <evbernardes@gmail.com>
|
1199 |
+
Michele Ceccacci <michelececcacci1@gmail.com>
|
1200 |
+
Ayush Aryan <ayush.aryan71@gmail.com>
|
1201 |
+
Kishore Gopalakrishnan <kishore96@gmail.com>
|
1202 |
+
Jan-Philipp Hoffmann <sonntagsgesicht@icloud.com>
|
1203 |
+
Daiki Takahashi <haru.td@gmail.com>
|
1204 |
+
Sayan Mitra <ee18b156@smail.iitm.ac.in>
|
1205 |
+
Aman Kumar Shukla <theprofessionalaman@gmail.com>
|
1206 |
+
Zoufiné Lauer-Baré <raszoufine@gmail.com>
|
1207 |
+
Charles Harris <erdos4d@gmail.com>
|
1208 |
+
Tejaswini Sanapathi <sastejaswini2002@gmail.com>
|
1209 |
+
Devansh <be19b002@smail.iitm.ac.in>
|
1210 |
+
Aaron Gokaslan <aaronGokaslan@gmail.com>
|
1211 |
+
Daan Koning (he/him) <daanolivierkoning@gmail.com>
|
1212 |
+
Steven Burns <royalstream@hotmail.com>
|
1213 |
+
Jay Patankar <patankarjays@gmail.com>
|
1214 |
+
Vivek Soni <sonisheela1977@gmail.com>
|
1215 |
+
Le Cong Minh Hieu <hieu.lecongminh@gmail.com>
|
1216 |
+
Sam Ritchie <sam@mentat.org>
|
1217 |
+
Maciej Skórski <maciej.skorski@gmail.com>
|
1218 |
+
Tilo Reneau-Cardoso <tiloreneau@gmail.com>
|
1219 |
+
Laurence Warne <laurencewarne@gmail.com>
|
1220 |
+
Lukas Molleman <Lukas.Molleman@gmail.com>
|
1221 |
+
Konstantinos Riganas <kostasriganas24@gmail.com>
|
1222 |
+
Grace Su <grace.duansu@gmail.com>
|
1223 |
+
Pedro Rosa <pedro_sxbr@usp.br>
|
1224 |
+
Abhinav Cillanki <abhinavcillanki@kgpian.iitkgp.ac.in>
|
1225 |
+
Baiyuan Qiu <1061688677@qq.com>
|
1226 |
+
Liwei Cai <cai.lw123@gmail.com>
|
1227 |
+
Daniel Weindl <daniel.weindl@helmholtz-muenchen.de>
|
1228 |
+
Isidora Araya <iarayaday@gmail.com>
|
1229 |
+
Seb Tiburzio <sebtiburzio@gmail.com>
|
1230 |
+
Victory Omole <vtomole2@gmail.com>
|
1231 |
+
Abhishek Chaudhary <ac5003@columbia.edu>
|
1232 |
+
Alexander Zhura <nice.zhura@list.ru>
|
1233 |
+
Shuai Zhou <shuaivzhou@berkeley.edu>
|
1234 |
+
Martin Manns <mmanns@gmx.net>
|
1235 |
+
John Möller <john.moller@outlook.com>
|
1236 |
+
zzc <1378113190@qq.com>
|
1237 |
+
Pablo Galindo Salgado <pablogsal@gmail.com>
|
1238 |
+
Johannes Kasimir <johannes.kasimir@math.lu.se>
|
1239 |
+
Theodore Dias <theodore.dias@hotmail.co.uk>
|
1240 |
+
Kaustubh <90597818+kaustubh-765@users.noreply.github.com>
|
1241 |
+
Idan Pazi <idan.kp@gmail.com>
|
1242 |
+
Ishan Pandhare <91841626+Ishanned@users.noreply.github.com>
|
1243 |
+
Shishir Kushwaha <kushwahashishir1112@gmail.com>
|
1244 |
+
Bobby Palmer <bobbyp@umich.edu>
|
1245 |
+
Saikat Das <saikatdchhe@gmail.com>
|
1246 |
+
Suman mondal <smondal.qwerty@gmail.com>
|
1247 |
+
Taylan Sahin <info@taylansahin.net>
|
1248 |
+
Fabio Luporini <fabio@devitocodes.com>
|
1249 |
+
Oriel Malihi <orielmalihi1@gmail.com>
|
1250 |
+
Geetika Vadali <geetika.vadali4@gmail.com>
|
1251 |
+
Matthias Rettl <matthias.rettl@stud.unileoben.ac.at>
|
1252 |
+
Mikhail Remnev <maremnev@gmail.com>
|
1253 |
+
philwillnyc <56197213+philwillnyc@users.noreply.github.com>
|
1254 |
+
Raphael Lehner <raphael.lehner@gmail.com>
|
1255 |
+
Harry Mountain <harrymountain1@icloud.com>
|
1256 |
+
Bhavik Sachdev <b.sachdev1904@gmail.com>
|
1257 |
+
袁野 (Yuan Ye) <yuanyelele@tutanota.com>
|
1258 |
+
fazledyn-or <ataf@openrefactory.com>
|
1259 |
+
mohammedouahman <simofun85@gmail.com>
|
1260 |
+
K. Kraus <laqueray@googlemail.com>
|
1261 |
+
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
|
1262 |
+
platypus <platypus.computerchip@gmail.com>
|
1263 |
+
codecruisader <nnisarg55@gmail.com>
|
1264 |
+
James Whitehead <whiteheadj@gmail.com>
|
1265 |
+
atharvParlikar <atharvparlikar@gmail.com>
|
1266 |
+
Ivan Petukhov <satels@gmail.com>
|
1267 |
+
Augusto Borges <borges.augustoar@gmail.com>
|
1268 |
+
Han Wei Ang <ang.h.w@u.nus.edu>
|
1269 |
+
Congxu Yang <u7189828@anu.edu.au>
|
1270 |
+
Saicharan <62512681+saicharan2804@users.noreply.github.com>
|
1271 |
+
Arnab Nandi <arnabnandi2002@gmail.com>
|
1272 |
+
Harrison Oates <48871176+HarrisonOates@users.noreply.github.com>
|
1273 |
+
Corey Cerovsek <corey@cerovsek.com>
|
1274 |
+
Harsh Kasat <hkasat@waymore.io>
|
1275 |
+
omahs <73983677+omahs@users.noreply.github.com>
|
1276 |
+
Pascal Gitz <pascal.gitz@hotmail.ch>
|
1277 |
+
Ravindu-Hirimuthugoda <ravindu.18@cse.mrt.ac.lk>
|
1278 |
+
Sophia Pustova <tripplezzed@gmail.com>
|
1279 |
+
George Pittock <gpittock4@gmail.com>
|
1280 |
+
Warren Jacinto <warrenjacinto@gmail.com>
|
1281 |
+
Sachin Singh <sachinishu02@gmail.com>
|
1282 |
+
Zedmat <104870914+harshkasat@users.noreply.github.com>
|
1283 |
+
Samith Karunathilake <55777141+samithkavishke@users.noreply.github.com>
|
1284 |
+
Viraj Vekaria <virajv5593@gmail.com>
|
1285 |
+
Ankit Kumar Singh <ankitdiswar10@gmail.com>
|
1286 |
+
Abhishek Kumar <abhishek.nitdelhi@gmail.com>
|
1287 |
+
Mohak Malviya <mohakmalviya2000@gmail.com>
|
1288 |
+
Matthias Liesenfeld <116307294+maliesen@users.noreply.github.com>
|
1289 |
+
dodo <palumbododo@gmail.com>
|
1290 |
+
Mohamed Rezk <mohrizq895@gmail.com>
|
1291 |
+
Tommaso Vaccari <05-gesto-follemente@icloud.com>
|
1292 |
+
Alexis Schotte <alexis.schotte@gmail.com>
|
1293 |
+
Lauren Yim <31467609+cherryblossom000@users.noreply.github.com>
|
1294 |
+
Prey Patel <patel.prey@iitgn.ac.in>
|
1295 |
+
Riccardo Di Girolamo <riccardodigirolamo01@gmail.com>
|
1296 |
+
Abhishek kumar <kumar325571@gmail.com>
|
1297 |
+
Sam Lubelsky <sammy56lt@gmail.com>
|
1298 |
+
Henrique Soares <henrique.c.soares@tecnico.ulisboa.pt>
|
1299 |
+
Vladimir Sereda <voffch@gmail.com>
|
1300 |
+
Raj Sapale <raj4sapale4@gmail.com>
|
1301 |
+
Gerald Teschl <gerald.teschl@univie.ac.at>
|
1302 |
+
Richard Samuel <98638849+samuelard7@users.noreply.github.com>
|
1303 |
+
HeeJae Chang <hechang@microsoft.com>
|
1304 |
+
Hwayeon Kang <hwayeonniii@gmail.com>
|
1305 |
+
Nick Harder <nharder@umich.edu>
|
1306 |
+
Ethan DeGuire <ethandeguire@gmail.com>
|
1307 |
+
Lorenz Winkler <lorenz.winkler@tuwien.ac.at>
|
1308 |
+
Richard Rodenbusch <rrodenbusch@gmail.com>
|
1309 |
+
Zhenxu Zhu <xzdlj@outlook.com>
|
1310 |
+
Mark van Gelder <m.j.vangelder@student.tudelft.nl>
|
1311 |
+
James A. Preiss <jamesalanpreiss@gmail.com>
|
1312 |
+
Emile Fourcini <emile.fourcin1@gmail.com>
|
1313 |
+
Alberto Jiménez Ruiz <Alberto.Jimenez@uclm.es>
|
1314 |
+
João Bravo <joaocgbravo@tecnico.ulisboa.pt>
|
1315 |
+
Dean Price <dean1357price1357@gmail.com>
|
1316 |
+
Hugo Kerstens <hugo@kerstens.me>
|
1317 |
+
Jan Jancar <johny@neuromancer.sk>
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/LICENSE
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright (c) 2006-2023 SymPy Development Team
|
2 |
+
|
3 |
+
All rights reserved.
|
4 |
+
|
5 |
+
Redistribution and use in source and binary forms, with or without
|
6 |
+
modification, are permitted provided that the following conditions are met:
|
7 |
+
|
8 |
+
a. Redistributions of source code must retain the above copyright notice,
|
9 |
+
this list of conditions and the following disclaimer.
|
10 |
+
b. Redistributions in binary form must reproduce the above copyright
|
11 |
+
notice, this list of conditions and the following disclaimer in the
|
12 |
+
documentation and/or other materials provided with the distribution.
|
13 |
+
c. Neither the name of SymPy nor the names of its contributors
|
14 |
+
may be used to endorse or promote products derived from this software
|
15 |
+
without specific prior written permission.
|
16 |
+
|
17 |
+
|
18 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
21 |
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
22 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
26 |
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
27 |
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
28 |
+
DAMAGE.
|
29 |
+
|
30 |
+
--------------------------------------------------------------------------------
|
31 |
+
|
32 |
+
Patches that were taken from the Diofant project (https://github.com/diofant/diofant)
|
33 |
+
are licensed as:
|
34 |
+
|
35 |
+
Copyright (c) 2006-2018 SymPy Development Team,
|
36 |
+
2013-2023 Sergey B Kirpichev
|
37 |
+
|
38 |
+
All rights reserved.
|
39 |
+
|
40 |
+
Redistribution and use in source and binary forms, with or without
|
41 |
+
modification, are permitted provided that the following conditions are met:
|
42 |
+
|
43 |
+
a. Redistributions of source code must retain the above copyright notice,
|
44 |
+
this list of conditions and the following disclaimer.
|
45 |
+
b. Redistributions in binary form must reproduce the above copyright
|
46 |
+
notice, this list of conditions and the following disclaimer in the
|
47 |
+
documentation and/or other materials provided with the distribution.
|
48 |
+
c. Neither the name of Diofant or SymPy nor the names of its contributors
|
49 |
+
may be used to endorse or promote products derived from this software
|
50 |
+
without specific prior written permission.
|
51 |
+
|
52 |
+
|
53 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
54 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
55 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
56 |
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
57 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
58 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
59 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
60 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
61 |
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
62 |
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
63 |
+
DAMAGE.
|
64 |
+
|
65 |
+
--------------------------------------------------------------------------------
|
66 |
+
|
67 |
+
Submodules taken from the multipledispatch project (https://github.com/mrocklin/multipledispatch)
|
68 |
+
are licensed as:
|
69 |
+
|
70 |
+
Copyright (c) 2014 Matthew Rocklin
|
71 |
+
|
72 |
+
All rights reserved.
|
73 |
+
|
74 |
+
Redistribution and use in source and binary forms, with or without
|
75 |
+
modification, are permitted provided that the following conditions are met:
|
76 |
+
|
77 |
+
a. Redistributions of source code must retain the above copyright notice,
|
78 |
+
this list of conditions and the following disclaimer.
|
79 |
+
b. Redistributions in binary form must reproduce the above copyright
|
80 |
+
notice, this list of conditions and the following disclaimer in the
|
81 |
+
documentation and/or other materials provided with the distribution.
|
82 |
+
c. Neither the name of multipledispatch nor the names of its contributors
|
83 |
+
may be used to endorse or promote products derived from this software
|
84 |
+
without specific prior written permission.
|
85 |
+
|
86 |
+
|
87 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
88 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
89 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
90 |
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
91 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
92 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
93 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
94 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
95 |
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
96 |
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
97 |
+
DAMAGE.
|
98 |
+
|
99 |
+
--------------------------------------------------------------------------------
|
100 |
+
|
101 |
+
The files under the directory sympy/parsing/autolev/tests/pydy-example-repo
|
102 |
+
are directly copied from PyDy project and are licensed as:
|
103 |
+
|
104 |
+
Copyright (c) 2009-2023, PyDy Authors
|
105 |
+
All rights reserved.
|
106 |
+
|
107 |
+
Redistribution and use in source and binary forms, with or without
|
108 |
+
modification, are permitted provided that the following conditions are met:
|
109 |
+
|
110 |
+
* Redistributions of source code must retain the above copyright
|
111 |
+
notice, this list of conditions and the following disclaimer.
|
112 |
+
* Redistributions in binary form must reproduce the above copyright
|
113 |
+
notice, this list of conditions and the following disclaimer in the
|
114 |
+
documentation and/or other materials provided with the distribution.
|
115 |
+
* Neither the name of this project nor the names of its contributors may be
|
116 |
+
used to endorse or promote products derived from this software without
|
117 |
+
specific prior written permission.
|
118 |
+
|
119 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
120 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
121 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
122 |
+
DISCLAIMED. IN NO EVENT SHALL PYDY AUTHORS BE LIABLE FOR ANY DIRECT,
|
123 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
124 |
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
125 |
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
126 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
127 |
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
128 |
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
129 |
+
|
130 |
+
--------------------------------------------------------------------------------
|
131 |
+
|
132 |
+
The files under the directory sympy/parsing/latex
|
133 |
+
are directly copied from latex2sympy project and are licensed as:
|
134 |
+
|
135 |
+
Copyright 2016, latex2sympy
|
136 |
+
|
137 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
138 |
+
of this software and associated documentation files (the "Software"), to deal
|
139 |
+
in the Software without restriction, including without limitation the rights
|
140 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
141 |
+
copies of the Software, and to permit persons to whom the Software is
|
142 |
+
furnished to do so, subject to the following conditions:
|
143 |
+
|
144 |
+
The above copyright notice and this permission notice shall be included in all
|
145 |
+
copies or substantial portions of the Software.
|
146 |
+
|
147 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
148 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
149 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
150 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
151 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
152 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
153 |
+
SOFTWARE.
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/METADATA
ADDED
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: sympy
|
3 |
+
Version: 1.13.1
|
4 |
+
Summary: Computer algebra system (CAS) in Python
|
5 |
+
Home-page: https://sympy.org
|
6 |
+
Author: SymPy development team
|
7 |
+
Author-email: sympy@googlegroups.com
|
8 |
+
License: BSD
|
9 |
+
Project-URL: Source, https://github.com/sympy/sympy
|
10 |
+
Keywords: Math CAS
|
11 |
+
Classifier: License :: OSI Approved :: BSD License
|
12 |
+
Classifier: Operating System :: OS Independent
|
13 |
+
Classifier: Programming Language :: Python
|
14 |
+
Classifier: Topic :: Scientific/Engineering
|
15 |
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
16 |
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
17 |
+
Classifier: Programming Language :: Python :: 3
|
18 |
+
Classifier: Programming Language :: Python :: 3.8
|
19 |
+
Classifier: Programming Language :: Python :: 3.9
|
20 |
+
Classifier: Programming Language :: Python :: 3.10
|
21 |
+
Classifier: Programming Language :: Python :: 3.11
|
22 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
23 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
24 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
25 |
+
Requires-Python: >=3.8
|
26 |
+
Description-Content-Type: text/markdown
|
27 |
+
License-File: LICENSE
|
28 |
+
License-File: AUTHORS
|
29 |
+
Requires-Dist: mpmath <1.4,>=1.1.0
|
30 |
+
Provides-Extra: dev
|
31 |
+
Requires-Dist: pytest >=7.1.0 ; extra == 'dev'
|
32 |
+
Requires-Dist: hypothesis >=6.70.0 ; extra == 'dev'
|
33 |
+
|
34 |
+
# SymPy
|
35 |
+
|
36 |
+
[](https://pypi.python.org/pypi/sympy)
|
37 |
+
[](https://gitter.im/sympy/sympy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
38 |
+
[](https://zenodo.org/badge/latestdoi/18918/sympy/sympy)
|
39 |
+
[](https://pepy.tech/project/sympy)
|
40 |
+
[](https://github.com/sympy/sympy/issues)
|
41 |
+
[](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project)
|
42 |
+
[](https://numfocus.org)
|
43 |
+
[](https://github.com/sympy/sympy/releases)
|
44 |
+
|
45 |
+
[](https://sympy.org/)
|
46 |
+
|
47 |
+
|
48 |
+
See the [AUTHORS](AUTHORS) file for the list of authors.
|
49 |
+
|
50 |
+
And many more people helped on the SymPy mailing list, reported bugs,
|
51 |
+
helped organize SymPy's participation in the Google Summer of Code, the
|
52 |
+
Google Highly Open Participation Contest, Google Code-In, wrote and
|
53 |
+
blogged about SymPy...
|
54 |
+
|
55 |
+
License: New BSD License (see the [LICENSE](LICENSE) file for details) covers all
|
56 |
+
files in the sympy repository unless stated otherwise.
|
57 |
+
|
58 |
+
Our mailing list is at
|
59 |
+
<https://groups.google.com/forum/?fromgroups#!forum/sympy>.
|
60 |
+
|
61 |
+
We have a community chat at [Gitter](https://gitter.im/sympy/sympy). Feel
|
62 |
+
free to ask us anything there. We have a very welcoming and helpful
|
63 |
+
community.
|
64 |
+
|
65 |
+
## Download
|
66 |
+
|
67 |
+
The recommended installation method is through Anaconda,
|
68 |
+
<https://www.anaconda.com/products/distribution>
|
69 |
+
|
70 |
+
You can also get the latest version of SymPy from
|
71 |
+
<https://pypi.python.org/pypi/sympy/>
|
72 |
+
|
73 |
+
To get the git version do
|
74 |
+
|
75 |
+
$ git clone https://github.com/sympy/sympy.git
|
76 |
+
|
77 |
+
For other options (tarballs, debs, etc.), see
|
78 |
+
<https://docs.sympy.org/dev/install.html>.
|
79 |
+
|
80 |
+
## Documentation and Usage
|
81 |
+
|
82 |
+
For in-depth instructions on installation and building the
|
83 |
+
documentation, see the [SymPy Documentation Style Guide](https://docs.sympy.org/dev/documentation-style-guide.html).
|
84 |
+
|
85 |
+
Everything is at:
|
86 |
+
|
87 |
+
<https://docs.sympy.org/>
|
88 |
+
|
89 |
+
You can generate everything at the above site in your local copy of
|
90 |
+
SymPy by:
|
91 |
+
|
92 |
+
$ cd doc
|
93 |
+
$ make html
|
94 |
+
|
95 |
+
Then the docs will be in <span class="title-ref">\_build/html</span>. If
|
96 |
+
you don't want to read that, here is a short usage:
|
97 |
+
|
98 |
+
From this directory, start Python and:
|
99 |
+
|
100 |
+
``` python
|
101 |
+
>>> from sympy import Symbol, cos
|
102 |
+
>>> x = Symbol('x')
|
103 |
+
>>> e = 1/cos(x)
|
104 |
+
>>> print(e.series(x, 0, 10))
|
105 |
+
1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)
|
106 |
+
```
|
107 |
+
|
108 |
+
SymPy also comes with a console that is a simple wrapper around the
|
109 |
+
classic python console (or IPython when available) that loads the SymPy
|
110 |
+
namespace and executes some common commands for you.
|
111 |
+
|
112 |
+
To start it, issue:
|
113 |
+
|
114 |
+
$ bin/isympy
|
115 |
+
|
116 |
+
from this directory, if SymPy is not installed or simply:
|
117 |
+
|
118 |
+
$ isympy
|
119 |
+
|
120 |
+
if SymPy is installed.
|
121 |
+
|
122 |
+
## Installation
|
123 |
+
|
124 |
+
To install SymPy using PyPI, run the following command:
|
125 |
+
|
126 |
+
$ pip install sympy
|
127 |
+
|
128 |
+
To install SymPy using Anaconda, run the following command:
|
129 |
+
|
130 |
+
$ conda install -c anaconda sympy
|
131 |
+
|
132 |
+
To install SymPy from GitHub source, first clone SymPy using `git`:
|
133 |
+
|
134 |
+
$ git clone https://github.com/sympy/sympy.git
|
135 |
+
|
136 |
+
Then, in the `sympy` repository that you cloned, simply run:
|
137 |
+
|
138 |
+
$ pip install .
|
139 |
+
|
140 |
+
See <https://docs.sympy.org/dev/install.html> for more information.
|
141 |
+
|
142 |
+
## Contributing
|
143 |
+
|
144 |
+
We welcome contributions from anyone, even if you are new to open
|
145 |
+
source. Please read our [Introduction to Contributing](https://docs.sympy.org/dev/contributing/introduction-to-contributing.html)
|
146 |
+
page and the [SymPy Documentation Style Guide](https://docs.sympy.org/dev/documentation-style-guide.html). If you
|
147 |
+
are new and looking for some way to contribute, a good place to start is
|
148 |
+
to look at the issues tagged [Easy to Fix](https://github.com/sympy/sympy/issues?q=is%3Aopen+is%3Aissue+label%3A%22Easy+to+Fix%22).
|
149 |
+
|
150 |
+
Please note that all participants in this project are expected to follow
|
151 |
+
our Code of Conduct. By participating in this project you agree to abide
|
152 |
+
by its terms. See [CODE\_OF\_CONDUCT.md](CODE_OF_CONDUCT.md).
|
153 |
+
|
154 |
+
## Tests
|
155 |
+
|
156 |
+
To execute all tests, run:
|
157 |
+
|
158 |
+
$./setup.py test
|
159 |
+
|
160 |
+
in the current directory.
|
161 |
+
|
162 |
+
For the more fine-grained running of tests or doctests, use `bin/test`
|
163 |
+
or respectively `bin/doctest`. The master branch is automatically tested
|
164 |
+
by GitHub Actions.
|
165 |
+
|
166 |
+
To test pull requests, use
|
167 |
+
[sympy-bot](https://github.com/sympy/sympy-bot).
|
168 |
+
|
169 |
+
## Regenerate Experimental <span class="title-ref">LaTeX</span> Parser/Lexer
|
170 |
+
|
171 |
+
The parser and lexer were generated with the [ANTLR4](http://antlr4.org)
|
172 |
+
toolchain in `sympy/parsing/latex/_antlr` and checked into the repo.
|
173 |
+
Presently, most users should not need to regenerate these files, but
|
174 |
+
if you plan to work on this feature, you will need the `antlr4`
|
175 |
+
command-line tool (and you must ensure that it is in your `PATH`).
|
176 |
+
One way to get it is:
|
177 |
+
|
178 |
+
$ conda install -c conda-forge antlr=4.11.1
|
179 |
+
|
180 |
+
Alternatively, follow the instructions on the ANTLR website and download
|
181 |
+
the `antlr-4.11.1-complete.jar`. Then export the `CLASSPATH` as instructed
|
182 |
+
and instead of creating `antlr4` as an alias, make it an executable file
|
183 |
+
with the following contents:
|
184 |
+
``` bash
|
185 |
+
#!/bin/bash
|
186 |
+
java -jar /usr/local/lib/antlr-4.11.1-complete.jar "$@"
|
187 |
+
```
|
188 |
+
|
189 |
+
After making changes to `sympy/parsing/latex/LaTeX.g4`, run:
|
190 |
+
|
191 |
+
$ ./setup.py antlr
|
192 |
+
|
193 |
+
## Clean
|
194 |
+
|
195 |
+
To clean everything (thus getting the same tree as in the repository):
|
196 |
+
|
197 |
+
$ git clean -Xdf
|
198 |
+
|
199 |
+
which will clear everything ignored by `.gitignore`, and:
|
200 |
+
|
201 |
+
$ git clean -df
|
202 |
+
|
203 |
+
to clear all untracked files. You can revert the most recent changes in
|
204 |
+
git with:
|
205 |
+
|
206 |
+
$ git reset --hard
|
207 |
+
|
208 |
+
WARNING: The above commands will all clear changes you may have made,
|
209 |
+
and you will lose them forever. Be sure to check things with `git
|
210 |
+
status`, `git diff`, `git clean -Xn`, and `git clean -n` before doing any
|
211 |
+
of those.
|
212 |
+
|
213 |
+
## Bugs
|
214 |
+
|
215 |
+
Our issue tracker is at <https://github.com/sympy/sympy/issues>. Please
|
216 |
+
report any bugs that you find. Or, even better, fork the repository on
|
217 |
+
GitHub and create a pull request. We welcome all changes, big or small,
|
218 |
+
and we will help you make the pull request if you are new to git (just
|
219 |
+
ask on our mailing list or Gitter Channel). If you further have any queries, you can find answers
|
220 |
+
on Stack Overflow using the [sympy](https://stackoverflow.com/questions/tagged/sympy) tag.
|
221 |
+
|
222 |
+
## Brief History
|
223 |
+
|
224 |
+
SymPy was started by Ondřej Čertík in 2005, he wrote some code during
|
225 |
+
the summer, then he wrote some more code during summer 2006. In February
|
226 |
+
2007, Fabian Pedregosa joined the project and helped fix many things,
|
227 |
+
contributed documentation, and made it alive again. 5 students (Mateusz
|
228 |
+
Paprocki, Brian Jorgensen, Jason Gedge, Robert Schwarz, and Chris Wu)
|
229 |
+
improved SymPy incredibly during summer 2007 as part of the Google
|
230 |
+
Summer of Code. Pearu Peterson joined the development during the summer
|
231 |
+
2007 and he has made SymPy much more competitive by rewriting the core
|
232 |
+
from scratch, which has made it from 10x to 100x faster. Jurjen N.E. Bos
|
233 |
+
has contributed pretty-printing and other patches. Fredrik Johansson has
|
234 |
+
written mpmath and contributed a lot of patches.
|
235 |
+
|
236 |
+
SymPy has participated in every Google Summer of Code since 2007. You
|
237 |
+
can see <https://github.com/sympy/sympy/wiki#google-summer-of-code> for
|
238 |
+
full details. Each year has improved SymPy by bounds. Most of SymPy's
|
239 |
+
development has come from Google Summer of Code students.
|
240 |
+
|
241 |
+
In 2011, Ondřej Čertík stepped down as lead developer, with Aaron
|
242 |
+
Meurer, who also started as a Google Summer of Code student, taking his
|
243 |
+
place. Ondřej Čertík is still active in the community but is too busy
|
244 |
+
with work and family to play a lead development role.
|
245 |
+
|
246 |
+
Since then, a lot more people have joined the development and some
|
247 |
+
people have also left. You can see the full list in doc/src/aboutus.rst,
|
248 |
+
or online at:
|
249 |
+
|
250 |
+
<https://docs.sympy.org/dev/aboutus.html#sympy-development-team>
|
251 |
+
|
252 |
+
The git history goes back to 2007 when development moved from svn to hg.
|
253 |
+
To see the history before that point, look at
|
254 |
+
<https://github.com/sympy/sympy-old>.
|
255 |
+
|
256 |
+
You can use git to see the biggest developers. The command:
|
257 |
+
|
258 |
+
$ git shortlog -ns
|
259 |
+
|
260 |
+
will show each developer, sorted by commits to the project. The command:
|
261 |
+
|
262 |
+
$ git shortlog -ns --since="1 year"
|
263 |
+
|
264 |
+
will show the top developers from the last year.
|
265 |
+
|
266 |
+
## Citation
|
267 |
+
|
268 |
+
To cite SymPy in publications use
|
269 |
+
|
270 |
+
> Meurer A, Smith CP, Paprocki M, Čertík O, Kirpichev SB, Rocklin M,
|
271 |
+
> Kumar A, Ivanov S, Moore JK, Singh S, Rathnayake T, Vig S, Granger BE,
|
272 |
+
> Muller RP, Bonazzi F, Gupta H, Vats S, Johansson F, Pedregosa F, Curry
|
273 |
+
> MJ, Terrel AR, Roučka Š, Saboo A, Fernando I, Kulal S, Cimrman R,
|
274 |
+
> Scopatz A. (2017) SymPy: symbolic computing in Python. *PeerJ Computer
|
275 |
+
> Science* 3:e103 <https://doi.org/10.7717/peerj-cs.103>
|
276 |
+
|
277 |
+
A BibTeX entry for LaTeX users is
|
278 |
+
|
279 |
+
``` bibtex
|
280 |
+
@article{10.7717/peerj-cs.103,
|
281 |
+
title = {SymPy: symbolic computing in Python},
|
282 |
+
author = {Meurer, Aaron and Smith, Christopher P. and Paprocki, Mateusz and \v{C}ert\'{i}k, Ond\v{r}ej and Kirpichev, Sergey B. and Rocklin, Matthew and Kumar, Amit and Ivanov, Sergiu and Moore, Jason K. and Singh, Sartaj and Rathnayake, Thilina and Vig, Sean and Granger, Brian E. and Muller, Richard P. and Bonazzi, Francesco and Gupta, Harsh and Vats, Shivam and Johansson, Fredrik and Pedregosa, Fabian and Curry, Matthew J. and Terrel, Andy R. and Rou\v{c}ka, \v{S}t\v{e}p\'{a}n and Saboo, Ashutosh and Fernando, Isuru and Kulal, Sumith and Cimrman, Robert and Scopatz, Anthony},
|
283 |
+
year = 2017,
|
284 |
+
month = Jan,
|
285 |
+
keywords = {Python, Computer algebra system, Symbolics},
|
286 |
+
abstract = {
|
287 |
+
SymPy is an open-source computer algebra system written in pure Python. It is built with a focus on extensibility and ease of use, through both interactive and programmatic applications. These characteristics have led SymPy to become a popular symbolic library for the scientific Python ecosystem. This paper presents the architecture of SymPy, a description of its features, and a discussion of select submodules. The supplementary material provides additional examples and further outlines details of the architecture and features of SymPy.
|
288 |
+
},
|
289 |
+
volume = 3,
|
290 |
+
pages = {e103},
|
291 |
+
journal = {PeerJ Computer Science},
|
292 |
+
issn = {2376-5992},
|
293 |
+
url = {https://doi.org/10.7717/peerj-cs.103},
|
294 |
+
doi = {10.7717/peerj-cs.103}
|
295 |
+
}
|
296 |
+
```
|
297 |
+
|
298 |
+
SymPy is BSD licensed, so you are free to use it whatever you like, be
|
299 |
+
it academic, commercial, creating forks or derivatives, as long as you
|
300 |
+
copy the BSD statement if you redistribute it (see the LICENSE file for
|
301 |
+
details). That said, although not required by the SymPy license, if it
|
302 |
+
is convenient for you, please cite SymPy when using it in your work and
|
303 |
+
also consider contributing all your changes back, so that we can
|
304 |
+
incorporate it and all of us will benefit in the end.
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/RECORD
ADDED
The diff for this file is too large to render.
See raw diff
|
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (71.0.3)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/entry_points.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
[console_scripts]
|
2 |
+
isympy = isympy:main
|
MLPY/Lib/site-packages/sympy-1.13.1.dist-info/top_level.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
isympy
|
2 |
+
sympy
|
MLPY/Lib/site-packages/sympy/__init__.py
ADDED
@@ -0,0 +1,542 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
SymPy is a Python library for symbolic mathematics. It aims to become a
|
3 |
+
full-featured computer algebra system (CAS) while keeping the code as simple
|
4 |
+
as possible in order to be comprehensible and easily extensible. SymPy is
|
5 |
+
written entirely in Python. It depends on mpmath, and other external libraries
|
6 |
+
may be optionally for things like plotting support.
|
7 |
+
|
8 |
+
See the webpage for more information and documentation:
|
9 |
+
|
10 |
+
https://sympy.org
|
11 |
+
|
12 |
+
"""
|
13 |
+
|
14 |
+
|
15 |
+
import sys
|
16 |
+
if sys.version_info < (3, 8):
|
17 |
+
raise ImportError("Python version 3.8 or above is required for SymPy.")
|
18 |
+
del sys
|
19 |
+
|
20 |
+
|
21 |
+
try:
|
22 |
+
import mpmath
|
23 |
+
except ImportError:
|
24 |
+
raise ImportError("SymPy now depends on mpmath as an external library. "
|
25 |
+
"See https://docs.sympy.org/latest/install.html#mpmath for more information.")
|
26 |
+
|
27 |
+
del mpmath
|
28 |
+
|
29 |
+
from sympy.release import __version__
|
30 |
+
from sympy.core.cache import lazy_function
|
31 |
+
|
32 |
+
if 'dev' in __version__:
|
33 |
+
def enable_warnings():
|
34 |
+
import warnings
|
35 |
+
warnings.filterwarnings('default', '.*', DeprecationWarning, module='sympy.*')
|
36 |
+
del warnings
|
37 |
+
enable_warnings()
|
38 |
+
del enable_warnings
|
39 |
+
|
40 |
+
|
41 |
+
def __sympy_debug():
|
42 |
+
# helper function so we don't import os globally
|
43 |
+
import os
|
44 |
+
debug_str = os.getenv('SYMPY_DEBUG', 'False')
|
45 |
+
if debug_str in ('True', 'False'):
|
46 |
+
return eval(debug_str)
|
47 |
+
else:
|
48 |
+
raise RuntimeError("unrecognized value for SYMPY_DEBUG: %s" %
|
49 |
+
debug_str)
|
50 |
+
SYMPY_DEBUG = __sympy_debug() # type: bool
|
51 |
+
|
52 |
+
from .core import (sympify, SympifyError, cacheit, Basic, Atom,
|
53 |
+
preorder_traversal, S, Expr, AtomicExpr, UnevaluatedExpr, Symbol,
|
54 |
+
Wild, Dummy, symbols, var, Number, Float, Rational, Integer,
|
55 |
+
NumberSymbol, RealNumber, igcd, ilcm, seterr, E, I, nan, oo, pi, zoo,
|
56 |
+
AlgebraicNumber, comp, mod_inverse, Pow, integer_nthroot, integer_log,
|
57 |
+
trailing, Mul, prod, Add, Mod, Rel, Eq, Ne, Lt, Le, Gt, Ge, Equality,
|
58 |
+
GreaterThan, LessThan, Unequality, StrictGreaterThan, StrictLessThan,
|
59 |
+
vectorize, Lambda, WildFunction, Derivative, diff, FunctionClass,
|
60 |
+
Function, Subs, expand, PoleError, count_ops, expand_mul, expand_log,
|
61 |
+
expand_func, expand_trig, expand_complex, expand_multinomial, nfloat,
|
62 |
+
expand_power_base, expand_power_exp, arity, PrecisionExhausted, N,
|
63 |
+
evalf, Tuple, Dict, gcd_terms, factor_terms, factor_nc, evaluate,
|
64 |
+
Catalan, EulerGamma, GoldenRatio, TribonacciConstant, bottom_up, use,
|
65 |
+
postorder_traversal, default_sort_key, ordered, num_digits)
|
66 |
+
|
67 |
+
from .logic import (to_cnf, to_dnf, to_nnf, And, Or, Not, Xor, Nand, Nor,
|
68 |
+
Implies, Equivalent, ITE, POSform, SOPform, simplify_logic, bool_map,
|
69 |
+
true, false, satisfiable)
|
70 |
+
|
71 |
+
from .assumptions import (AppliedPredicate, Predicate, AssumptionsContext,
|
72 |
+
assuming, Q, ask, register_handler, remove_handler, refine)
|
73 |
+
|
74 |
+
from .polys import (Poly, PurePoly, poly_from_expr, parallel_poly_from_expr,
|
75 |
+
degree, total_degree, degree_list, LC, LM, LT, pdiv, prem, pquo,
|
76 |
+
pexquo, div, rem, quo, exquo, half_gcdex, gcdex, invert,
|
77 |
+
subresultants, resultant, discriminant, cofactors, gcd_list, gcd,
|
78 |
+
lcm_list, lcm, terms_gcd, trunc, monic, content, primitive, compose,
|
79 |
+
decompose, sturm, gff_list, gff, sqf_norm, sqf_part, sqf_list, sqf,
|
80 |
+
factor_list, factor, intervals, refine_root, count_roots, all_roots,
|
81 |
+
real_roots, nroots, ground_roots, nth_power_roots_poly, cancel,
|
82 |
+
reduced, groebner, is_zero_dimensional, GroebnerBasis, poly,
|
83 |
+
symmetrize, horner, interpolate, rational_interpolate, viete, together,
|
84 |
+
BasePolynomialError, ExactQuotientFailed, PolynomialDivisionFailed,
|
85 |
+
OperationNotSupported, HeuristicGCDFailed, HomomorphismFailed,
|
86 |
+
IsomorphismFailed, ExtraneousFactors, EvaluationFailed,
|
87 |
+
RefinementFailed, CoercionFailed, NotInvertible, NotReversible,
|
88 |
+
NotAlgebraic, DomainError, PolynomialError, UnificationFailed,
|
89 |
+
GeneratorsError, GeneratorsNeeded, ComputationFailed,
|
90 |
+
UnivariatePolynomialError, MultivariatePolynomialError,
|
91 |
+
PolificationFailed, OptionError, FlagError, minpoly,
|
92 |
+
minimal_polynomial, primitive_element, field_isomorphism,
|
93 |
+
to_number_field, isolate, round_two, prime_decomp, prime_valuation,
|
94 |
+
galois_group, itermonomials, Monomial, lex, grlex,
|
95 |
+
grevlex, ilex, igrlex, igrevlex, CRootOf, rootof, RootOf,
|
96 |
+
ComplexRootOf, RootSum, roots, Domain, FiniteField, IntegerRing,
|
97 |
+
RationalField, RealField, ComplexField, PythonFiniteField,
|
98 |
+
GMPYFiniteField, PythonIntegerRing, GMPYIntegerRing, PythonRational,
|
99 |
+
GMPYRationalField, AlgebraicField, PolynomialRing, FractionField,
|
100 |
+
ExpressionDomain, FF_python, FF_gmpy, ZZ_python, ZZ_gmpy, QQ_python,
|
101 |
+
QQ_gmpy, GF, FF, ZZ, QQ, ZZ_I, QQ_I, RR, CC, EX, EXRAW,
|
102 |
+
construct_domain, swinnerton_dyer_poly, cyclotomic_poly,
|
103 |
+
symmetric_poly, random_poly, interpolating_poly, jacobi_poly,
|
104 |
+
chebyshevt_poly, chebyshevu_poly, hermite_poly, hermite_prob_poly,
|
105 |
+
legendre_poly, laguerre_poly, apart, apart_list, assemble_partfrac_list,
|
106 |
+
Options, ring, xring, vring, sring, field, xfield, vfield, sfield)
|
107 |
+
|
108 |
+
from .series import (Order, O, limit, Limit, gruntz, series, approximants,
|
109 |
+
residue, EmptySequence, SeqPer, SeqFormula, sequence, SeqAdd, SeqMul,
|
110 |
+
fourier_series, fps, difference_delta, limit_seq)
|
111 |
+
|
112 |
+
from .functions import (factorial, factorial2, rf, ff, binomial,
|
113 |
+
RisingFactorial, FallingFactorial, subfactorial, carmichael,
|
114 |
+
fibonacci, lucas, motzkin, tribonacci, harmonic, bernoulli, bell, euler,
|
115 |
+
catalan, genocchi, andre, partition, divisor_sigma, legendre_symbol,
|
116 |
+
jacobi_symbol, kronecker_symbol, mobius, primenu, primeomega,
|
117 |
+
totient, reduced_totient, primepi, sqrt, root, Min, Max, Id,
|
118 |
+
real_root, Rem, cbrt, re, im, sign, Abs, conjugate, arg, polar_lift,
|
119 |
+
periodic_argument, unbranched_argument, principal_branch, transpose,
|
120 |
+
adjoint, polarify, unpolarify, sin, cos, tan, sec, csc, cot, sinc,
|
121 |
+
asin, acos, atan, asec, acsc, acot, atan2, exp_polar, exp, ln, log,
|
122 |
+
LambertW, sinh, cosh, tanh, coth, sech, csch, asinh, acosh, atanh,
|
123 |
+
acoth, asech, acsch, floor, ceiling, frac, Piecewise, piecewise_fold,
|
124 |
+
piecewise_exclusive, erf, erfc, erfi, erf2, erfinv, erfcinv, erf2inv,
|
125 |
+
Ei, expint, E1, li, Li, Si, Ci, Shi, Chi, fresnels, fresnelc, gamma,
|
126 |
+
lowergamma, uppergamma, polygamma, loggamma, digamma, trigamma,
|
127 |
+
multigamma, dirichlet_eta, zeta, lerchphi, polylog, stieltjes, Eijk,
|
128 |
+
LeviCivita, KroneckerDelta, SingularityFunction, DiracDelta, Heaviside,
|
129 |
+
bspline_basis, bspline_basis_set, interpolating_spline, besselj,
|
130 |
+
bessely, besseli, besselk, hankel1, hankel2, jn, yn, jn_zeros, hn1,
|
131 |
+
hn2, airyai, airybi, airyaiprime, airybiprime, marcumq, hyper,
|
132 |
+
meijerg, appellf1, legendre, assoc_legendre, hermite, hermite_prob,
|
133 |
+
chebyshevt, chebyshevu, chebyshevu_root, chebyshevt_root, laguerre,
|
134 |
+
assoc_laguerre, gegenbauer, jacobi, jacobi_normalized, Ynm, Ynm_c,
|
135 |
+
Znm, elliptic_k, elliptic_f, elliptic_e, elliptic_pi, beta, mathieus,
|
136 |
+
mathieuc, mathieusprime, mathieucprime, riemann_xi, betainc, betainc_regularized)
|
137 |
+
|
138 |
+
from .ntheory import (nextprime, prevprime, prime, primerange,
|
139 |
+
randprime, Sieve, sieve, primorial, cycle_length, composite,
|
140 |
+
compositepi, isprime, divisors, proper_divisors, factorint,
|
141 |
+
multiplicity, perfect_power, pollard_pm1, pollard_rho, primefactors,
|
142 |
+
divisor_count, proper_divisor_count,
|
143 |
+
factorrat,
|
144 |
+
mersenne_prime_exponent, is_perfect, is_mersenne_prime, is_abundant,
|
145 |
+
is_deficient, is_amicable, is_carmichael, abundance, npartitions, is_primitive_root,
|
146 |
+
is_quad_residue, n_order, sqrt_mod,
|
147 |
+
quadratic_residues, primitive_root, nthroot_mod, is_nthpow_residue,
|
148 |
+
sqrt_mod_iter, discrete_log, quadratic_congruence,
|
149 |
+
binomial_coefficients, binomial_coefficients_list,
|
150 |
+
multinomial_coefficients, continued_fraction_periodic,
|
151 |
+
continued_fraction_iterator, continued_fraction_reduce,
|
152 |
+
continued_fraction_convergents, continued_fraction, egyptian_fraction)
|
153 |
+
|
154 |
+
from .concrete import product, Product, summation, Sum
|
155 |
+
|
156 |
+
from .discrete import (fft, ifft, ntt, intt, fwht, ifwht, mobius_transform,
|
157 |
+
inverse_mobius_transform, convolution, covering_product,
|
158 |
+
intersecting_product)
|
159 |
+
|
160 |
+
from .simplify import (simplify, hypersimp, hypersimilar, logcombine,
|
161 |
+
separatevars, posify, besselsimp, kroneckersimp, signsimp,
|
162 |
+
nsimplify, FU, fu, sqrtdenest, cse, epath, EPath, hyperexpand,
|
163 |
+
collect, rcollect, radsimp, collect_const, fraction, numer, denom,
|
164 |
+
trigsimp, exptrigsimp, powsimp, powdenest, combsimp, gammasimp,
|
165 |
+
ratsimp, ratsimpmodprime)
|
166 |
+
|
167 |
+
from .sets import (Set, Interval, Union, EmptySet, FiniteSet, ProductSet,
|
168 |
+
Intersection, DisjointUnion, imageset, Complement, SymmetricDifference, ImageSet,
|
169 |
+
Range, ComplexRegion, Complexes, Reals, Contains, ConditionSet, Ordinal,
|
170 |
+
OmegaPower, ord0, PowerSet, Naturals, Naturals0, UniversalSet,
|
171 |
+
Integers, Rationals)
|
172 |
+
|
173 |
+
from .solvers import (solve, solve_linear_system, solve_linear_system_LU,
|
174 |
+
solve_undetermined_coeffs, nsolve, solve_linear, checksol, det_quick,
|
175 |
+
inv_quick, check_assumptions, failing_assumptions, diophantine,
|
176 |
+
rsolve, rsolve_poly, rsolve_ratio, rsolve_hyper, checkodesol,
|
177 |
+
classify_ode, dsolve, homogeneous_order, solve_poly_system,
|
178 |
+
solve_triangulated, pde_separate, pde_separate_add, pde_separate_mul,
|
179 |
+
pdsolve, classify_pde, checkpdesol, ode_order, reduce_inequalities,
|
180 |
+
reduce_abs_inequality, reduce_abs_inequalities, solve_poly_inequality,
|
181 |
+
solve_rational_inequalities, solve_univariate_inequality, decompogen,
|
182 |
+
solveset, linsolve, linear_eq_to_matrix, nonlinsolve, substitution)
|
183 |
+
|
184 |
+
from .matrices import (ShapeError, NonSquareMatrixError, GramSchmidt,
|
185 |
+
casoratian, diag, eye, hessian, jordan_cell, list2numpy, matrix2numpy,
|
186 |
+
matrix_multiply_elementwise, ones, randMatrix, rot_axis1, rot_axis2,
|
187 |
+
rot_axis3, symarray, wronskian, zeros, MutableDenseMatrix,
|
188 |
+
DeferredVector, MatrixBase, Matrix, MutableMatrix,
|
189 |
+
MutableSparseMatrix, banded, ImmutableDenseMatrix,
|
190 |
+
ImmutableSparseMatrix, ImmutableMatrix, SparseMatrix, MatrixSlice,
|
191 |
+
BlockDiagMatrix, BlockMatrix, FunctionMatrix, Identity, Inverse,
|
192 |
+
MatAdd, MatMul, MatPow, MatrixExpr, MatrixSymbol, Trace, Transpose,
|
193 |
+
ZeroMatrix, OneMatrix, blockcut, block_collapse, matrix_symbols,
|
194 |
+
Adjoint, hadamard_product, HadamardProduct, HadamardPower,
|
195 |
+
Determinant, det, diagonalize_vector, DiagMatrix, DiagonalMatrix,
|
196 |
+
DiagonalOf, trace, DotProduct, kronecker_product, KroneckerProduct,
|
197 |
+
PermutationMatrix, MatrixPermute, Permanent, per, rot_ccw_axis1,
|
198 |
+
rot_ccw_axis2, rot_ccw_axis3, rot_givens)
|
199 |
+
|
200 |
+
from .geometry import (Point, Point2D, Point3D, Line, Ray, Segment, Line2D,
|
201 |
+
Segment2D, Ray2D, Line3D, Segment3D, Ray3D, Plane, Ellipse, Circle,
|
202 |
+
Polygon, RegularPolygon, Triangle, rad, deg, are_similar, centroid,
|
203 |
+
convex_hull, idiff, intersection, closest_points, farthest_points,
|
204 |
+
GeometryError, Curve, Parabola)
|
205 |
+
|
206 |
+
from .utilities import (flatten, group, take, subsets, variations,
|
207 |
+
numbered_symbols, cartes, capture, dict_merge, prefixes, postfixes,
|
208 |
+
sift, topological_sort, unflatten, has_dups, has_variety, reshape,
|
209 |
+
rotations, filldedent, lambdify,
|
210 |
+
threaded, xthreaded, public, memoize_property, timed)
|
211 |
+
|
212 |
+
from .integrals import (integrate, Integral, line_integrate, mellin_transform,
|
213 |
+
inverse_mellin_transform, MellinTransform, InverseMellinTransform,
|
214 |
+
laplace_transform, laplace_correspondence, laplace_initial_conds,
|
215 |
+
inverse_laplace_transform, LaplaceTransform,
|
216 |
+
InverseLaplaceTransform, fourier_transform, inverse_fourier_transform,
|
217 |
+
FourierTransform, InverseFourierTransform, sine_transform,
|
218 |
+
inverse_sine_transform, SineTransform, InverseSineTransform,
|
219 |
+
cosine_transform, inverse_cosine_transform, CosineTransform,
|
220 |
+
InverseCosineTransform, hankel_transform, inverse_hankel_transform,
|
221 |
+
HankelTransform, InverseHankelTransform, singularityintegrate)
|
222 |
+
|
223 |
+
from .tensor import (IndexedBase, Idx, Indexed, get_contraction_structure,
|
224 |
+
get_indices, shape, MutableDenseNDimArray, ImmutableDenseNDimArray,
|
225 |
+
MutableSparseNDimArray, ImmutableSparseNDimArray, NDimArray,
|
226 |
+
tensorproduct, tensorcontraction, tensordiagonal, derive_by_array,
|
227 |
+
permutedims, Array, DenseNDimArray, SparseNDimArray)
|
228 |
+
|
229 |
+
from .parsing import parse_expr
|
230 |
+
|
231 |
+
from .calculus import (euler_equations, singularities, is_increasing,
|
232 |
+
is_strictly_increasing, is_decreasing, is_strictly_decreasing,
|
233 |
+
is_monotonic, finite_diff_weights, apply_finite_diff,
|
234 |
+
differentiate_finite, periodicity, not_empty_in, AccumBounds,
|
235 |
+
is_convex, stationary_points, minimum, maximum)
|
236 |
+
|
237 |
+
from .algebras import Quaternion
|
238 |
+
|
239 |
+
from .printing import (pager_print, pretty, pretty_print, pprint,
|
240 |
+
pprint_use_unicode, pprint_try_use_unicode, latex, print_latex,
|
241 |
+
multiline_latex, mathml, print_mathml, python, print_python, pycode,
|
242 |
+
ccode, print_ccode, smtlib_code, glsl_code, print_glsl, cxxcode, fcode,
|
243 |
+
print_fcode, rcode, print_rcode, jscode, print_jscode, julia_code,
|
244 |
+
mathematica_code, octave_code, rust_code, print_gtk, preview, srepr,
|
245 |
+
print_tree, StrPrinter, sstr, sstrrepr, TableForm, dotprint,
|
246 |
+
maple_code, print_maple_code)
|
247 |
+
|
248 |
+
test = lazy_function('sympy.testing.runtests_pytest', 'test')
|
249 |
+
doctest = lazy_function('sympy.testing.runtests', 'doctest')
|
250 |
+
|
251 |
+
# This module causes conflicts with other modules:
|
252 |
+
# from .stats import *
|
253 |
+
# Adds about .04-.05 seconds of import time
|
254 |
+
# from combinatorics import *
|
255 |
+
# This module is slow to import:
|
256 |
+
#from physics import units
|
257 |
+
from .plotting import plot, textplot, plot_backends, plot_implicit, plot_parametric
|
258 |
+
from .interactive import init_session, init_printing, interactive_traversal
|
259 |
+
|
260 |
+
evalf._create_evalf_table()
|
261 |
+
|
262 |
+
__all__ = [
|
263 |
+
'__version__',
|
264 |
+
|
265 |
+
# sympy.core
|
266 |
+
'sympify', 'SympifyError', 'cacheit', 'Basic', 'Atom',
|
267 |
+
'preorder_traversal', 'S', 'Expr', 'AtomicExpr', 'UnevaluatedExpr',
|
268 |
+
'Symbol', 'Wild', 'Dummy', 'symbols', 'var', 'Number', 'Float',
|
269 |
+
'Rational', 'Integer', 'NumberSymbol', 'RealNumber', 'igcd', 'ilcm',
|
270 |
+
'seterr', 'E', 'I', 'nan', 'oo', 'pi', 'zoo', 'AlgebraicNumber', 'comp',
|
271 |
+
'mod_inverse', 'Pow', 'integer_nthroot', 'integer_log', 'trailing', 'Mul', 'prod',
|
272 |
+
'Add', 'Mod', 'Rel', 'Eq', 'Ne', 'Lt', 'Le', 'Gt', 'Ge', 'Equality',
|
273 |
+
'GreaterThan', 'LessThan', 'Unequality', 'StrictGreaterThan',
|
274 |
+
'StrictLessThan', 'vectorize', 'Lambda', 'WildFunction', 'Derivative',
|
275 |
+
'diff', 'FunctionClass', 'Function', 'Subs', 'expand', 'PoleError',
|
276 |
+
'count_ops', 'expand_mul', 'expand_log', 'expand_func', 'expand_trig',
|
277 |
+
'expand_complex', 'expand_multinomial', 'nfloat', 'expand_power_base',
|
278 |
+
'expand_power_exp', 'arity', 'PrecisionExhausted', 'N', 'evalf', 'Tuple',
|
279 |
+
'Dict', 'gcd_terms', 'factor_terms', 'factor_nc', 'evaluate', 'Catalan',
|
280 |
+
'EulerGamma', 'GoldenRatio', 'TribonacciConstant', 'bottom_up', 'use',
|
281 |
+
'postorder_traversal', 'default_sort_key', 'ordered', 'num_digits',
|
282 |
+
|
283 |
+
# sympy.logic
|
284 |
+
'to_cnf', 'to_dnf', 'to_nnf', 'And', 'Or', 'Not', 'Xor', 'Nand', 'Nor',
|
285 |
+
'Implies', 'Equivalent', 'ITE', 'POSform', 'SOPform', 'simplify_logic',
|
286 |
+
'bool_map', 'true', 'false', 'satisfiable',
|
287 |
+
|
288 |
+
# sympy.assumptions
|
289 |
+
'AppliedPredicate', 'Predicate', 'AssumptionsContext', 'assuming', 'Q',
|
290 |
+
'ask', 'register_handler', 'remove_handler', 'refine',
|
291 |
+
|
292 |
+
# sympy.polys
|
293 |
+
'Poly', 'PurePoly', 'poly_from_expr', 'parallel_poly_from_expr', 'degree',
|
294 |
+
'total_degree', 'degree_list', 'LC', 'LM', 'LT', 'pdiv', 'prem', 'pquo',
|
295 |
+
'pexquo', 'div', 'rem', 'quo', 'exquo', 'half_gcdex', 'gcdex', 'invert',
|
296 |
+
'subresultants', 'resultant', 'discriminant', 'cofactors', 'gcd_list',
|
297 |
+
'gcd', 'lcm_list', 'lcm', 'terms_gcd', 'trunc', 'monic', 'content',
|
298 |
+
'primitive', 'compose', 'decompose', 'sturm', 'gff_list', 'gff',
|
299 |
+
'sqf_norm', 'sqf_part', 'sqf_list', 'sqf', 'factor_list', 'factor',
|
300 |
+
'intervals', 'refine_root', 'count_roots', 'all_roots', 'real_roots',
|
301 |
+
'nroots', 'ground_roots', 'nth_power_roots_poly', 'cancel', 'reduced',
|
302 |
+
'groebner', 'is_zero_dimensional', 'GroebnerBasis', 'poly', 'symmetrize',
|
303 |
+
'horner', 'interpolate', 'rational_interpolate', 'viete', 'together',
|
304 |
+
'BasePolynomialError', 'ExactQuotientFailed', 'PolynomialDivisionFailed',
|
305 |
+
'OperationNotSupported', 'HeuristicGCDFailed', 'HomomorphismFailed',
|
306 |
+
'IsomorphismFailed', 'ExtraneousFactors', 'EvaluationFailed',
|
307 |
+
'RefinementFailed', 'CoercionFailed', 'NotInvertible', 'NotReversible',
|
308 |
+
'NotAlgebraic', 'DomainError', 'PolynomialError', 'UnificationFailed',
|
309 |
+
'GeneratorsError', 'GeneratorsNeeded', 'ComputationFailed',
|
310 |
+
'UnivariatePolynomialError', 'MultivariatePolynomialError',
|
311 |
+
'PolificationFailed', 'OptionError', 'FlagError', 'minpoly',
|
312 |
+
'minimal_polynomial', 'primitive_element', 'field_isomorphism',
|
313 |
+
'to_number_field', 'isolate', 'round_two', 'prime_decomp',
|
314 |
+
'prime_valuation', 'galois_group', 'itermonomials', 'Monomial', 'lex', 'grlex',
|
315 |
+
'grevlex', 'ilex', 'igrlex', 'igrevlex', 'CRootOf', 'rootof', 'RootOf',
|
316 |
+
'ComplexRootOf', 'RootSum', 'roots', 'Domain', 'FiniteField',
|
317 |
+
'IntegerRing', 'RationalField', 'RealField', 'ComplexField',
|
318 |
+
'PythonFiniteField', 'GMPYFiniteField', 'PythonIntegerRing',
|
319 |
+
'GMPYIntegerRing', 'PythonRational', 'GMPYRationalField',
|
320 |
+
'AlgebraicField', 'PolynomialRing', 'FractionField', 'ExpressionDomain',
|
321 |
+
'FF_python', 'FF_gmpy', 'ZZ_python', 'ZZ_gmpy', 'QQ_python', 'QQ_gmpy',
|
322 |
+
'GF', 'FF', 'ZZ', 'QQ', 'ZZ_I', 'QQ_I', 'RR', 'CC', 'EX', 'EXRAW',
|
323 |
+
'construct_domain', 'swinnerton_dyer_poly', 'cyclotomic_poly',
|
324 |
+
'symmetric_poly', 'random_poly', 'interpolating_poly', 'jacobi_poly',
|
325 |
+
'chebyshevt_poly', 'chebyshevu_poly', 'hermite_poly', 'hermite_prob_poly',
|
326 |
+
'legendre_poly', 'laguerre_poly', 'apart', 'apart_list', 'assemble_partfrac_list',
|
327 |
+
'Options', 'ring', 'xring', 'vring', 'sring', 'field', 'xfield', 'vfield',
|
328 |
+
'sfield',
|
329 |
+
|
330 |
+
# sympy.series
|
331 |
+
'Order', 'O', 'limit', 'Limit', 'gruntz', 'series', 'approximants',
|
332 |
+
'residue', 'EmptySequence', 'SeqPer', 'SeqFormula', 'sequence', 'SeqAdd',
|
333 |
+
'SeqMul', 'fourier_series', 'fps', 'difference_delta', 'limit_seq',
|
334 |
+
|
335 |
+
# sympy.functions
|
336 |
+
'factorial', 'factorial2', 'rf', 'ff', 'binomial', 'RisingFactorial',
|
337 |
+
'FallingFactorial', 'subfactorial', 'carmichael', 'fibonacci', 'lucas',
|
338 |
+
'motzkin', 'tribonacci', 'harmonic', 'bernoulli', 'bell', 'euler', 'catalan',
|
339 |
+
'genocchi', 'andre', 'partition', 'divisor_sigma', 'legendre_symbol', 'jacobi_symbol',
|
340 |
+
'kronecker_symbol', 'mobius', 'primenu', 'primeomega', 'totient', 'primepi',
|
341 |
+
'reduced_totient', 'sqrt', 'root', 'Min', 'Max', 'Id', 'real_root',
|
342 |
+
'Rem', 'cbrt', 're', 'im', 'sign', 'Abs', 'conjugate', 'arg', 'polar_lift',
|
343 |
+
'periodic_argument', 'unbranched_argument', 'principal_branch',
|
344 |
+
'transpose', 'adjoint', 'polarify', 'unpolarify', 'sin', 'cos', 'tan',
|
345 |
+
'sec', 'csc', 'cot', 'sinc', 'asin', 'acos', 'atan', 'asec', 'acsc',
|
346 |
+
'acot', 'atan2', 'exp_polar', 'exp', 'ln', 'log', 'LambertW', 'sinh',
|
347 |
+
'cosh', 'tanh', 'coth', 'sech', 'csch', 'asinh', 'acosh', 'atanh',
|
348 |
+
'acoth', 'asech', 'acsch', 'floor', 'ceiling', 'frac', 'Piecewise',
|
349 |
+
'piecewise_fold', 'piecewise_exclusive', 'erf', 'erfc', 'erfi', 'erf2',
|
350 |
+
'erfinv', 'erfcinv', 'erf2inv', 'Ei', 'expint', 'E1', 'li', 'Li', 'Si',
|
351 |
+
'Ci', 'Shi', 'Chi', 'fresnels', 'fresnelc', 'gamma', 'lowergamma',
|
352 |
+
'uppergamma', 'polygamma', 'loggamma', 'digamma', 'trigamma', 'multigamma',
|
353 |
+
'dirichlet_eta', 'zeta', 'lerchphi', 'polylog', 'stieltjes', 'Eijk', 'LeviCivita',
|
354 |
+
'KroneckerDelta', 'SingularityFunction', 'DiracDelta', 'Heaviside',
|
355 |
+
'bspline_basis', 'bspline_basis_set', 'interpolating_spline', 'besselj',
|
356 |
+
'bessely', 'besseli', 'besselk', 'hankel1', 'hankel2', 'jn', 'yn',
|
357 |
+
'jn_zeros', 'hn1', 'hn2', 'airyai', 'airybi', 'airyaiprime',
|
358 |
+
'airybiprime', 'marcumq', 'hyper', 'meijerg', 'appellf1', 'legendre',
|
359 |
+
'assoc_legendre', 'hermite', 'hermite_prob', 'chebyshevt', 'chebyshevu',
|
360 |
+
'chebyshevu_root', 'chebyshevt_root', 'laguerre', 'assoc_laguerre',
|
361 |
+
'gegenbauer', 'jacobi', 'jacobi_normalized', 'Ynm', 'Ynm_c', 'Znm',
|
362 |
+
'elliptic_k', 'elliptic_f', 'elliptic_e', 'elliptic_pi', 'beta',
|
363 |
+
'mathieus', 'mathieuc', 'mathieusprime', 'mathieucprime', 'riemann_xi','betainc',
|
364 |
+
'betainc_regularized',
|
365 |
+
|
366 |
+
# sympy.ntheory
|
367 |
+
'nextprime', 'prevprime', 'prime', 'primerange', 'randprime',
|
368 |
+
'Sieve', 'sieve', 'primorial', 'cycle_length', 'composite', 'compositepi',
|
369 |
+
'isprime', 'divisors', 'proper_divisors', 'factorint', 'multiplicity',
|
370 |
+
'perfect_power', 'pollard_pm1', 'pollard_rho', 'primefactors',
|
371 |
+
'divisor_count', 'proper_divisor_count',
|
372 |
+
'factorrat',
|
373 |
+
'mersenne_prime_exponent', 'is_perfect', 'is_mersenne_prime',
|
374 |
+
'is_abundant', 'is_deficient', 'is_amicable', 'is_carmichael', 'abundance',
|
375 |
+
'npartitions',
|
376 |
+
'is_primitive_root', 'is_quad_residue',
|
377 |
+
'n_order', 'sqrt_mod', 'quadratic_residues',
|
378 |
+
'primitive_root', 'nthroot_mod', 'is_nthpow_residue', 'sqrt_mod_iter',
|
379 |
+
'discrete_log', 'quadratic_congruence', 'binomial_coefficients',
|
380 |
+
'binomial_coefficients_list', 'multinomial_coefficients',
|
381 |
+
'continued_fraction_periodic', 'continued_fraction_iterator',
|
382 |
+
'continued_fraction_reduce', 'continued_fraction_convergents',
|
383 |
+
'continued_fraction', 'egyptian_fraction',
|
384 |
+
|
385 |
+
# sympy.concrete
|
386 |
+
'product', 'Product', 'summation', 'Sum',
|
387 |
+
|
388 |
+
# sympy.discrete
|
389 |
+
'fft', 'ifft', 'ntt', 'intt', 'fwht', 'ifwht', 'mobius_transform',
|
390 |
+
'inverse_mobius_transform', 'convolution', 'covering_product',
|
391 |
+
'intersecting_product',
|
392 |
+
|
393 |
+
# sympy.simplify
|
394 |
+
'simplify', 'hypersimp', 'hypersimilar', 'logcombine', 'separatevars',
|
395 |
+
'posify', 'besselsimp', 'kroneckersimp', 'signsimp',
|
396 |
+
'nsimplify', 'FU', 'fu', 'sqrtdenest', 'cse', 'epath', 'EPath',
|
397 |
+
'hyperexpand', 'collect', 'rcollect', 'radsimp', 'collect_const',
|
398 |
+
'fraction', 'numer', 'denom', 'trigsimp', 'exptrigsimp', 'powsimp',
|
399 |
+
'powdenest', 'combsimp', 'gammasimp', 'ratsimp', 'ratsimpmodprime',
|
400 |
+
|
401 |
+
# sympy.sets
|
402 |
+
'Set', 'Interval', 'Union', 'EmptySet', 'FiniteSet', 'ProductSet',
|
403 |
+
'Intersection', 'imageset', 'DisjointUnion', 'Complement', 'SymmetricDifference',
|
404 |
+
'ImageSet', 'Range', 'ComplexRegion', 'Reals', 'Contains', 'ConditionSet',
|
405 |
+
'Ordinal', 'OmegaPower', 'ord0', 'PowerSet', 'Naturals',
|
406 |
+
'Naturals0', 'UniversalSet', 'Integers', 'Rationals', 'Complexes',
|
407 |
+
|
408 |
+
# sympy.solvers
|
409 |
+
'solve', 'solve_linear_system', 'solve_linear_system_LU',
|
410 |
+
'solve_undetermined_coeffs', 'nsolve', 'solve_linear', 'checksol',
|
411 |
+
'det_quick', 'inv_quick', 'check_assumptions', 'failing_assumptions',
|
412 |
+
'diophantine', 'rsolve', 'rsolve_poly', 'rsolve_ratio', 'rsolve_hyper',
|
413 |
+
'checkodesol', 'classify_ode', 'dsolve', 'homogeneous_order',
|
414 |
+
'solve_poly_system', 'solve_triangulated', 'pde_separate',
|
415 |
+
'pde_separate_add', 'pde_separate_mul', 'pdsolve', 'classify_pde',
|
416 |
+
'checkpdesol', 'ode_order', 'reduce_inequalities',
|
417 |
+
'reduce_abs_inequality', 'reduce_abs_inequalities',
|
418 |
+
'solve_poly_inequality', 'solve_rational_inequalities',
|
419 |
+
'solve_univariate_inequality', 'decompogen', 'solveset', 'linsolve',
|
420 |
+
'linear_eq_to_matrix', 'nonlinsolve', 'substitution',
|
421 |
+
|
422 |
+
# sympy.matrices
|
423 |
+
'ShapeError', 'NonSquareMatrixError', 'GramSchmidt', 'casoratian', 'diag',
|
424 |
+
'eye', 'hessian', 'jordan_cell', 'list2numpy', 'matrix2numpy',
|
425 |
+
'matrix_multiply_elementwise', 'ones', 'randMatrix', 'rot_axis1',
|
426 |
+
'rot_axis2', 'rot_axis3', 'symarray', 'wronskian', 'zeros',
|
427 |
+
'MutableDenseMatrix', 'DeferredVector', 'MatrixBase', 'Matrix',
|
428 |
+
'MutableMatrix', 'MutableSparseMatrix', 'banded', 'ImmutableDenseMatrix',
|
429 |
+
'ImmutableSparseMatrix', 'ImmutableMatrix', 'SparseMatrix', 'MatrixSlice',
|
430 |
+
'BlockDiagMatrix', 'BlockMatrix', 'FunctionMatrix', 'Identity', 'Inverse',
|
431 |
+
'MatAdd', 'MatMul', 'MatPow', 'MatrixExpr', 'MatrixSymbol', 'Trace',
|
432 |
+
'Transpose', 'ZeroMatrix', 'OneMatrix', 'blockcut', 'block_collapse',
|
433 |
+
'matrix_symbols', 'Adjoint', 'hadamard_product', 'HadamardProduct',
|
434 |
+
'HadamardPower', 'Determinant', 'det', 'diagonalize_vector', 'DiagMatrix',
|
435 |
+
'DiagonalMatrix', 'DiagonalOf', 'trace', 'DotProduct',
|
436 |
+
'kronecker_product', 'KroneckerProduct', 'PermutationMatrix',
|
437 |
+
'MatrixPermute', 'Permanent', 'per', 'rot_ccw_axis1', 'rot_ccw_axis2',
|
438 |
+
'rot_ccw_axis3', 'rot_givens',
|
439 |
+
|
440 |
+
# sympy.geometry
|
441 |
+
'Point', 'Point2D', 'Point3D', 'Line', 'Ray', 'Segment', 'Line2D',
|
442 |
+
'Segment2D', 'Ray2D', 'Line3D', 'Segment3D', 'Ray3D', 'Plane', 'Ellipse',
|
443 |
+
'Circle', 'Polygon', 'RegularPolygon', 'Triangle', 'rad', 'deg',
|
444 |
+
'are_similar', 'centroid', 'convex_hull', 'idiff', 'intersection',
|
445 |
+
'closest_points', 'farthest_points', 'GeometryError', 'Curve', 'Parabola',
|
446 |
+
|
447 |
+
# sympy.utilities
|
448 |
+
'flatten', 'group', 'take', 'subsets', 'variations', 'numbered_symbols',
|
449 |
+
'cartes', 'capture', 'dict_merge', 'prefixes', 'postfixes', 'sift',
|
450 |
+
'topological_sort', 'unflatten', 'has_dups', 'has_variety', 'reshape',
|
451 |
+
'rotations', 'filldedent', 'lambdify', 'threaded', 'xthreaded',
|
452 |
+
'public', 'memoize_property', 'timed',
|
453 |
+
|
454 |
+
# sympy.integrals
|
455 |
+
'integrate', 'Integral', 'line_integrate', 'mellin_transform',
|
456 |
+
'inverse_mellin_transform', 'MellinTransform', 'InverseMellinTransform',
|
457 |
+
'laplace_transform', 'inverse_laplace_transform', 'LaplaceTransform',
|
458 |
+
'laplace_correspondence', 'laplace_initial_conds',
|
459 |
+
'InverseLaplaceTransform', 'fourier_transform',
|
460 |
+
'inverse_fourier_transform', 'FourierTransform',
|
461 |
+
'InverseFourierTransform', 'sine_transform', 'inverse_sine_transform',
|
462 |
+
'SineTransform', 'InverseSineTransform', 'cosine_transform',
|
463 |
+
'inverse_cosine_transform', 'CosineTransform', 'InverseCosineTransform',
|
464 |
+
'hankel_transform', 'inverse_hankel_transform', 'HankelTransform',
|
465 |
+
'InverseHankelTransform', 'singularityintegrate',
|
466 |
+
|
467 |
+
# sympy.tensor
|
468 |
+
'IndexedBase', 'Idx', 'Indexed', 'get_contraction_structure',
|
469 |
+
'get_indices', 'shape', 'MutableDenseNDimArray', 'ImmutableDenseNDimArray',
|
470 |
+
'MutableSparseNDimArray', 'ImmutableSparseNDimArray', 'NDimArray',
|
471 |
+
'tensorproduct', 'tensorcontraction', 'tensordiagonal', 'derive_by_array',
|
472 |
+
'permutedims', 'Array', 'DenseNDimArray', 'SparseNDimArray',
|
473 |
+
|
474 |
+
# sympy.parsing
|
475 |
+
'parse_expr',
|
476 |
+
|
477 |
+
# sympy.calculus
|
478 |
+
'euler_equations', 'singularities', 'is_increasing',
|
479 |
+
'is_strictly_increasing', 'is_decreasing', 'is_strictly_decreasing',
|
480 |
+
'is_monotonic', 'finite_diff_weights', 'apply_finite_diff',
|
481 |
+
'differentiate_finite', 'periodicity', 'not_empty_in',
|
482 |
+
'AccumBounds', 'is_convex', 'stationary_points', 'minimum', 'maximum',
|
483 |
+
|
484 |
+
# sympy.algebras
|
485 |
+
'Quaternion',
|
486 |
+
|
487 |
+
# sympy.printing
|
488 |
+
'pager_print', 'pretty', 'pretty_print', 'pprint', 'pprint_use_unicode',
|
489 |
+
'pprint_try_use_unicode', 'latex', 'print_latex', 'multiline_latex',
|
490 |
+
'mathml', 'print_mathml', 'python', 'print_python', 'pycode', 'ccode',
|
491 |
+
'print_ccode', 'smtlib_code', 'glsl_code', 'print_glsl', 'cxxcode', 'fcode',
|
492 |
+
'print_fcode', 'rcode', 'print_rcode', 'jscode', 'print_jscode',
|
493 |
+
'julia_code', 'mathematica_code', 'octave_code', 'rust_code', 'print_gtk',
|
494 |
+
'preview', 'srepr', 'print_tree', 'StrPrinter', 'sstr', 'sstrrepr',
|
495 |
+
'TableForm', 'dotprint', 'maple_code', 'print_maple_code',
|
496 |
+
|
497 |
+
# sympy.plotting
|
498 |
+
'plot', 'textplot', 'plot_backends', 'plot_implicit', 'plot_parametric',
|
499 |
+
|
500 |
+
# sympy.interactive
|
501 |
+
'init_session', 'init_printing', 'interactive_traversal',
|
502 |
+
|
503 |
+
# sympy.testing
|
504 |
+
'test', 'doctest',
|
505 |
+
]
|
506 |
+
|
507 |
+
|
508 |
+
#===========================================================================#
|
509 |
+
# #
|
510 |
+
# XXX: The names below were importable before SymPy 1.6 using #
|
511 |
+
# #
|
512 |
+
# from sympy import * #
|
513 |
+
# #
|
514 |
+
# This happened implicitly because there was no __all__ defined in this #
|
515 |
+
# __init__.py file. Not every package is imported. The list matches what #
|
516 |
+
# would have been imported before. It is possible that these packages will #
|
517 |
+
# not be imported by a star-import from sympy in future. #
|
518 |
+
# #
|
519 |
+
#===========================================================================#
|
520 |
+
|
521 |
+
|
522 |
+
__all__.extend((
|
523 |
+
'algebras',
|
524 |
+
'assumptions',
|
525 |
+
'calculus',
|
526 |
+
'concrete',
|
527 |
+
'discrete',
|
528 |
+
'external',
|
529 |
+
'functions',
|
530 |
+
'geometry',
|
531 |
+
'interactive',
|
532 |
+
'multipledispatch',
|
533 |
+
'ntheory',
|
534 |
+
'parsing',
|
535 |
+
'plotting',
|
536 |
+
'polys',
|
537 |
+
'printing',
|
538 |
+
'release',
|
539 |
+
'strategies',
|
540 |
+
'tensor',
|
541 |
+
'utilities',
|
542 |
+
))
|
MLPY/Lib/site-packages/sympy/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (28.3 kB). View file
|
|
MLPY/Lib/site-packages/sympy/__pycache__/abc.cpython-39.pyc
ADDED
Binary file (3.5 kB). View file
|
|
MLPY/Lib/site-packages/sympy/__pycache__/conftest.cpython-39.pyc
ADDED
Binary file (2.9 kB). View file
|
|
MLPY/Lib/site-packages/sympy/__pycache__/galgebra.cpython-39.pyc
ADDED
Binary file (259 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/__pycache__/release.cpython-39.pyc
ADDED
Binary file (163 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/__pycache__/this.cpython-39.pyc
ADDED
Binary file (702 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/abc.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
This module exports all latin and greek letters as Symbols, so you can
|
3 |
+
conveniently do
|
4 |
+
|
5 |
+
>>> from sympy.abc import x, y
|
6 |
+
|
7 |
+
instead of the slightly more clunky-looking
|
8 |
+
|
9 |
+
>>> from sympy import symbols
|
10 |
+
>>> x, y = symbols('x y')
|
11 |
+
|
12 |
+
Caveats
|
13 |
+
=======
|
14 |
+
|
15 |
+
1. As of the time of writing this, the names ``O``, ``S``, ``I``, ``N``,
|
16 |
+
``E``, and ``Q`` are colliding with names defined in SymPy. If you import them
|
17 |
+
from both ``sympy.abc`` and ``sympy``, the second import will "win".
|
18 |
+
This is an issue only for * imports, which should only be used for short-lived
|
19 |
+
code such as interactive sessions and throwaway scripts that do not survive
|
20 |
+
until the next SymPy upgrade, where ``sympy`` may contain a different set of
|
21 |
+
names.
|
22 |
+
|
23 |
+
2. This module does not define symbol names on demand, i.e.
|
24 |
+
``from sympy.abc import foo`` will be reported as an error because
|
25 |
+
``sympy.abc`` does not contain the name ``foo``. To get a symbol named ``foo``,
|
26 |
+
you still need to use ``Symbol('foo')`` or ``symbols('foo')``.
|
27 |
+
You can freely mix usage of ``sympy.abc`` and ``Symbol``/``symbols``, though
|
28 |
+
sticking with one and only one way to get the symbols does tend to make the code
|
29 |
+
more readable.
|
30 |
+
|
31 |
+
The module also defines some special names to help detect which names clash
|
32 |
+
with the default SymPy namespace.
|
33 |
+
|
34 |
+
``_clash1`` defines all the single letter variables that clash with
|
35 |
+
SymPy objects; ``_clash2`` defines the multi-letter clashing symbols;
|
36 |
+
and ``_clash`` is the union of both. These can be passed for ``locals``
|
37 |
+
during sympification if one desires Symbols rather than the non-Symbol
|
38 |
+
objects for those names.
|
39 |
+
|
40 |
+
Examples
|
41 |
+
========
|
42 |
+
|
43 |
+
>>> from sympy import S
|
44 |
+
>>> from sympy.abc import _clash1, _clash2, _clash
|
45 |
+
>>> S("Q & C", locals=_clash1)
|
46 |
+
C & Q
|
47 |
+
>>> S('pi(x)', locals=_clash2)
|
48 |
+
pi(x)
|
49 |
+
>>> S('pi(C, Q)', locals=_clash)
|
50 |
+
pi(C, Q)
|
51 |
+
|
52 |
+
"""
|
53 |
+
|
54 |
+
from typing import Any, Dict as tDict
|
55 |
+
|
56 |
+
import string
|
57 |
+
|
58 |
+
from .core import Symbol, symbols
|
59 |
+
from .core.alphabets import greeks
|
60 |
+
from sympy.parsing.sympy_parser import null
|
61 |
+
|
62 |
+
##### Symbol definitions #####
|
63 |
+
|
64 |
+
# Implementation note: The easiest way to avoid typos in the symbols()
|
65 |
+
# parameter is to copy it from the left-hand side of the assignment.
|
66 |
+
|
67 |
+
a, b, c, d, e, f, g, h, i, j = symbols('a, b, c, d, e, f, g, h, i, j')
|
68 |
+
k, l, m, n, o, p, q, r, s, t = symbols('k, l, m, n, o, p, q, r, s, t')
|
69 |
+
u, v, w, x, y, z = symbols('u, v, w, x, y, z')
|
70 |
+
|
71 |
+
A, B, C, D, E, F, G, H, I, J = symbols('A, B, C, D, E, F, G, H, I, J')
|
72 |
+
K, L, M, N, O, P, Q, R, S, T = symbols('K, L, M, N, O, P, Q, R, S, T')
|
73 |
+
U, V, W, X, Y, Z = symbols('U, V, W, X, Y, Z')
|
74 |
+
|
75 |
+
alpha, beta, gamma, delta = symbols('alpha, beta, gamma, delta')
|
76 |
+
epsilon, zeta, eta, theta = symbols('epsilon, zeta, eta, theta')
|
77 |
+
iota, kappa, lamda, mu = symbols('iota, kappa, lamda, mu')
|
78 |
+
nu, xi, omicron, pi = symbols('nu, xi, omicron, pi')
|
79 |
+
rho, sigma, tau, upsilon = symbols('rho, sigma, tau, upsilon')
|
80 |
+
phi, chi, psi, omega = symbols('phi, chi, psi, omega')
|
81 |
+
|
82 |
+
|
83 |
+
##### Clashing-symbols diagnostics #####
|
84 |
+
|
85 |
+
# We want to know which names in SymPy collide with those in here.
|
86 |
+
# This is mostly for diagnosing SymPy's namespace during SymPy development.
|
87 |
+
|
88 |
+
_latin = list(string.ascii_letters)
|
89 |
+
# QOSINE should not be imported as they clash; gamma, pi and zeta clash, too
|
90 |
+
_greek = list(greeks) # make a copy, so we can mutate it
|
91 |
+
# Note: We import lamda since lambda is a reserved keyword in Python
|
92 |
+
_greek.remove("lambda")
|
93 |
+
_greek.append("lamda")
|
94 |
+
|
95 |
+
ns: tDict[str, Any] = {}
|
96 |
+
exec('from sympy import *', ns)
|
97 |
+
_clash1: tDict[str, Any] = {}
|
98 |
+
_clash2: tDict[str, Any] = {}
|
99 |
+
while ns:
|
100 |
+
_k, _ = ns.popitem()
|
101 |
+
if _k in _greek:
|
102 |
+
_clash2[_k] = null
|
103 |
+
_greek.remove(_k)
|
104 |
+
elif _k in _latin:
|
105 |
+
_clash1[_k] = null
|
106 |
+
_latin.remove(_k)
|
107 |
+
_clash = {}
|
108 |
+
_clash.update(_clash1)
|
109 |
+
_clash.update(_clash2)
|
110 |
+
|
111 |
+
del _latin, _greek, Symbol, _k, null
|
MLPY/Lib/site-packages/sympy/algebras/__init__.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from .quaternion import Quaternion
|
2 |
+
|
3 |
+
__all__ = ["Quaternion",]
|
MLPY/Lib/site-packages/sympy/algebras/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (218 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/algebras/__pycache__/quaternion.cpython-39.pyc
ADDED
Binary file (47.3 kB). View file
|
|
MLPY/Lib/site-packages/sympy/algebras/quaternion.py
ADDED
@@ -0,0 +1,1667 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sympy.core.numbers import Rational
|
2 |
+
from sympy.core.singleton import S
|
3 |
+
from sympy.core.relational import is_eq
|
4 |
+
from sympy.functions.elementary.complexes import (conjugate, im, re, sign)
|
5 |
+
from sympy.functions.elementary.exponential import (exp, log as ln)
|
6 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
7 |
+
from sympy.functions.elementary.trigonometric import (acos, asin, atan2)
|
8 |
+
from sympy.functions.elementary.trigonometric import (cos, sin)
|
9 |
+
from sympy.simplify.trigsimp import trigsimp
|
10 |
+
from sympy.integrals.integrals import integrate
|
11 |
+
from sympy.matrices.dense import MutableDenseMatrix as Matrix
|
12 |
+
from sympy.core.sympify import sympify, _sympify
|
13 |
+
from sympy.core.expr import Expr
|
14 |
+
from sympy.core.logic import fuzzy_not, fuzzy_or
|
15 |
+
from sympy.utilities.misc import as_int
|
16 |
+
|
17 |
+
from mpmath.libmp.libmpf import prec_to_dps
|
18 |
+
|
19 |
+
|
20 |
+
def _check_norm(elements, norm):
|
21 |
+
"""validate if input norm is consistent"""
|
22 |
+
if norm is not None and norm.is_number:
|
23 |
+
if norm.is_positive is False:
|
24 |
+
raise ValueError("Input norm must be positive.")
|
25 |
+
|
26 |
+
numerical = all(i.is_number and i.is_real is True for i in elements)
|
27 |
+
if numerical and is_eq(norm**2, sum(i**2 for i in elements)) is False:
|
28 |
+
raise ValueError("Incompatible value for norm.")
|
29 |
+
|
30 |
+
|
31 |
+
def _is_extrinsic(seq):
|
32 |
+
"""validate seq and return True if seq is lowercase and False if uppercase"""
|
33 |
+
if type(seq) != str:
|
34 |
+
raise ValueError('Expected seq to be a string.')
|
35 |
+
if len(seq) != 3:
|
36 |
+
raise ValueError("Expected 3 axes, got `{}`.".format(seq))
|
37 |
+
|
38 |
+
intrinsic = seq.isupper()
|
39 |
+
extrinsic = seq.islower()
|
40 |
+
if not (intrinsic or extrinsic):
|
41 |
+
raise ValueError("seq must either be fully uppercase (for extrinsic "
|
42 |
+
"rotations), or fully lowercase, for intrinsic "
|
43 |
+
"rotations).")
|
44 |
+
|
45 |
+
i, j, k = seq.lower()
|
46 |
+
if (i == j) or (j == k):
|
47 |
+
raise ValueError("Consecutive axes must be different")
|
48 |
+
|
49 |
+
bad = set(seq) - set('xyzXYZ')
|
50 |
+
if bad:
|
51 |
+
raise ValueError("Expected axes from `seq` to be from "
|
52 |
+
"['x', 'y', 'z'] or ['X', 'Y', 'Z'], "
|
53 |
+
"got {}".format(''.join(bad)))
|
54 |
+
|
55 |
+
return extrinsic
|
56 |
+
|
57 |
+
|
58 |
+
class Quaternion(Expr):
|
59 |
+
"""Provides basic quaternion operations.
|
60 |
+
Quaternion objects can be instantiated as ``Quaternion(a, b, c, d)``
|
61 |
+
as in $q = a + bi + cj + dk$.
|
62 |
+
|
63 |
+
Parameters
|
64 |
+
==========
|
65 |
+
|
66 |
+
norm : None or number
|
67 |
+
Pre-defined quaternion norm. If a value is given, Quaternion.norm
|
68 |
+
returns this pre-defined value instead of calculating the norm
|
69 |
+
|
70 |
+
Examples
|
71 |
+
========
|
72 |
+
|
73 |
+
>>> from sympy import Quaternion
|
74 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
75 |
+
>>> q
|
76 |
+
1 + 2*i + 3*j + 4*k
|
77 |
+
|
78 |
+
Quaternions over complex fields can be defined as:
|
79 |
+
|
80 |
+
>>> from sympy import Quaternion
|
81 |
+
>>> from sympy import symbols, I
|
82 |
+
>>> x = symbols('x')
|
83 |
+
>>> q1 = Quaternion(x, x**3, x, x**2, real_field = False)
|
84 |
+
>>> q2 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
85 |
+
>>> q1
|
86 |
+
x + x**3*i + x*j + x**2*k
|
87 |
+
>>> q2
|
88 |
+
(3 + 4*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k
|
89 |
+
|
90 |
+
Defining symbolic unit quaternions:
|
91 |
+
|
92 |
+
>>> from sympy import Quaternion
|
93 |
+
>>> from sympy.abc import w, x, y, z
|
94 |
+
>>> q = Quaternion(w, x, y, z, norm=1)
|
95 |
+
>>> q
|
96 |
+
w + x*i + y*j + z*k
|
97 |
+
>>> q.norm()
|
98 |
+
1
|
99 |
+
|
100 |
+
References
|
101 |
+
==========
|
102 |
+
|
103 |
+
.. [1] https://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/
|
104 |
+
.. [2] https://en.wikipedia.org/wiki/Quaternion
|
105 |
+
|
106 |
+
"""
|
107 |
+
_op_priority = 11.0
|
108 |
+
|
109 |
+
is_commutative = False
|
110 |
+
|
111 |
+
def __new__(cls, a=0, b=0, c=0, d=0, real_field=True, norm=None):
|
112 |
+
a, b, c, d = map(sympify, (a, b, c, d))
|
113 |
+
|
114 |
+
if any(i.is_commutative is False for i in [a, b, c, d]):
|
115 |
+
raise ValueError("arguments have to be commutative")
|
116 |
+
obj = super().__new__(cls, a, b, c, d)
|
117 |
+
obj._real_field = real_field
|
118 |
+
obj.set_norm(norm)
|
119 |
+
return obj
|
120 |
+
|
121 |
+
def set_norm(self, norm):
|
122 |
+
"""Sets norm of an already instantiated quaternion.
|
123 |
+
|
124 |
+
Parameters
|
125 |
+
==========
|
126 |
+
|
127 |
+
norm : None or number
|
128 |
+
Pre-defined quaternion norm. If a value is given, Quaternion.norm
|
129 |
+
returns this pre-defined value instead of calculating the norm
|
130 |
+
|
131 |
+
Examples
|
132 |
+
========
|
133 |
+
|
134 |
+
>>> from sympy import Quaternion
|
135 |
+
>>> from sympy.abc import a, b, c, d
|
136 |
+
>>> q = Quaternion(a, b, c, d)
|
137 |
+
>>> q.norm()
|
138 |
+
sqrt(a**2 + b**2 + c**2 + d**2)
|
139 |
+
|
140 |
+
Setting the norm:
|
141 |
+
|
142 |
+
>>> q.set_norm(1)
|
143 |
+
>>> q.norm()
|
144 |
+
1
|
145 |
+
|
146 |
+
Removing set norm:
|
147 |
+
|
148 |
+
>>> q.set_norm(None)
|
149 |
+
>>> q.norm()
|
150 |
+
sqrt(a**2 + b**2 + c**2 + d**2)
|
151 |
+
|
152 |
+
"""
|
153 |
+
norm = sympify(norm)
|
154 |
+
_check_norm(self.args, norm)
|
155 |
+
self._norm = norm
|
156 |
+
|
157 |
+
@property
|
158 |
+
def a(self):
|
159 |
+
return self.args[0]
|
160 |
+
|
161 |
+
@property
|
162 |
+
def b(self):
|
163 |
+
return self.args[1]
|
164 |
+
|
165 |
+
@property
|
166 |
+
def c(self):
|
167 |
+
return self.args[2]
|
168 |
+
|
169 |
+
@property
|
170 |
+
def d(self):
|
171 |
+
return self.args[3]
|
172 |
+
|
173 |
+
@property
|
174 |
+
def real_field(self):
|
175 |
+
return self._real_field
|
176 |
+
|
177 |
+
@property
|
178 |
+
def product_matrix_left(self):
|
179 |
+
r"""Returns 4 x 4 Matrix equivalent to a Hamilton product from the
|
180 |
+
left. This can be useful when treating quaternion elements as column
|
181 |
+
vectors. Given a quaternion $q = a + bi + cj + dk$ where a, b, c and d
|
182 |
+
are real numbers, the product matrix from the left is:
|
183 |
+
|
184 |
+
.. math::
|
185 |
+
|
186 |
+
M = \begin{bmatrix} a &-b &-c &-d \\
|
187 |
+
b & a &-d & c \\
|
188 |
+
c & d & a &-b \\
|
189 |
+
d &-c & b & a \end{bmatrix}
|
190 |
+
|
191 |
+
Examples
|
192 |
+
========
|
193 |
+
|
194 |
+
>>> from sympy import Quaternion
|
195 |
+
>>> from sympy.abc import a, b, c, d
|
196 |
+
>>> q1 = Quaternion(1, 0, 0, 1)
|
197 |
+
>>> q2 = Quaternion(a, b, c, d)
|
198 |
+
>>> q1.product_matrix_left
|
199 |
+
Matrix([
|
200 |
+
[1, 0, 0, -1],
|
201 |
+
[0, 1, -1, 0],
|
202 |
+
[0, 1, 1, 0],
|
203 |
+
[1, 0, 0, 1]])
|
204 |
+
|
205 |
+
>>> q1.product_matrix_left * q2.to_Matrix()
|
206 |
+
Matrix([
|
207 |
+
[a - d],
|
208 |
+
[b - c],
|
209 |
+
[b + c],
|
210 |
+
[a + d]])
|
211 |
+
|
212 |
+
This is equivalent to:
|
213 |
+
|
214 |
+
>>> (q1 * q2).to_Matrix()
|
215 |
+
Matrix([
|
216 |
+
[a - d],
|
217 |
+
[b - c],
|
218 |
+
[b + c],
|
219 |
+
[a + d]])
|
220 |
+
"""
|
221 |
+
return Matrix([
|
222 |
+
[self.a, -self.b, -self.c, -self.d],
|
223 |
+
[self.b, self.a, -self.d, self.c],
|
224 |
+
[self.c, self.d, self.a, -self.b],
|
225 |
+
[self.d, -self.c, self.b, self.a]])
|
226 |
+
|
227 |
+
@property
|
228 |
+
def product_matrix_right(self):
|
229 |
+
r"""Returns 4 x 4 Matrix equivalent to a Hamilton product from the
|
230 |
+
right. This can be useful when treating quaternion elements as column
|
231 |
+
vectors. Given a quaternion $q = a + bi + cj + dk$ where a, b, c and d
|
232 |
+
are real numbers, the product matrix from the left is:
|
233 |
+
|
234 |
+
.. math::
|
235 |
+
|
236 |
+
M = \begin{bmatrix} a &-b &-c &-d \\
|
237 |
+
b & a & d &-c \\
|
238 |
+
c &-d & a & b \\
|
239 |
+
d & c &-b & a \end{bmatrix}
|
240 |
+
|
241 |
+
|
242 |
+
Examples
|
243 |
+
========
|
244 |
+
|
245 |
+
>>> from sympy import Quaternion
|
246 |
+
>>> from sympy.abc import a, b, c, d
|
247 |
+
>>> q1 = Quaternion(a, b, c, d)
|
248 |
+
>>> q2 = Quaternion(1, 0, 0, 1)
|
249 |
+
>>> q2.product_matrix_right
|
250 |
+
Matrix([
|
251 |
+
[1, 0, 0, -1],
|
252 |
+
[0, 1, 1, 0],
|
253 |
+
[0, -1, 1, 0],
|
254 |
+
[1, 0, 0, 1]])
|
255 |
+
|
256 |
+
Note the switched arguments: the matrix represents the quaternion on
|
257 |
+
the right, but is still considered as a matrix multiplication from the
|
258 |
+
left.
|
259 |
+
|
260 |
+
>>> q2.product_matrix_right * q1.to_Matrix()
|
261 |
+
Matrix([
|
262 |
+
[ a - d],
|
263 |
+
[ b + c],
|
264 |
+
[-b + c],
|
265 |
+
[ a + d]])
|
266 |
+
|
267 |
+
This is equivalent to:
|
268 |
+
|
269 |
+
>>> (q1 * q2).to_Matrix()
|
270 |
+
Matrix([
|
271 |
+
[ a - d],
|
272 |
+
[ b + c],
|
273 |
+
[-b + c],
|
274 |
+
[ a + d]])
|
275 |
+
"""
|
276 |
+
return Matrix([
|
277 |
+
[self.a, -self.b, -self.c, -self.d],
|
278 |
+
[self.b, self.a, self.d, -self.c],
|
279 |
+
[self.c, -self.d, self.a, self.b],
|
280 |
+
[self.d, self.c, -self.b, self.a]])
|
281 |
+
|
282 |
+
def to_Matrix(self, vector_only=False):
|
283 |
+
"""Returns elements of quaternion as a column vector.
|
284 |
+
By default, a ``Matrix`` of length 4 is returned, with the real part as the
|
285 |
+
first element.
|
286 |
+
If ``vector_only`` is ``True``, returns only imaginary part as a Matrix of
|
287 |
+
length 3.
|
288 |
+
|
289 |
+
Parameters
|
290 |
+
==========
|
291 |
+
|
292 |
+
vector_only : bool
|
293 |
+
If True, only imaginary part is returned.
|
294 |
+
Default value: False
|
295 |
+
|
296 |
+
Returns
|
297 |
+
=======
|
298 |
+
|
299 |
+
Matrix
|
300 |
+
A column vector constructed by the elements of the quaternion.
|
301 |
+
|
302 |
+
Examples
|
303 |
+
========
|
304 |
+
|
305 |
+
>>> from sympy import Quaternion
|
306 |
+
>>> from sympy.abc import a, b, c, d
|
307 |
+
>>> q = Quaternion(a, b, c, d)
|
308 |
+
>>> q
|
309 |
+
a + b*i + c*j + d*k
|
310 |
+
|
311 |
+
>>> q.to_Matrix()
|
312 |
+
Matrix([
|
313 |
+
[a],
|
314 |
+
[b],
|
315 |
+
[c],
|
316 |
+
[d]])
|
317 |
+
|
318 |
+
|
319 |
+
>>> q.to_Matrix(vector_only=True)
|
320 |
+
Matrix([
|
321 |
+
[b],
|
322 |
+
[c],
|
323 |
+
[d]])
|
324 |
+
|
325 |
+
"""
|
326 |
+
if vector_only:
|
327 |
+
return Matrix(self.args[1:])
|
328 |
+
else:
|
329 |
+
return Matrix(self.args)
|
330 |
+
|
331 |
+
@classmethod
|
332 |
+
def from_Matrix(cls, elements):
|
333 |
+
"""Returns quaternion from elements of a column vector`.
|
334 |
+
If vector_only is True, returns only imaginary part as a Matrix of
|
335 |
+
length 3.
|
336 |
+
|
337 |
+
Parameters
|
338 |
+
==========
|
339 |
+
|
340 |
+
elements : Matrix, list or tuple of length 3 or 4. If length is 3,
|
341 |
+
assume real part is zero.
|
342 |
+
Default value: False
|
343 |
+
|
344 |
+
Returns
|
345 |
+
=======
|
346 |
+
|
347 |
+
Quaternion
|
348 |
+
A quaternion created from the input elements.
|
349 |
+
|
350 |
+
Examples
|
351 |
+
========
|
352 |
+
|
353 |
+
>>> from sympy import Quaternion
|
354 |
+
>>> from sympy.abc import a, b, c, d
|
355 |
+
>>> q = Quaternion.from_Matrix([a, b, c, d])
|
356 |
+
>>> q
|
357 |
+
a + b*i + c*j + d*k
|
358 |
+
|
359 |
+
>>> q = Quaternion.from_Matrix([b, c, d])
|
360 |
+
>>> q
|
361 |
+
0 + b*i + c*j + d*k
|
362 |
+
|
363 |
+
"""
|
364 |
+
length = len(elements)
|
365 |
+
if length != 3 and length != 4:
|
366 |
+
raise ValueError("Input elements must have length 3 or 4, got {} "
|
367 |
+
"elements".format(length))
|
368 |
+
|
369 |
+
if length == 3:
|
370 |
+
return Quaternion(0, *elements)
|
371 |
+
else:
|
372 |
+
return Quaternion(*elements)
|
373 |
+
|
374 |
+
@classmethod
|
375 |
+
def from_euler(cls, angles, seq):
|
376 |
+
"""Returns quaternion equivalent to rotation represented by the Euler
|
377 |
+
angles, in the sequence defined by ``seq``.
|
378 |
+
|
379 |
+
Parameters
|
380 |
+
==========
|
381 |
+
|
382 |
+
angles : list, tuple or Matrix of 3 numbers
|
383 |
+
The Euler angles (in radians).
|
384 |
+
seq : string of length 3
|
385 |
+
Represents the sequence of rotations.
|
386 |
+
For extrinsic rotations, seq must be all lowercase and its elements
|
387 |
+
must be from the set ``{'x', 'y', 'z'}``
|
388 |
+
For intrinsic rotations, seq must be all uppercase and its elements
|
389 |
+
must be from the set ``{'X', 'Y', 'Z'}``
|
390 |
+
|
391 |
+
Returns
|
392 |
+
=======
|
393 |
+
|
394 |
+
Quaternion
|
395 |
+
The normalized rotation quaternion calculated from the Euler angles
|
396 |
+
in the given sequence.
|
397 |
+
|
398 |
+
Examples
|
399 |
+
========
|
400 |
+
|
401 |
+
>>> from sympy import Quaternion
|
402 |
+
>>> from sympy import pi
|
403 |
+
>>> q = Quaternion.from_euler([pi/2, 0, 0], 'xyz')
|
404 |
+
>>> q
|
405 |
+
sqrt(2)/2 + sqrt(2)/2*i + 0*j + 0*k
|
406 |
+
|
407 |
+
>>> q = Quaternion.from_euler([0, pi/2, pi] , 'zyz')
|
408 |
+
>>> q
|
409 |
+
0 + (-sqrt(2)/2)*i + 0*j + sqrt(2)/2*k
|
410 |
+
|
411 |
+
>>> q = Quaternion.from_euler([0, pi/2, pi] , 'ZYZ')
|
412 |
+
>>> q
|
413 |
+
0 + sqrt(2)/2*i + 0*j + sqrt(2)/2*k
|
414 |
+
|
415 |
+
"""
|
416 |
+
|
417 |
+
if len(angles) != 3:
|
418 |
+
raise ValueError("3 angles must be given.")
|
419 |
+
|
420 |
+
extrinsic = _is_extrinsic(seq)
|
421 |
+
i, j, k = seq.lower()
|
422 |
+
|
423 |
+
# get elementary basis vectors
|
424 |
+
ei = [1 if n == i else 0 for n in 'xyz']
|
425 |
+
ej = [1 if n == j else 0 for n in 'xyz']
|
426 |
+
ek = [1 if n == k else 0 for n in 'xyz']
|
427 |
+
|
428 |
+
# calculate distinct quaternions
|
429 |
+
qi = cls.from_axis_angle(ei, angles[0])
|
430 |
+
qj = cls.from_axis_angle(ej, angles[1])
|
431 |
+
qk = cls.from_axis_angle(ek, angles[2])
|
432 |
+
|
433 |
+
if extrinsic:
|
434 |
+
return trigsimp(qk * qj * qi)
|
435 |
+
else:
|
436 |
+
return trigsimp(qi * qj * qk)
|
437 |
+
|
438 |
+
def to_euler(self, seq, angle_addition=True, avoid_square_root=False):
|
439 |
+
r"""Returns Euler angles representing same rotation as the quaternion,
|
440 |
+
in the sequence given by ``seq``. This implements the method described
|
441 |
+
in [1]_.
|
442 |
+
|
443 |
+
For degenerate cases (gymbal lock cases), the third angle is
|
444 |
+
set to zero.
|
445 |
+
|
446 |
+
Parameters
|
447 |
+
==========
|
448 |
+
|
449 |
+
seq : string of length 3
|
450 |
+
Represents the sequence of rotations.
|
451 |
+
For extrinsic rotations, seq must be all lowercase and its elements
|
452 |
+
must be from the set ``{'x', 'y', 'z'}``
|
453 |
+
For intrinsic rotations, seq must be all uppercase and its elements
|
454 |
+
must be from the set ``{'X', 'Y', 'Z'}``
|
455 |
+
|
456 |
+
angle_addition : bool
|
457 |
+
When True, first and third angles are given as an addition and
|
458 |
+
subtraction of two simpler ``atan2`` expressions. When False, the
|
459 |
+
first and third angles are each given by a single more complicated
|
460 |
+
``atan2`` expression. This equivalent expression is given by:
|
461 |
+
|
462 |
+
.. math::
|
463 |
+
|
464 |
+
\operatorname{atan_2} (b,a) \pm \operatorname{atan_2} (d,c) =
|
465 |
+
\operatorname{atan_2} (bc\pm ad, ac\mp bd)
|
466 |
+
|
467 |
+
Default value: True
|
468 |
+
|
469 |
+
avoid_square_root : bool
|
470 |
+
When True, the second angle is calculated with an expression based
|
471 |
+
on ``acos``, which is slightly more complicated but avoids a square
|
472 |
+
root. When False, second angle is calculated with ``atan2``, which
|
473 |
+
is simpler and can be better for numerical reasons (some
|
474 |
+
numerical implementations of ``acos`` have problems near zero).
|
475 |
+
Default value: False
|
476 |
+
|
477 |
+
|
478 |
+
Returns
|
479 |
+
=======
|
480 |
+
|
481 |
+
Tuple
|
482 |
+
The Euler angles calculated from the quaternion
|
483 |
+
|
484 |
+
Examples
|
485 |
+
========
|
486 |
+
|
487 |
+
>>> from sympy import Quaternion
|
488 |
+
>>> from sympy.abc import a, b, c, d
|
489 |
+
>>> euler = Quaternion(a, b, c, d).to_euler('zyz')
|
490 |
+
>>> euler
|
491 |
+
(-atan2(-b, c) + atan2(d, a),
|
492 |
+
2*atan2(sqrt(b**2 + c**2), sqrt(a**2 + d**2)),
|
493 |
+
atan2(-b, c) + atan2(d, a))
|
494 |
+
|
495 |
+
|
496 |
+
References
|
497 |
+
==========
|
498 |
+
|
499 |
+
.. [1] https://doi.org/10.1371/journal.pone.0276302
|
500 |
+
|
501 |
+
"""
|
502 |
+
if self.is_zero_quaternion():
|
503 |
+
raise ValueError('Cannot convert a quaternion with norm 0.')
|
504 |
+
|
505 |
+
angles = [0, 0, 0]
|
506 |
+
|
507 |
+
extrinsic = _is_extrinsic(seq)
|
508 |
+
i, j, k = seq.lower()
|
509 |
+
|
510 |
+
# get index corresponding to elementary basis vectors
|
511 |
+
i = 'xyz'.index(i) + 1
|
512 |
+
j = 'xyz'.index(j) + 1
|
513 |
+
k = 'xyz'.index(k) + 1
|
514 |
+
|
515 |
+
if not extrinsic:
|
516 |
+
i, k = k, i
|
517 |
+
|
518 |
+
# check if sequence is symmetric
|
519 |
+
symmetric = i == k
|
520 |
+
if symmetric:
|
521 |
+
k = 6 - i - j
|
522 |
+
|
523 |
+
# parity of the permutation
|
524 |
+
sign = (i - j) * (j - k) * (k - i) // 2
|
525 |
+
|
526 |
+
# permutate elements
|
527 |
+
elements = [self.a, self.b, self.c, self.d]
|
528 |
+
a = elements[0]
|
529 |
+
b = elements[i]
|
530 |
+
c = elements[j]
|
531 |
+
d = elements[k] * sign
|
532 |
+
|
533 |
+
if not symmetric:
|
534 |
+
a, b, c, d = a - c, b + d, c + a, d - b
|
535 |
+
|
536 |
+
if avoid_square_root:
|
537 |
+
if symmetric:
|
538 |
+
n2 = self.norm()**2
|
539 |
+
angles[1] = acos((a * a + b * b - c * c - d * d) / n2)
|
540 |
+
else:
|
541 |
+
n2 = 2 * self.norm()**2
|
542 |
+
angles[1] = asin((c * c + d * d - a * a - b * b) / n2)
|
543 |
+
else:
|
544 |
+
angles[1] = 2 * atan2(sqrt(c * c + d * d), sqrt(a * a + b * b))
|
545 |
+
if not symmetric:
|
546 |
+
angles[1] -= S.Pi / 2
|
547 |
+
|
548 |
+
# Check for singularities in numerical cases
|
549 |
+
case = 0
|
550 |
+
if is_eq(c, S.Zero) and is_eq(d, S.Zero):
|
551 |
+
case = 1
|
552 |
+
if is_eq(a, S.Zero) and is_eq(b, S.Zero):
|
553 |
+
case = 2
|
554 |
+
|
555 |
+
if case == 0:
|
556 |
+
if angle_addition:
|
557 |
+
angles[0] = atan2(b, a) + atan2(d, c)
|
558 |
+
angles[2] = atan2(b, a) - atan2(d, c)
|
559 |
+
else:
|
560 |
+
angles[0] = atan2(b*c + a*d, a*c - b*d)
|
561 |
+
angles[2] = atan2(b*c - a*d, a*c + b*d)
|
562 |
+
|
563 |
+
else: # any degenerate case
|
564 |
+
angles[2 * (not extrinsic)] = S.Zero
|
565 |
+
if case == 1:
|
566 |
+
angles[2 * extrinsic] = 2 * atan2(b, a)
|
567 |
+
else:
|
568 |
+
angles[2 * extrinsic] = 2 * atan2(d, c)
|
569 |
+
angles[2 * extrinsic] *= (-1 if extrinsic else 1)
|
570 |
+
|
571 |
+
# for Tait-Bryan angles
|
572 |
+
if not symmetric:
|
573 |
+
angles[0] *= sign
|
574 |
+
|
575 |
+
if extrinsic:
|
576 |
+
return tuple(angles[::-1])
|
577 |
+
else:
|
578 |
+
return tuple(angles)
|
579 |
+
|
580 |
+
@classmethod
|
581 |
+
def from_axis_angle(cls, vector, angle):
|
582 |
+
"""Returns a rotation quaternion given the axis and the angle of rotation.
|
583 |
+
|
584 |
+
Parameters
|
585 |
+
==========
|
586 |
+
|
587 |
+
vector : tuple of three numbers
|
588 |
+
The vector representation of the given axis.
|
589 |
+
angle : number
|
590 |
+
The angle by which axis is rotated (in radians).
|
591 |
+
|
592 |
+
Returns
|
593 |
+
=======
|
594 |
+
|
595 |
+
Quaternion
|
596 |
+
The normalized rotation quaternion calculated from the given axis and the angle of rotation.
|
597 |
+
|
598 |
+
Examples
|
599 |
+
========
|
600 |
+
|
601 |
+
>>> from sympy import Quaternion
|
602 |
+
>>> from sympy import pi, sqrt
|
603 |
+
>>> q = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), 2*pi/3)
|
604 |
+
>>> q
|
605 |
+
1/2 + 1/2*i + 1/2*j + 1/2*k
|
606 |
+
|
607 |
+
"""
|
608 |
+
(x, y, z) = vector
|
609 |
+
norm = sqrt(x**2 + y**2 + z**2)
|
610 |
+
(x, y, z) = (x / norm, y / norm, z / norm)
|
611 |
+
s = sin(angle * S.Half)
|
612 |
+
a = cos(angle * S.Half)
|
613 |
+
b = x * s
|
614 |
+
c = y * s
|
615 |
+
d = z * s
|
616 |
+
|
617 |
+
# note that this quaternion is already normalized by construction:
|
618 |
+
# c^2 + (s*x)^2 + (s*y)^2 + (s*z)^2 = c^2 + s^2*(x^2 + y^2 + z^2) = c^2 + s^2 * 1 = c^2 + s^2 = 1
|
619 |
+
# so, what we return is a normalized quaternion
|
620 |
+
|
621 |
+
return cls(a, b, c, d)
|
622 |
+
|
623 |
+
@classmethod
|
624 |
+
def from_rotation_matrix(cls, M):
|
625 |
+
"""Returns the equivalent quaternion of a matrix. The quaternion will be normalized
|
626 |
+
only if the matrix is special orthogonal (orthogonal and det(M) = 1).
|
627 |
+
|
628 |
+
Parameters
|
629 |
+
==========
|
630 |
+
|
631 |
+
M : Matrix
|
632 |
+
Input matrix to be converted to equivalent quaternion. M must be special
|
633 |
+
orthogonal (orthogonal and det(M) = 1) for the quaternion to be normalized.
|
634 |
+
|
635 |
+
Returns
|
636 |
+
=======
|
637 |
+
|
638 |
+
Quaternion
|
639 |
+
The quaternion equivalent to given matrix.
|
640 |
+
|
641 |
+
Examples
|
642 |
+
========
|
643 |
+
|
644 |
+
>>> from sympy import Quaternion
|
645 |
+
>>> from sympy import Matrix, symbols, cos, sin, trigsimp
|
646 |
+
>>> x = symbols('x')
|
647 |
+
>>> M = Matrix([[cos(x), -sin(x), 0], [sin(x), cos(x), 0], [0, 0, 1]])
|
648 |
+
>>> q = trigsimp(Quaternion.from_rotation_matrix(M))
|
649 |
+
>>> q
|
650 |
+
sqrt(2)*sqrt(cos(x) + 1)/2 + 0*i + 0*j + sqrt(2 - 2*cos(x))*sign(sin(x))/2*k
|
651 |
+
|
652 |
+
"""
|
653 |
+
|
654 |
+
absQ = M.det()**Rational(1, 3)
|
655 |
+
|
656 |
+
a = sqrt(absQ + M[0, 0] + M[1, 1] + M[2, 2]) / 2
|
657 |
+
b = sqrt(absQ + M[0, 0] - M[1, 1] - M[2, 2]) / 2
|
658 |
+
c = sqrt(absQ - M[0, 0] + M[1, 1] - M[2, 2]) / 2
|
659 |
+
d = sqrt(absQ - M[0, 0] - M[1, 1] + M[2, 2]) / 2
|
660 |
+
|
661 |
+
b = b * sign(M[2, 1] - M[1, 2])
|
662 |
+
c = c * sign(M[0, 2] - M[2, 0])
|
663 |
+
d = d * sign(M[1, 0] - M[0, 1])
|
664 |
+
|
665 |
+
return Quaternion(a, b, c, d)
|
666 |
+
|
667 |
+
def __add__(self, other):
|
668 |
+
return self.add(other)
|
669 |
+
|
670 |
+
def __radd__(self, other):
|
671 |
+
return self.add(other)
|
672 |
+
|
673 |
+
def __sub__(self, other):
|
674 |
+
return self.add(other*-1)
|
675 |
+
|
676 |
+
def __mul__(self, other):
|
677 |
+
return self._generic_mul(self, _sympify(other))
|
678 |
+
|
679 |
+
def __rmul__(self, other):
|
680 |
+
return self._generic_mul(_sympify(other), self)
|
681 |
+
|
682 |
+
def __pow__(self, p):
|
683 |
+
return self.pow(p)
|
684 |
+
|
685 |
+
def __neg__(self):
|
686 |
+
return Quaternion(-self.a, -self.b, -self.c, -self.d)
|
687 |
+
|
688 |
+
def __truediv__(self, other):
|
689 |
+
return self * sympify(other)**-1
|
690 |
+
|
691 |
+
def __rtruediv__(self, other):
|
692 |
+
return sympify(other) * self**-1
|
693 |
+
|
694 |
+
def _eval_Integral(self, *args):
|
695 |
+
return self.integrate(*args)
|
696 |
+
|
697 |
+
def diff(self, *symbols, **kwargs):
|
698 |
+
kwargs.setdefault('evaluate', True)
|
699 |
+
return self.func(*[a.diff(*symbols, **kwargs) for a in self.args])
|
700 |
+
|
701 |
+
def add(self, other):
|
702 |
+
"""Adds quaternions.
|
703 |
+
|
704 |
+
Parameters
|
705 |
+
==========
|
706 |
+
|
707 |
+
other : Quaternion
|
708 |
+
The quaternion to add to current (self) quaternion.
|
709 |
+
|
710 |
+
Returns
|
711 |
+
=======
|
712 |
+
|
713 |
+
Quaternion
|
714 |
+
The resultant quaternion after adding self to other
|
715 |
+
|
716 |
+
Examples
|
717 |
+
========
|
718 |
+
|
719 |
+
>>> from sympy import Quaternion
|
720 |
+
>>> from sympy import symbols
|
721 |
+
>>> q1 = Quaternion(1, 2, 3, 4)
|
722 |
+
>>> q2 = Quaternion(5, 6, 7, 8)
|
723 |
+
>>> q1.add(q2)
|
724 |
+
6 + 8*i + 10*j + 12*k
|
725 |
+
>>> q1 + 5
|
726 |
+
6 + 2*i + 3*j + 4*k
|
727 |
+
>>> x = symbols('x', real = True)
|
728 |
+
>>> q1.add(x)
|
729 |
+
(x + 1) + 2*i + 3*j + 4*k
|
730 |
+
|
731 |
+
Quaternions over complex fields :
|
732 |
+
|
733 |
+
>>> from sympy import Quaternion
|
734 |
+
>>> from sympy import I
|
735 |
+
>>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
736 |
+
>>> q3.add(2 + 3*I)
|
737 |
+
(5 + 7*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k
|
738 |
+
|
739 |
+
"""
|
740 |
+
q1 = self
|
741 |
+
q2 = sympify(other)
|
742 |
+
|
743 |
+
# If q2 is a number or a SymPy expression instead of a quaternion
|
744 |
+
if not isinstance(q2, Quaternion):
|
745 |
+
if q1.real_field and q2.is_complex:
|
746 |
+
return Quaternion(re(q2) + q1.a, im(q2) + q1.b, q1.c, q1.d)
|
747 |
+
elif q2.is_commutative:
|
748 |
+
return Quaternion(q1.a + q2, q1.b, q1.c, q1.d)
|
749 |
+
else:
|
750 |
+
raise ValueError("Only commutative expressions can be added with a Quaternion.")
|
751 |
+
|
752 |
+
return Quaternion(q1.a + q2.a, q1.b + q2.b, q1.c + q2.c, q1.d
|
753 |
+
+ q2.d)
|
754 |
+
|
755 |
+
def mul(self, other):
|
756 |
+
"""Multiplies quaternions.
|
757 |
+
|
758 |
+
Parameters
|
759 |
+
==========
|
760 |
+
|
761 |
+
other : Quaternion or symbol
|
762 |
+
The quaternion to multiply to current (self) quaternion.
|
763 |
+
|
764 |
+
Returns
|
765 |
+
=======
|
766 |
+
|
767 |
+
Quaternion
|
768 |
+
The resultant quaternion after multiplying self with other
|
769 |
+
|
770 |
+
Examples
|
771 |
+
========
|
772 |
+
|
773 |
+
>>> from sympy import Quaternion
|
774 |
+
>>> from sympy import symbols
|
775 |
+
>>> q1 = Quaternion(1, 2, 3, 4)
|
776 |
+
>>> q2 = Quaternion(5, 6, 7, 8)
|
777 |
+
>>> q1.mul(q2)
|
778 |
+
(-60) + 12*i + 30*j + 24*k
|
779 |
+
>>> q1.mul(2)
|
780 |
+
2 + 4*i + 6*j + 8*k
|
781 |
+
>>> x = symbols('x', real = True)
|
782 |
+
>>> q1.mul(x)
|
783 |
+
x + 2*x*i + 3*x*j + 4*x*k
|
784 |
+
|
785 |
+
Quaternions over complex fields :
|
786 |
+
|
787 |
+
>>> from sympy import Quaternion
|
788 |
+
>>> from sympy import I
|
789 |
+
>>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
790 |
+
>>> q3.mul(2 + 3*I)
|
791 |
+
(2 + 3*I)*(3 + 4*I) + (2 + 3*I)*(2 + 5*I)*i + 0*j + (2 + 3*I)*(7 + 8*I)*k
|
792 |
+
|
793 |
+
"""
|
794 |
+
return self._generic_mul(self, _sympify(other))
|
795 |
+
|
796 |
+
@staticmethod
|
797 |
+
def _generic_mul(q1, q2):
|
798 |
+
"""Generic multiplication.
|
799 |
+
|
800 |
+
Parameters
|
801 |
+
==========
|
802 |
+
|
803 |
+
q1 : Quaternion or symbol
|
804 |
+
q2 : Quaternion or symbol
|
805 |
+
|
806 |
+
It is important to note that if neither q1 nor q2 is a Quaternion,
|
807 |
+
this function simply returns q1 * q2.
|
808 |
+
|
809 |
+
Returns
|
810 |
+
=======
|
811 |
+
|
812 |
+
Quaternion
|
813 |
+
The resultant quaternion after multiplying q1 and q2
|
814 |
+
|
815 |
+
Examples
|
816 |
+
========
|
817 |
+
|
818 |
+
>>> from sympy import Quaternion
|
819 |
+
>>> from sympy import Symbol, S
|
820 |
+
>>> q1 = Quaternion(1, 2, 3, 4)
|
821 |
+
>>> q2 = Quaternion(5, 6, 7, 8)
|
822 |
+
>>> Quaternion._generic_mul(q1, q2)
|
823 |
+
(-60) + 12*i + 30*j + 24*k
|
824 |
+
>>> Quaternion._generic_mul(q1, S(2))
|
825 |
+
2 + 4*i + 6*j + 8*k
|
826 |
+
>>> x = Symbol('x', real = True)
|
827 |
+
>>> Quaternion._generic_mul(q1, x)
|
828 |
+
x + 2*x*i + 3*x*j + 4*x*k
|
829 |
+
|
830 |
+
Quaternions over complex fields :
|
831 |
+
|
832 |
+
>>> from sympy import I
|
833 |
+
>>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
834 |
+
>>> Quaternion._generic_mul(q3, 2 + 3*I)
|
835 |
+
(2 + 3*I)*(3 + 4*I) + (2 + 3*I)*(2 + 5*I)*i + 0*j + (2 + 3*I)*(7 + 8*I)*k
|
836 |
+
|
837 |
+
"""
|
838 |
+
# None is a Quaternion:
|
839 |
+
if not isinstance(q1, Quaternion) and not isinstance(q2, Quaternion):
|
840 |
+
return q1 * q2
|
841 |
+
|
842 |
+
# If q1 is a number or a SymPy expression instead of a quaternion
|
843 |
+
if not isinstance(q1, Quaternion):
|
844 |
+
if q2.real_field and q1.is_complex:
|
845 |
+
return Quaternion(re(q1), im(q1), 0, 0) * q2
|
846 |
+
elif q1.is_commutative:
|
847 |
+
return Quaternion(q1 * q2.a, q1 * q2.b, q1 * q2.c, q1 * q2.d)
|
848 |
+
else:
|
849 |
+
raise ValueError("Only commutative expressions can be multiplied with a Quaternion.")
|
850 |
+
|
851 |
+
# If q2 is a number or a SymPy expression instead of a quaternion
|
852 |
+
if not isinstance(q2, Quaternion):
|
853 |
+
if q1.real_field and q2.is_complex:
|
854 |
+
return q1 * Quaternion(re(q2), im(q2), 0, 0)
|
855 |
+
elif q2.is_commutative:
|
856 |
+
return Quaternion(q2 * q1.a, q2 * q1.b, q2 * q1.c, q2 * q1.d)
|
857 |
+
else:
|
858 |
+
raise ValueError("Only commutative expressions can be multiplied with a Quaternion.")
|
859 |
+
|
860 |
+
# If any of the quaternions has a fixed norm, pre-compute norm
|
861 |
+
if q1._norm is None and q2._norm is None:
|
862 |
+
norm = None
|
863 |
+
else:
|
864 |
+
norm = q1.norm() * q2.norm()
|
865 |
+
|
866 |
+
return Quaternion(-q1.b*q2.b - q1.c*q2.c - q1.d*q2.d + q1.a*q2.a,
|
867 |
+
q1.b*q2.a + q1.c*q2.d - q1.d*q2.c + q1.a*q2.b,
|
868 |
+
-q1.b*q2.d + q1.c*q2.a + q1.d*q2.b + q1.a*q2.c,
|
869 |
+
q1.b*q2.c - q1.c*q2.b + q1.d*q2.a + q1.a * q2.d,
|
870 |
+
norm=norm)
|
871 |
+
|
872 |
+
def _eval_conjugate(self):
|
873 |
+
"""Returns the conjugate of the quaternion."""
|
874 |
+
q = self
|
875 |
+
return Quaternion(q.a, -q.b, -q.c, -q.d, norm=q._norm)
|
876 |
+
|
877 |
+
def norm(self):
|
878 |
+
"""Returns the norm of the quaternion."""
|
879 |
+
if self._norm is None: # check if norm is pre-defined
|
880 |
+
q = self
|
881 |
+
# trigsimp is used to simplify sin(x)^2 + cos(x)^2 (these terms
|
882 |
+
# arise when from_axis_angle is used).
|
883 |
+
return sqrt(trigsimp(q.a**2 + q.b**2 + q.c**2 + q.d**2))
|
884 |
+
|
885 |
+
return self._norm
|
886 |
+
|
887 |
+
def normalize(self):
|
888 |
+
"""Returns the normalized form of the quaternion."""
|
889 |
+
q = self
|
890 |
+
return q * (1/q.norm())
|
891 |
+
|
892 |
+
def inverse(self):
|
893 |
+
"""Returns the inverse of the quaternion."""
|
894 |
+
q = self
|
895 |
+
if not q.norm():
|
896 |
+
raise ValueError("Cannot compute inverse for a quaternion with zero norm")
|
897 |
+
return conjugate(q) * (1/q.norm()**2)
|
898 |
+
|
899 |
+
def pow(self, p):
|
900 |
+
"""Finds the pth power of the quaternion.
|
901 |
+
|
902 |
+
Parameters
|
903 |
+
==========
|
904 |
+
|
905 |
+
p : int
|
906 |
+
Power to be applied on quaternion.
|
907 |
+
|
908 |
+
Returns
|
909 |
+
=======
|
910 |
+
|
911 |
+
Quaternion
|
912 |
+
Returns the p-th power of the current quaternion.
|
913 |
+
Returns the inverse if p = -1.
|
914 |
+
|
915 |
+
Examples
|
916 |
+
========
|
917 |
+
|
918 |
+
>>> from sympy import Quaternion
|
919 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
920 |
+
>>> q.pow(4)
|
921 |
+
668 + (-224)*i + (-336)*j + (-448)*k
|
922 |
+
|
923 |
+
"""
|
924 |
+
try:
|
925 |
+
q, p = self, as_int(p)
|
926 |
+
except ValueError:
|
927 |
+
return NotImplemented
|
928 |
+
|
929 |
+
if p < 0:
|
930 |
+
q, p = q.inverse(), -p
|
931 |
+
|
932 |
+
if p == 1:
|
933 |
+
return q
|
934 |
+
|
935 |
+
res = Quaternion(1, 0, 0, 0)
|
936 |
+
while p > 0:
|
937 |
+
if p & 1:
|
938 |
+
res *= q
|
939 |
+
q *= q
|
940 |
+
p >>= 1
|
941 |
+
|
942 |
+
return res
|
943 |
+
|
944 |
+
def exp(self):
|
945 |
+
"""Returns the exponential of $q$, given by $e^q$.
|
946 |
+
|
947 |
+
Returns
|
948 |
+
=======
|
949 |
+
|
950 |
+
Quaternion
|
951 |
+
The exponential of the quaternion.
|
952 |
+
|
953 |
+
Examples
|
954 |
+
========
|
955 |
+
|
956 |
+
>>> from sympy import Quaternion
|
957 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
958 |
+
>>> q.exp()
|
959 |
+
E*cos(sqrt(29))
|
960 |
+
+ 2*sqrt(29)*E*sin(sqrt(29))/29*i
|
961 |
+
+ 3*sqrt(29)*E*sin(sqrt(29))/29*j
|
962 |
+
+ 4*sqrt(29)*E*sin(sqrt(29))/29*k
|
963 |
+
|
964 |
+
"""
|
965 |
+
# exp(q) = e^a(cos||v|| + v/||v||*sin||v||)
|
966 |
+
q = self
|
967 |
+
vector_norm = sqrt(q.b**2 + q.c**2 + q.d**2)
|
968 |
+
a = exp(q.a) * cos(vector_norm)
|
969 |
+
b = exp(q.a) * sin(vector_norm) * q.b / vector_norm
|
970 |
+
c = exp(q.a) * sin(vector_norm) * q.c / vector_norm
|
971 |
+
d = exp(q.a) * sin(vector_norm) * q.d / vector_norm
|
972 |
+
|
973 |
+
return Quaternion(a, b, c, d)
|
974 |
+
|
975 |
+
def log(self):
|
976 |
+
r"""Returns the logarithm of the quaternion, given by $\log q$.
|
977 |
+
|
978 |
+
Examples
|
979 |
+
========
|
980 |
+
|
981 |
+
>>> from sympy import Quaternion
|
982 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
983 |
+
>>> q.log()
|
984 |
+
log(sqrt(30))
|
985 |
+
+ 2*sqrt(29)*acos(sqrt(30)/30)/29*i
|
986 |
+
+ 3*sqrt(29)*acos(sqrt(30)/30)/29*j
|
987 |
+
+ 4*sqrt(29)*acos(sqrt(30)/30)/29*k
|
988 |
+
|
989 |
+
"""
|
990 |
+
# log(q) = log||q|| + v/||v||*arccos(a/||q||)
|
991 |
+
q = self
|
992 |
+
vector_norm = sqrt(q.b**2 + q.c**2 + q.d**2)
|
993 |
+
q_norm = q.norm()
|
994 |
+
a = ln(q_norm)
|
995 |
+
b = q.b * acos(q.a / q_norm) / vector_norm
|
996 |
+
c = q.c * acos(q.a / q_norm) / vector_norm
|
997 |
+
d = q.d * acos(q.a / q_norm) / vector_norm
|
998 |
+
|
999 |
+
return Quaternion(a, b, c, d)
|
1000 |
+
|
1001 |
+
def _eval_subs(self, *args):
|
1002 |
+
elements = [i.subs(*args) for i in self.args]
|
1003 |
+
norm = self._norm
|
1004 |
+
if norm is not None:
|
1005 |
+
norm = norm.subs(*args)
|
1006 |
+
_check_norm(elements, norm)
|
1007 |
+
return Quaternion(*elements, norm=norm)
|
1008 |
+
|
1009 |
+
def _eval_evalf(self, prec):
|
1010 |
+
"""Returns the floating point approximations (decimal numbers) of the quaternion.
|
1011 |
+
|
1012 |
+
Returns
|
1013 |
+
=======
|
1014 |
+
|
1015 |
+
Quaternion
|
1016 |
+
Floating point approximations of quaternion(self)
|
1017 |
+
|
1018 |
+
Examples
|
1019 |
+
========
|
1020 |
+
|
1021 |
+
>>> from sympy import Quaternion
|
1022 |
+
>>> from sympy import sqrt
|
1023 |
+
>>> q = Quaternion(1/sqrt(1), 1/sqrt(2), 1/sqrt(3), 1/sqrt(4))
|
1024 |
+
>>> q.evalf()
|
1025 |
+
1.00000000000000
|
1026 |
+
+ 0.707106781186547*i
|
1027 |
+
+ 0.577350269189626*j
|
1028 |
+
+ 0.500000000000000*k
|
1029 |
+
|
1030 |
+
"""
|
1031 |
+
nprec = prec_to_dps(prec)
|
1032 |
+
return Quaternion(*[arg.evalf(n=nprec) for arg in self.args])
|
1033 |
+
|
1034 |
+
def pow_cos_sin(self, p):
|
1035 |
+
"""Computes the pth power in the cos-sin form.
|
1036 |
+
|
1037 |
+
Parameters
|
1038 |
+
==========
|
1039 |
+
|
1040 |
+
p : int
|
1041 |
+
Power to be applied on quaternion.
|
1042 |
+
|
1043 |
+
Returns
|
1044 |
+
=======
|
1045 |
+
|
1046 |
+
Quaternion
|
1047 |
+
The p-th power in the cos-sin form.
|
1048 |
+
|
1049 |
+
Examples
|
1050 |
+
========
|
1051 |
+
|
1052 |
+
>>> from sympy import Quaternion
|
1053 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
1054 |
+
>>> q.pow_cos_sin(4)
|
1055 |
+
900*cos(4*acos(sqrt(30)/30))
|
1056 |
+
+ 1800*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*i
|
1057 |
+
+ 2700*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*j
|
1058 |
+
+ 3600*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*k
|
1059 |
+
|
1060 |
+
"""
|
1061 |
+
# q = ||q||*(cos(a) + u*sin(a))
|
1062 |
+
# q^p = ||q||^p * (cos(p*a) + u*sin(p*a))
|
1063 |
+
|
1064 |
+
q = self
|
1065 |
+
(v, angle) = q.to_axis_angle()
|
1066 |
+
q2 = Quaternion.from_axis_angle(v, p * angle)
|
1067 |
+
return q2 * (q.norm()**p)
|
1068 |
+
|
1069 |
+
def integrate(self, *args):
|
1070 |
+
"""Computes integration of quaternion.
|
1071 |
+
|
1072 |
+
Returns
|
1073 |
+
=======
|
1074 |
+
|
1075 |
+
Quaternion
|
1076 |
+
Integration of the quaternion(self) with the given variable.
|
1077 |
+
|
1078 |
+
Examples
|
1079 |
+
========
|
1080 |
+
|
1081 |
+
Indefinite Integral of quaternion :
|
1082 |
+
|
1083 |
+
>>> from sympy import Quaternion
|
1084 |
+
>>> from sympy.abc import x
|
1085 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
1086 |
+
>>> q.integrate(x)
|
1087 |
+
x + 2*x*i + 3*x*j + 4*x*k
|
1088 |
+
|
1089 |
+
Definite integral of quaternion :
|
1090 |
+
|
1091 |
+
>>> from sympy import Quaternion
|
1092 |
+
>>> from sympy.abc import x
|
1093 |
+
>>> q = Quaternion(1, 2, 3, 4)
|
1094 |
+
>>> q.integrate((x, 1, 5))
|
1095 |
+
4 + 8*i + 12*j + 16*k
|
1096 |
+
|
1097 |
+
"""
|
1098 |
+
# TODO: is this expression correct?
|
1099 |
+
return Quaternion(integrate(self.a, *args), integrate(self.b, *args),
|
1100 |
+
integrate(self.c, *args), integrate(self.d, *args))
|
1101 |
+
|
1102 |
+
@staticmethod
|
1103 |
+
def rotate_point(pin, r):
|
1104 |
+
"""Returns the coordinates of the point pin (a 3 tuple) after rotation.
|
1105 |
+
|
1106 |
+
Parameters
|
1107 |
+
==========
|
1108 |
+
|
1109 |
+
pin : tuple
|
1110 |
+
A 3-element tuple of coordinates of a point which needs to be
|
1111 |
+
rotated.
|
1112 |
+
r : Quaternion or tuple
|
1113 |
+
Axis and angle of rotation.
|
1114 |
+
|
1115 |
+
It's important to note that when r is a tuple, it must be of the form
|
1116 |
+
(axis, angle)
|
1117 |
+
|
1118 |
+
Returns
|
1119 |
+
=======
|
1120 |
+
|
1121 |
+
tuple
|
1122 |
+
The coordinates of the point after rotation.
|
1123 |
+
|
1124 |
+
Examples
|
1125 |
+
========
|
1126 |
+
|
1127 |
+
>>> from sympy import Quaternion
|
1128 |
+
>>> from sympy import symbols, trigsimp, cos, sin
|
1129 |
+
>>> x = symbols('x')
|
1130 |
+
>>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
|
1131 |
+
>>> trigsimp(Quaternion.rotate_point((1, 1, 1), q))
|
1132 |
+
(sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)
|
1133 |
+
>>> (axis, angle) = q.to_axis_angle()
|
1134 |
+
>>> trigsimp(Quaternion.rotate_point((1, 1, 1), (axis, angle)))
|
1135 |
+
(sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)
|
1136 |
+
|
1137 |
+
"""
|
1138 |
+
if isinstance(r, tuple):
|
1139 |
+
# if r is of the form (vector, angle)
|
1140 |
+
q = Quaternion.from_axis_angle(r[0], r[1])
|
1141 |
+
else:
|
1142 |
+
# if r is a quaternion
|
1143 |
+
q = r.normalize()
|
1144 |
+
pout = q * Quaternion(0, pin[0], pin[1], pin[2]) * conjugate(q)
|
1145 |
+
return (pout.b, pout.c, pout.d)
|
1146 |
+
|
1147 |
+
def to_axis_angle(self):
|
1148 |
+
"""Returns the axis and angle of rotation of a quaternion.
|
1149 |
+
|
1150 |
+
Returns
|
1151 |
+
=======
|
1152 |
+
|
1153 |
+
tuple
|
1154 |
+
Tuple of (axis, angle)
|
1155 |
+
|
1156 |
+
Examples
|
1157 |
+
========
|
1158 |
+
|
1159 |
+
>>> from sympy import Quaternion
|
1160 |
+
>>> q = Quaternion(1, 1, 1, 1)
|
1161 |
+
>>> (axis, angle) = q.to_axis_angle()
|
1162 |
+
>>> axis
|
1163 |
+
(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3)
|
1164 |
+
>>> angle
|
1165 |
+
2*pi/3
|
1166 |
+
|
1167 |
+
"""
|
1168 |
+
q = self
|
1169 |
+
if q.a.is_negative:
|
1170 |
+
q = q * -1
|
1171 |
+
|
1172 |
+
q = q.normalize()
|
1173 |
+
angle = trigsimp(2 * acos(q.a))
|
1174 |
+
|
1175 |
+
# Since quaternion is normalised, q.a is less than 1.
|
1176 |
+
s = sqrt(1 - q.a*q.a)
|
1177 |
+
|
1178 |
+
x = trigsimp(q.b / s)
|
1179 |
+
y = trigsimp(q.c / s)
|
1180 |
+
z = trigsimp(q.d / s)
|
1181 |
+
|
1182 |
+
v = (x, y, z)
|
1183 |
+
t = (v, angle)
|
1184 |
+
|
1185 |
+
return t
|
1186 |
+
|
1187 |
+
def to_rotation_matrix(self, v=None, homogeneous=True):
|
1188 |
+
"""Returns the equivalent rotation transformation matrix of the quaternion
|
1189 |
+
which represents rotation about the origin if ``v`` is not passed.
|
1190 |
+
|
1191 |
+
Parameters
|
1192 |
+
==========
|
1193 |
+
|
1194 |
+
v : tuple or None
|
1195 |
+
Default value: None
|
1196 |
+
homogeneous : bool
|
1197 |
+
When True, gives an expression that may be more efficient for
|
1198 |
+
symbolic calculations but less so for direct evaluation. Both
|
1199 |
+
formulas are mathematically equivalent.
|
1200 |
+
Default value: True
|
1201 |
+
|
1202 |
+
Returns
|
1203 |
+
=======
|
1204 |
+
|
1205 |
+
tuple
|
1206 |
+
Returns the equivalent rotation transformation matrix of the quaternion
|
1207 |
+
which represents rotation about the origin if v is not passed.
|
1208 |
+
|
1209 |
+
Examples
|
1210 |
+
========
|
1211 |
+
|
1212 |
+
>>> from sympy import Quaternion
|
1213 |
+
>>> from sympy import symbols, trigsimp, cos, sin
|
1214 |
+
>>> x = symbols('x')
|
1215 |
+
>>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
|
1216 |
+
>>> trigsimp(q.to_rotation_matrix())
|
1217 |
+
Matrix([
|
1218 |
+
[cos(x), -sin(x), 0],
|
1219 |
+
[sin(x), cos(x), 0],
|
1220 |
+
[ 0, 0, 1]])
|
1221 |
+
|
1222 |
+
Generates a 4x4 transformation matrix (used for rotation about a point
|
1223 |
+
other than the origin) if the point(v) is passed as an argument.
|
1224 |
+
"""
|
1225 |
+
|
1226 |
+
q = self
|
1227 |
+
s = q.norm()**-2
|
1228 |
+
|
1229 |
+
# diagonal elements are different according to parameter normal
|
1230 |
+
if homogeneous:
|
1231 |
+
m00 = s*(q.a**2 + q.b**2 - q.c**2 - q.d**2)
|
1232 |
+
m11 = s*(q.a**2 - q.b**2 + q.c**2 - q.d**2)
|
1233 |
+
m22 = s*(q.a**2 - q.b**2 - q.c**2 + q.d**2)
|
1234 |
+
else:
|
1235 |
+
m00 = 1 - 2*s*(q.c**2 + q.d**2)
|
1236 |
+
m11 = 1 - 2*s*(q.b**2 + q.d**2)
|
1237 |
+
m22 = 1 - 2*s*(q.b**2 + q.c**2)
|
1238 |
+
|
1239 |
+
m01 = 2*s*(q.b*q.c - q.d*q.a)
|
1240 |
+
m02 = 2*s*(q.b*q.d + q.c*q.a)
|
1241 |
+
|
1242 |
+
m10 = 2*s*(q.b*q.c + q.d*q.a)
|
1243 |
+
m12 = 2*s*(q.c*q.d - q.b*q.a)
|
1244 |
+
|
1245 |
+
m20 = 2*s*(q.b*q.d - q.c*q.a)
|
1246 |
+
m21 = 2*s*(q.c*q.d + q.b*q.a)
|
1247 |
+
|
1248 |
+
if not v:
|
1249 |
+
return Matrix([[m00, m01, m02], [m10, m11, m12], [m20, m21, m22]])
|
1250 |
+
|
1251 |
+
else:
|
1252 |
+
(x, y, z) = v
|
1253 |
+
|
1254 |
+
m03 = x - x*m00 - y*m01 - z*m02
|
1255 |
+
m13 = y - x*m10 - y*m11 - z*m12
|
1256 |
+
m23 = z - x*m20 - y*m21 - z*m22
|
1257 |
+
m30 = m31 = m32 = 0
|
1258 |
+
m33 = 1
|
1259 |
+
|
1260 |
+
return Matrix([[m00, m01, m02, m03], [m10, m11, m12, m13],
|
1261 |
+
[m20, m21, m22, m23], [m30, m31, m32, m33]])
|
1262 |
+
|
1263 |
+
def scalar_part(self):
|
1264 |
+
r"""Returns scalar part($\mathbf{S}(q)$) of the quaternion q.
|
1265 |
+
|
1266 |
+
Explanation
|
1267 |
+
===========
|
1268 |
+
|
1269 |
+
Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{S}(q) = a$.
|
1270 |
+
|
1271 |
+
Examples
|
1272 |
+
========
|
1273 |
+
|
1274 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1275 |
+
>>> q = Quaternion(4, 8, 13, 12)
|
1276 |
+
>>> q.scalar_part()
|
1277 |
+
4
|
1278 |
+
|
1279 |
+
"""
|
1280 |
+
|
1281 |
+
return self.a
|
1282 |
+
|
1283 |
+
def vector_part(self):
|
1284 |
+
r"""
|
1285 |
+
Returns $\mathbf{V}(q)$, the vector part of the quaternion $q$.
|
1286 |
+
|
1287 |
+
Explanation
|
1288 |
+
===========
|
1289 |
+
|
1290 |
+
Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{V}(q) = bi + cj + dk$.
|
1291 |
+
|
1292 |
+
Examples
|
1293 |
+
========
|
1294 |
+
|
1295 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1296 |
+
>>> q = Quaternion(1, 1, 1, 1)
|
1297 |
+
>>> q.vector_part()
|
1298 |
+
0 + 1*i + 1*j + 1*k
|
1299 |
+
|
1300 |
+
>>> q = Quaternion(4, 8, 13, 12)
|
1301 |
+
>>> q.vector_part()
|
1302 |
+
0 + 8*i + 13*j + 12*k
|
1303 |
+
|
1304 |
+
"""
|
1305 |
+
|
1306 |
+
return Quaternion(0, self.b, self.c, self.d)
|
1307 |
+
|
1308 |
+
def axis(self):
|
1309 |
+
r"""
|
1310 |
+
Returns $\mathbf{Ax}(q)$, the axis of the quaternion $q$.
|
1311 |
+
|
1312 |
+
Explanation
|
1313 |
+
===========
|
1314 |
+
|
1315 |
+
Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{Ax}(q)$ i.e., the versor of the vector part of that quaternion
|
1316 |
+
equal to $\mathbf{U}[\mathbf{V}(q)]$.
|
1317 |
+
The axis is always an imaginary unit with square equal to $-1 + 0i + 0j + 0k$.
|
1318 |
+
|
1319 |
+
Examples
|
1320 |
+
========
|
1321 |
+
|
1322 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1323 |
+
>>> q = Quaternion(1, 1, 1, 1)
|
1324 |
+
>>> q.axis()
|
1325 |
+
0 + sqrt(3)/3*i + sqrt(3)/3*j + sqrt(3)/3*k
|
1326 |
+
|
1327 |
+
See Also
|
1328 |
+
========
|
1329 |
+
|
1330 |
+
vector_part
|
1331 |
+
|
1332 |
+
"""
|
1333 |
+
axis = self.vector_part().normalize()
|
1334 |
+
|
1335 |
+
return Quaternion(0, axis.b, axis.c, axis.d)
|
1336 |
+
|
1337 |
+
def is_pure(self):
|
1338 |
+
"""
|
1339 |
+
Returns true if the quaternion is pure, false if the quaternion is not pure
|
1340 |
+
or returns none if it is unknown.
|
1341 |
+
|
1342 |
+
Explanation
|
1343 |
+
===========
|
1344 |
+
|
1345 |
+
A pure quaternion (also a vector quaternion) is a quaternion with scalar
|
1346 |
+
part equal to 0.
|
1347 |
+
|
1348 |
+
Examples
|
1349 |
+
========
|
1350 |
+
|
1351 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1352 |
+
>>> q = Quaternion(0, 8, 13, 12)
|
1353 |
+
>>> q.is_pure()
|
1354 |
+
True
|
1355 |
+
|
1356 |
+
See Also
|
1357 |
+
========
|
1358 |
+
scalar_part
|
1359 |
+
|
1360 |
+
"""
|
1361 |
+
|
1362 |
+
return self.a.is_zero
|
1363 |
+
|
1364 |
+
def is_zero_quaternion(self):
|
1365 |
+
"""
|
1366 |
+
Returns true if the quaternion is a zero quaternion or false if it is not a zero quaternion
|
1367 |
+
and None if the value is unknown.
|
1368 |
+
|
1369 |
+
Explanation
|
1370 |
+
===========
|
1371 |
+
|
1372 |
+
A zero quaternion is a quaternion with both scalar part and
|
1373 |
+
vector part equal to 0.
|
1374 |
+
|
1375 |
+
Examples
|
1376 |
+
========
|
1377 |
+
|
1378 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1379 |
+
>>> q = Quaternion(1, 0, 0, 0)
|
1380 |
+
>>> q.is_zero_quaternion()
|
1381 |
+
False
|
1382 |
+
|
1383 |
+
>>> q = Quaternion(0, 0, 0, 0)
|
1384 |
+
>>> q.is_zero_quaternion()
|
1385 |
+
True
|
1386 |
+
|
1387 |
+
See Also
|
1388 |
+
========
|
1389 |
+
scalar_part
|
1390 |
+
vector_part
|
1391 |
+
|
1392 |
+
"""
|
1393 |
+
|
1394 |
+
return self.norm().is_zero
|
1395 |
+
|
1396 |
+
def angle(self):
|
1397 |
+
r"""
|
1398 |
+
Returns the angle of the quaternion measured in the real-axis plane.
|
1399 |
+
|
1400 |
+
Explanation
|
1401 |
+
===========
|
1402 |
+
|
1403 |
+
Given a quaternion $q = a + bi + cj + dk$ where $a$, $b$, $c$ and $d$
|
1404 |
+
are real numbers, returns the angle of the quaternion given by
|
1405 |
+
|
1406 |
+
.. math::
|
1407 |
+
\theta := 2 \operatorname{atan_2}\left(\sqrt{b^2 + c^2 + d^2}, {a}\right)
|
1408 |
+
|
1409 |
+
Examples
|
1410 |
+
========
|
1411 |
+
|
1412 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1413 |
+
>>> q = Quaternion(1, 4, 4, 4)
|
1414 |
+
>>> q.angle()
|
1415 |
+
2*atan(4*sqrt(3))
|
1416 |
+
|
1417 |
+
"""
|
1418 |
+
|
1419 |
+
return 2 * atan2(self.vector_part().norm(), self.scalar_part())
|
1420 |
+
|
1421 |
+
|
1422 |
+
def arc_coplanar(self, other):
|
1423 |
+
"""
|
1424 |
+
Returns True if the transformation arcs represented by the input quaternions happen in the same plane.
|
1425 |
+
|
1426 |
+
Explanation
|
1427 |
+
===========
|
1428 |
+
|
1429 |
+
Two quaternions are said to be coplanar (in this arc sense) when their axes are parallel.
|
1430 |
+
The plane of a quaternion is the one normal to its axis.
|
1431 |
+
|
1432 |
+
Parameters
|
1433 |
+
==========
|
1434 |
+
|
1435 |
+
other : a Quaternion
|
1436 |
+
|
1437 |
+
Returns
|
1438 |
+
=======
|
1439 |
+
|
1440 |
+
True : if the planes of the two quaternions are the same, apart from its orientation/sign.
|
1441 |
+
False : if the planes of the two quaternions are not the same, apart from its orientation/sign.
|
1442 |
+
None : if plane of either of the quaternion is unknown.
|
1443 |
+
|
1444 |
+
Examples
|
1445 |
+
========
|
1446 |
+
|
1447 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1448 |
+
>>> q1 = Quaternion(1, 4, 4, 4)
|
1449 |
+
>>> q2 = Quaternion(3, 8, 8, 8)
|
1450 |
+
>>> Quaternion.arc_coplanar(q1, q2)
|
1451 |
+
True
|
1452 |
+
|
1453 |
+
>>> q1 = Quaternion(2, 8, 13, 12)
|
1454 |
+
>>> Quaternion.arc_coplanar(q1, q2)
|
1455 |
+
False
|
1456 |
+
|
1457 |
+
See Also
|
1458 |
+
========
|
1459 |
+
|
1460 |
+
vector_coplanar
|
1461 |
+
is_pure
|
1462 |
+
|
1463 |
+
"""
|
1464 |
+
if (self.is_zero_quaternion()) or (other.is_zero_quaternion()):
|
1465 |
+
raise ValueError('Neither of the given quaternions can be 0')
|
1466 |
+
|
1467 |
+
return fuzzy_or([(self.axis() - other.axis()).is_zero_quaternion(), (self.axis() + other.axis()).is_zero_quaternion()])
|
1468 |
+
|
1469 |
+
@classmethod
|
1470 |
+
def vector_coplanar(cls, q1, q2, q3):
|
1471 |
+
r"""
|
1472 |
+
Returns True if the axis of the pure quaternions seen as 3D vectors
|
1473 |
+
``q1``, ``q2``, and ``q3`` are coplanar.
|
1474 |
+
|
1475 |
+
Explanation
|
1476 |
+
===========
|
1477 |
+
|
1478 |
+
Three pure quaternions are vector coplanar if the quaternions seen as 3D vectors are coplanar.
|
1479 |
+
|
1480 |
+
Parameters
|
1481 |
+
==========
|
1482 |
+
|
1483 |
+
q1
|
1484 |
+
A pure Quaternion.
|
1485 |
+
q2
|
1486 |
+
A pure Quaternion.
|
1487 |
+
q3
|
1488 |
+
A pure Quaternion.
|
1489 |
+
|
1490 |
+
Returns
|
1491 |
+
=======
|
1492 |
+
|
1493 |
+
True : if the axis of the pure quaternions seen as 3D vectors
|
1494 |
+
q1, q2, and q3 are coplanar.
|
1495 |
+
False : if the axis of the pure quaternions seen as 3D vectors
|
1496 |
+
q1, q2, and q3 are not coplanar.
|
1497 |
+
None : if the axis of the pure quaternions seen as 3D vectors
|
1498 |
+
q1, q2, and q3 are coplanar is unknown.
|
1499 |
+
|
1500 |
+
Examples
|
1501 |
+
========
|
1502 |
+
|
1503 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1504 |
+
>>> q1 = Quaternion(0, 4, 4, 4)
|
1505 |
+
>>> q2 = Quaternion(0, 8, 8, 8)
|
1506 |
+
>>> q3 = Quaternion(0, 24, 24, 24)
|
1507 |
+
>>> Quaternion.vector_coplanar(q1, q2, q3)
|
1508 |
+
True
|
1509 |
+
|
1510 |
+
>>> q1 = Quaternion(0, 8, 16, 8)
|
1511 |
+
>>> q2 = Quaternion(0, 8, 3, 12)
|
1512 |
+
>>> Quaternion.vector_coplanar(q1, q2, q3)
|
1513 |
+
False
|
1514 |
+
|
1515 |
+
See Also
|
1516 |
+
========
|
1517 |
+
|
1518 |
+
axis
|
1519 |
+
is_pure
|
1520 |
+
|
1521 |
+
"""
|
1522 |
+
|
1523 |
+
if fuzzy_not(q1.is_pure()) or fuzzy_not(q2.is_pure()) or fuzzy_not(q3.is_pure()):
|
1524 |
+
raise ValueError('The given quaternions must be pure')
|
1525 |
+
|
1526 |
+
M = Matrix([[q1.b, q1.c, q1.d], [q2.b, q2.c, q2.d], [q3.b, q3.c, q3.d]]).det()
|
1527 |
+
return M.is_zero
|
1528 |
+
|
1529 |
+
def parallel(self, other):
|
1530 |
+
"""
|
1531 |
+
Returns True if the two pure quaternions seen as 3D vectors are parallel.
|
1532 |
+
|
1533 |
+
Explanation
|
1534 |
+
===========
|
1535 |
+
|
1536 |
+
Two pure quaternions are called parallel when their vector product is commutative which
|
1537 |
+
implies that the quaternions seen as 3D vectors have same direction.
|
1538 |
+
|
1539 |
+
Parameters
|
1540 |
+
==========
|
1541 |
+
|
1542 |
+
other : a Quaternion
|
1543 |
+
|
1544 |
+
Returns
|
1545 |
+
=======
|
1546 |
+
|
1547 |
+
True : if the two pure quaternions seen as 3D vectors are parallel.
|
1548 |
+
False : if the two pure quaternions seen as 3D vectors are not parallel.
|
1549 |
+
None : if the two pure quaternions seen as 3D vectors are parallel is unknown.
|
1550 |
+
|
1551 |
+
Examples
|
1552 |
+
========
|
1553 |
+
|
1554 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1555 |
+
>>> q = Quaternion(0, 4, 4, 4)
|
1556 |
+
>>> q1 = Quaternion(0, 8, 8, 8)
|
1557 |
+
>>> q.parallel(q1)
|
1558 |
+
True
|
1559 |
+
|
1560 |
+
>>> q1 = Quaternion(0, 8, 13, 12)
|
1561 |
+
>>> q.parallel(q1)
|
1562 |
+
False
|
1563 |
+
|
1564 |
+
"""
|
1565 |
+
|
1566 |
+
if fuzzy_not(self.is_pure()) or fuzzy_not(other.is_pure()):
|
1567 |
+
raise ValueError('The provided quaternions must be pure')
|
1568 |
+
|
1569 |
+
return (self*other - other*self).is_zero_quaternion()
|
1570 |
+
|
1571 |
+
def orthogonal(self, other):
|
1572 |
+
"""
|
1573 |
+
Returns the orthogonality of two quaternions.
|
1574 |
+
|
1575 |
+
Explanation
|
1576 |
+
===========
|
1577 |
+
|
1578 |
+
Two pure quaternions are called orthogonal when their product is anti-commutative.
|
1579 |
+
|
1580 |
+
Parameters
|
1581 |
+
==========
|
1582 |
+
|
1583 |
+
other : a Quaternion
|
1584 |
+
|
1585 |
+
Returns
|
1586 |
+
=======
|
1587 |
+
|
1588 |
+
True : if the two pure quaternions seen as 3D vectors are orthogonal.
|
1589 |
+
False : if the two pure quaternions seen as 3D vectors are not orthogonal.
|
1590 |
+
None : if the two pure quaternions seen as 3D vectors are orthogonal is unknown.
|
1591 |
+
|
1592 |
+
Examples
|
1593 |
+
========
|
1594 |
+
|
1595 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1596 |
+
>>> q = Quaternion(0, 4, 4, 4)
|
1597 |
+
>>> q1 = Quaternion(0, 8, 8, 8)
|
1598 |
+
>>> q.orthogonal(q1)
|
1599 |
+
False
|
1600 |
+
|
1601 |
+
>>> q1 = Quaternion(0, 2, 2, 0)
|
1602 |
+
>>> q = Quaternion(0, 2, -2, 0)
|
1603 |
+
>>> q.orthogonal(q1)
|
1604 |
+
True
|
1605 |
+
|
1606 |
+
"""
|
1607 |
+
|
1608 |
+
if fuzzy_not(self.is_pure()) or fuzzy_not(other.is_pure()):
|
1609 |
+
raise ValueError('The given quaternions must be pure')
|
1610 |
+
|
1611 |
+
return (self*other + other*self).is_zero_quaternion()
|
1612 |
+
|
1613 |
+
def index_vector(self):
|
1614 |
+
r"""
|
1615 |
+
Returns the index vector of the quaternion.
|
1616 |
+
|
1617 |
+
Explanation
|
1618 |
+
===========
|
1619 |
+
|
1620 |
+
The index vector is given by $\mathbf{T}(q)$, the norm (or magnitude) of
|
1621 |
+
the quaternion $q$, multiplied by $\mathbf{Ax}(q)$, the axis of $q$.
|
1622 |
+
|
1623 |
+
Returns
|
1624 |
+
=======
|
1625 |
+
|
1626 |
+
Quaternion: representing index vector of the provided quaternion.
|
1627 |
+
|
1628 |
+
Examples
|
1629 |
+
========
|
1630 |
+
|
1631 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1632 |
+
>>> q = Quaternion(2, 4, 2, 4)
|
1633 |
+
>>> q.index_vector()
|
1634 |
+
0 + 4*sqrt(10)/3*i + 2*sqrt(10)/3*j + 4*sqrt(10)/3*k
|
1635 |
+
|
1636 |
+
See Also
|
1637 |
+
========
|
1638 |
+
|
1639 |
+
axis
|
1640 |
+
norm
|
1641 |
+
|
1642 |
+
"""
|
1643 |
+
|
1644 |
+
return self.norm() * self.axis()
|
1645 |
+
|
1646 |
+
def mensor(self):
|
1647 |
+
"""
|
1648 |
+
Returns the natural logarithm of the norm(magnitude) of the quaternion.
|
1649 |
+
|
1650 |
+
Examples
|
1651 |
+
========
|
1652 |
+
|
1653 |
+
>>> from sympy.algebras.quaternion import Quaternion
|
1654 |
+
>>> q = Quaternion(2, 4, 2, 4)
|
1655 |
+
>>> q.mensor()
|
1656 |
+
log(2*sqrt(10))
|
1657 |
+
>>> q.norm()
|
1658 |
+
2*sqrt(10)
|
1659 |
+
|
1660 |
+
See Also
|
1661 |
+
========
|
1662 |
+
|
1663 |
+
norm
|
1664 |
+
|
1665 |
+
"""
|
1666 |
+
|
1667 |
+
return ln(self.norm())
|
MLPY/Lib/site-packages/sympy/algebras/tests/__init__.py
ADDED
File without changes
|
MLPY/Lib/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (157 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-39.pyc
ADDED
Binary file (16 kB). View file
|
|
MLPY/Lib/site-packages/sympy/algebras/tests/test_quaternion.py
ADDED
@@ -0,0 +1,428 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sympy.testing.pytest import slow
|
2 |
+
from sympy.core.function import diff
|
3 |
+
from sympy.core.function import expand
|
4 |
+
from sympy.core.numbers import (E, I, Rational, pi)
|
5 |
+
from sympy.core.singleton import S
|
6 |
+
from sympy.core.symbol import (Symbol, symbols)
|
7 |
+
from sympy.functions.elementary.complexes import (Abs, conjugate, im, re, sign)
|
8 |
+
from sympy.functions.elementary.exponential import log
|
9 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
10 |
+
from sympy.functions.elementary.trigonometric import (acos, asin, cos, sin, atan2, atan)
|
11 |
+
from sympy.integrals.integrals import integrate
|
12 |
+
from sympy.matrices.dense import Matrix
|
13 |
+
from sympy.simplify import simplify
|
14 |
+
from sympy.simplify.trigsimp import trigsimp
|
15 |
+
from sympy.algebras.quaternion import Quaternion
|
16 |
+
from sympy.testing.pytest import raises
|
17 |
+
import math
|
18 |
+
from itertools import permutations, product
|
19 |
+
|
20 |
+
w, x, y, z = symbols('w:z')
|
21 |
+
phi = symbols('phi')
|
22 |
+
|
23 |
+
def test_quaternion_construction():
|
24 |
+
q = Quaternion(w, x, y, z)
|
25 |
+
assert q + q == Quaternion(2*w, 2*x, 2*y, 2*z)
|
26 |
+
|
27 |
+
q2 = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3),
|
28 |
+
pi*Rational(2, 3))
|
29 |
+
assert q2 == Quaternion(S.Half, S.Half,
|
30 |
+
S.Half, S.Half)
|
31 |
+
|
32 |
+
M = Matrix([[cos(phi), -sin(phi), 0], [sin(phi), cos(phi), 0], [0, 0, 1]])
|
33 |
+
q3 = trigsimp(Quaternion.from_rotation_matrix(M))
|
34 |
+
assert q3 == Quaternion(
|
35 |
+
sqrt(2)*sqrt(cos(phi) + 1)/2, 0, 0, sqrt(2 - 2*cos(phi))*sign(sin(phi))/2)
|
36 |
+
|
37 |
+
nc = Symbol('nc', commutative=False)
|
38 |
+
raises(ValueError, lambda: Quaternion(w, x, nc, z))
|
39 |
+
|
40 |
+
|
41 |
+
def test_quaternion_construction_norm():
|
42 |
+
q1 = Quaternion(*symbols('a:d'))
|
43 |
+
|
44 |
+
q2 = Quaternion(w, x, y, z)
|
45 |
+
assert expand((q1*q2).norm()**2 - (q1.norm()**2 * q2.norm()**2)) == 0
|
46 |
+
|
47 |
+
q3 = Quaternion(w, x, y, z, norm=1)
|
48 |
+
assert (q1 * q3).norm() == q1.norm()
|
49 |
+
|
50 |
+
|
51 |
+
def test_issue_25254():
|
52 |
+
# calculating the inverse cached the norm which caused problems
|
53 |
+
# when multiplying
|
54 |
+
p = Quaternion(1, 0, 0, 0)
|
55 |
+
q = Quaternion.from_axis_angle((1, 1, 1), 3 * math.pi/4)
|
56 |
+
qi = q.inverse() # this operation cached the norm
|
57 |
+
test = q * p * qi
|
58 |
+
assert ((test - p).norm() < 1E-10)
|
59 |
+
|
60 |
+
|
61 |
+
def test_to_and_from_Matrix():
|
62 |
+
q = Quaternion(w, x, y, z)
|
63 |
+
q_full = Quaternion.from_Matrix(q.to_Matrix())
|
64 |
+
q_vect = Quaternion.from_Matrix(q.to_Matrix(True))
|
65 |
+
assert (q - q_full).is_zero_quaternion()
|
66 |
+
assert (q.vector_part() - q_vect).is_zero_quaternion()
|
67 |
+
|
68 |
+
|
69 |
+
def test_product_matrices():
|
70 |
+
q1 = Quaternion(w, x, y, z)
|
71 |
+
q2 = Quaternion(*(symbols("a:d")))
|
72 |
+
assert (q1 * q2).to_Matrix() == q1.product_matrix_left * q2.to_Matrix()
|
73 |
+
assert (q1 * q2).to_Matrix() == q2.product_matrix_right * q1.to_Matrix()
|
74 |
+
|
75 |
+
R1 = (q1.product_matrix_left * q1.product_matrix_right.T)[1:, 1:]
|
76 |
+
R2 = simplify(q1.to_rotation_matrix()*q1.norm()**2)
|
77 |
+
assert R1 == R2
|
78 |
+
|
79 |
+
|
80 |
+
def test_quaternion_axis_angle():
|
81 |
+
|
82 |
+
test_data = [ # axis, angle, expected_quaternion
|
83 |
+
((1, 0, 0), 0, (1, 0, 0, 0)),
|
84 |
+
((1, 0, 0), pi/2, (sqrt(2)/2, sqrt(2)/2, 0, 0)),
|
85 |
+
((0, 1, 0), pi/2, (sqrt(2)/2, 0, sqrt(2)/2, 0)),
|
86 |
+
((0, 0, 1), pi/2, (sqrt(2)/2, 0, 0, sqrt(2)/2)),
|
87 |
+
((1, 0, 0), pi, (0, 1, 0, 0)),
|
88 |
+
((0, 1, 0), pi, (0, 0, 1, 0)),
|
89 |
+
((0, 0, 1), pi, (0, 0, 0, 1)),
|
90 |
+
((1, 1, 1), pi, (0, 1/sqrt(3),1/sqrt(3),1/sqrt(3))),
|
91 |
+
((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), pi*2/3, (S.Half, S.Half, S.Half, S.Half))
|
92 |
+
]
|
93 |
+
|
94 |
+
for axis, angle, expected in test_data:
|
95 |
+
assert Quaternion.from_axis_angle(axis, angle) == Quaternion(*expected)
|
96 |
+
|
97 |
+
|
98 |
+
def test_quaternion_axis_angle_simplification():
|
99 |
+
result = Quaternion.from_axis_angle((1, 2, 3), asin(4))
|
100 |
+
assert result.a == cos(asin(4)/2)
|
101 |
+
assert result.b == sqrt(14)*sin(asin(4)/2)/14
|
102 |
+
assert result.c == sqrt(14)*sin(asin(4)/2)/7
|
103 |
+
assert result.d == 3*sqrt(14)*sin(asin(4)/2)/14
|
104 |
+
|
105 |
+
def test_quaternion_complex_real_addition():
|
106 |
+
a = symbols("a", complex=True)
|
107 |
+
b = symbols("b", real=True)
|
108 |
+
# This symbol is not complex:
|
109 |
+
c = symbols("c", commutative=False)
|
110 |
+
|
111 |
+
q = Quaternion(w, x, y, z)
|
112 |
+
assert a + q == Quaternion(w + re(a), x + im(a), y, z)
|
113 |
+
assert 1 + q == Quaternion(1 + w, x, y, z)
|
114 |
+
assert I + q == Quaternion(w, 1 + x, y, z)
|
115 |
+
assert b + q == Quaternion(w + b, x, y, z)
|
116 |
+
raises(ValueError, lambda: c + q)
|
117 |
+
raises(ValueError, lambda: q * c)
|
118 |
+
raises(ValueError, lambda: c * q)
|
119 |
+
|
120 |
+
assert -q == Quaternion(-w, -x, -y, -z)
|
121 |
+
|
122 |
+
q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
123 |
+
q2 = Quaternion(1, 4, 7, 8)
|
124 |
+
|
125 |
+
assert q1 + (2 + 3*I) == Quaternion(5 + 7*I, 2 + 5*I, 0, 7 + 8*I)
|
126 |
+
assert q2 + (2 + 3*I) == Quaternion(3, 7, 7, 8)
|
127 |
+
assert q1 * (2 + 3*I) == \
|
128 |
+
Quaternion((2 + 3*I)*(3 + 4*I), (2 + 3*I)*(2 + 5*I), 0, (2 + 3*I)*(7 + 8*I))
|
129 |
+
assert q2 * (2 + 3*I) == Quaternion(-10, 11, 38, -5)
|
130 |
+
|
131 |
+
q1 = Quaternion(1, 2, 3, 4)
|
132 |
+
q0 = Quaternion(0, 0, 0, 0)
|
133 |
+
assert q1 + q0 == q1
|
134 |
+
assert q1 - q0 == q1
|
135 |
+
assert q1 - q1 == q0
|
136 |
+
|
137 |
+
|
138 |
+
def test_quaternion_subs():
|
139 |
+
q = Quaternion.from_axis_angle((0, 0, 1), phi)
|
140 |
+
assert q.subs(phi, 0) == Quaternion(1, 0, 0, 0)
|
141 |
+
|
142 |
+
|
143 |
+
def test_quaternion_evalf():
|
144 |
+
assert (Quaternion(sqrt(2), 0, 0, sqrt(3)).evalf() ==
|
145 |
+
Quaternion(sqrt(2).evalf(), 0, 0, sqrt(3).evalf()))
|
146 |
+
assert (Quaternion(1/sqrt(2), 0, 0, 1/sqrt(2)).evalf() ==
|
147 |
+
Quaternion((1/sqrt(2)).evalf(), 0, 0, (1/sqrt(2)).evalf()))
|
148 |
+
|
149 |
+
|
150 |
+
def test_quaternion_functions():
|
151 |
+
q = Quaternion(w, x, y, z)
|
152 |
+
q1 = Quaternion(1, 2, 3, 4)
|
153 |
+
q0 = Quaternion(0, 0, 0, 0)
|
154 |
+
|
155 |
+
assert conjugate(q) == Quaternion(w, -x, -y, -z)
|
156 |
+
assert q.norm() == sqrt(w**2 + x**2 + y**2 + z**2)
|
157 |
+
assert q.normalize() == Quaternion(w, x, y, z) / sqrt(w**2 + x**2 + y**2 + z**2)
|
158 |
+
assert q.inverse() == Quaternion(w, -x, -y, -z) / (w**2 + x**2 + y**2 + z**2)
|
159 |
+
assert q.inverse() == q.pow(-1)
|
160 |
+
raises(ValueError, lambda: q0.inverse())
|
161 |
+
assert q.pow(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z)
|
162 |
+
assert q**(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z)
|
163 |
+
assert q1.pow(-2) == Quaternion(
|
164 |
+
Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225))
|
165 |
+
assert q1**(-2) == Quaternion(
|
166 |
+
Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225))
|
167 |
+
assert q1.pow(-0.5) == NotImplemented
|
168 |
+
raises(TypeError, lambda: q1**(-0.5))
|
169 |
+
|
170 |
+
assert q1.exp() == \
|
171 |
+
Quaternion(E * cos(sqrt(29)),
|
172 |
+
2 * sqrt(29) * E * sin(sqrt(29)) / 29,
|
173 |
+
3 * sqrt(29) * E * sin(sqrt(29)) / 29,
|
174 |
+
4 * sqrt(29) * E * sin(sqrt(29)) / 29)
|
175 |
+
assert q1.log() == \
|
176 |
+
Quaternion(log(sqrt(30)),
|
177 |
+
2 * sqrt(29) * acos(sqrt(30)/30) / 29,
|
178 |
+
3 * sqrt(29) * acos(sqrt(30)/30) / 29,
|
179 |
+
4 * sqrt(29) * acos(sqrt(30)/30) / 29)
|
180 |
+
|
181 |
+
assert q1.pow_cos_sin(2) == \
|
182 |
+
Quaternion(30 * cos(2 * acos(sqrt(30)/30)),
|
183 |
+
60 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29,
|
184 |
+
90 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29,
|
185 |
+
120 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29)
|
186 |
+
|
187 |
+
assert diff(Quaternion(x, x, x, x), x) == Quaternion(1, 1, 1, 1)
|
188 |
+
|
189 |
+
assert integrate(Quaternion(x, x, x, x), x) == \
|
190 |
+
Quaternion(x**2 / 2, x**2 / 2, x**2 / 2, x**2 / 2)
|
191 |
+
|
192 |
+
assert Quaternion.rotate_point((1, 1, 1), q1) == (S.One / 5, 1, S(7) / 5)
|
193 |
+
n = Symbol('n')
|
194 |
+
raises(TypeError, lambda: q1**n)
|
195 |
+
n = Symbol('n', integer=True)
|
196 |
+
raises(TypeError, lambda: q1**n)
|
197 |
+
|
198 |
+
assert Quaternion(22, 23, 55, 8).scalar_part() == 22
|
199 |
+
assert Quaternion(w, x, y, z).scalar_part() == w
|
200 |
+
|
201 |
+
assert Quaternion(22, 23, 55, 8).vector_part() == Quaternion(0, 23, 55, 8)
|
202 |
+
assert Quaternion(w, x, y, z).vector_part() == Quaternion(0, x, y, z)
|
203 |
+
|
204 |
+
assert q1.axis() == Quaternion(0, 2*sqrt(29)/29, 3*sqrt(29)/29, 4*sqrt(29)/29)
|
205 |
+
assert q1.axis().pow(2) == Quaternion(-1, 0, 0, 0)
|
206 |
+
assert q0.axis().scalar_part() == 0
|
207 |
+
assert (q.axis() == Quaternion(0,
|
208 |
+
x/sqrt(x**2 + y**2 + z**2),
|
209 |
+
y/sqrt(x**2 + y**2 + z**2),
|
210 |
+
z/sqrt(x**2 + y**2 + z**2)))
|
211 |
+
|
212 |
+
assert q0.is_pure() is True
|
213 |
+
assert q1.is_pure() is False
|
214 |
+
assert Quaternion(0, 0, 0, 3).is_pure() is True
|
215 |
+
assert Quaternion(0, 2, 10, 3).is_pure() is True
|
216 |
+
assert Quaternion(w, 2, 10, 3).is_pure() is None
|
217 |
+
|
218 |
+
assert q1.angle() == 2*atan(sqrt(29))
|
219 |
+
assert q.angle() == 2*atan2(sqrt(x**2 + y**2 + z**2), w)
|
220 |
+
|
221 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(2, 4, 6, 8)) is True
|
222 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, -2, -3, -4)) is True
|
223 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, 8, 12, 16)) is True
|
224 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, 2, 3, 4)) is True
|
225 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(w, 4, 6, 8)) is True
|
226 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(2, 7, 4, 1)) is False
|
227 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(w, x, y, z)) is None
|
228 |
+
raises(ValueError, lambda: Quaternion.arc_coplanar(q1, q0))
|
229 |
+
|
230 |
+
assert Quaternion.vector_coplanar(
|
231 |
+
Quaternion(0, 8, 12, 16),
|
232 |
+
Quaternion(0, 4, 6, 8),
|
233 |
+
Quaternion(0, 2, 3, 4)) is True
|
234 |
+
assert Quaternion.vector_coplanar(
|
235 |
+
Quaternion(0, 0, 0, 0), Quaternion(0, 4, 6, 8), Quaternion(0, 2, 3, 4)) is True
|
236 |
+
assert Quaternion.vector_coplanar(
|
237 |
+
Quaternion(0, 8, 2, 6), Quaternion(0, 1, 6, 6), Quaternion(0, 0, 3, 4)) is False
|
238 |
+
assert Quaternion.vector_coplanar(
|
239 |
+
Quaternion(0, 1, 3, 4),
|
240 |
+
Quaternion(0, 4, w, 6),
|
241 |
+
Quaternion(0, 6, 8, 1)) is None
|
242 |
+
raises(ValueError, lambda:
|
243 |
+
Quaternion.vector_coplanar(q0, Quaternion(0, 4, 6, 8), q1))
|
244 |
+
|
245 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 4, 6)) is True
|
246 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 2, 6)) is False
|
247 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(w, x, y, 6)) is None
|
248 |
+
raises(ValueError, lambda: q0.parallel(q1))
|
249 |
+
|
250 |
+
assert Quaternion(0, 1, 2, 3).orthogonal(Quaternion(0, -2, 1, 0)) is True
|
251 |
+
assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(0, 2, 2, 6)) is False
|
252 |
+
assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(w, x, y, 6)) is None
|
253 |
+
raises(ValueError, lambda: q0.orthogonal(q1))
|
254 |
+
|
255 |
+
assert q1.index_vector() == Quaternion(
|
256 |
+
0, 2*sqrt(870)/29,
|
257 |
+
3*sqrt(870)/29,
|
258 |
+
4*sqrt(870)/29)
|
259 |
+
assert Quaternion(0, 3, 9, 4).index_vector() == Quaternion(0, 3, 9, 4)
|
260 |
+
|
261 |
+
assert Quaternion(4, 3, 9, 4).mensor() == log(sqrt(122))
|
262 |
+
assert Quaternion(3, 3, 0, 2).mensor() == log(sqrt(22))
|
263 |
+
|
264 |
+
assert q0.is_zero_quaternion() is True
|
265 |
+
assert q1.is_zero_quaternion() is False
|
266 |
+
assert Quaternion(w, 0, 0, 0).is_zero_quaternion() is None
|
267 |
+
|
268 |
+
def test_quaternion_conversions():
|
269 |
+
q1 = Quaternion(1, 2, 3, 4)
|
270 |
+
|
271 |
+
assert q1.to_axis_angle() == ((2 * sqrt(29)/29,
|
272 |
+
3 * sqrt(29)/29,
|
273 |
+
4 * sqrt(29)/29),
|
274 |
+
2 * acos(sqrt(30)/30))
|
275 |
+
|
276 |
+
assert (q1.to_rotation_matrix() ==
|
277 |
+
Matrix([[Rational(-2, 3), Rational(2, 15), Rational(11, 15)],
|
278 |
+
[Rational(2, 3), Rational(-1, 3), Rational(2, 3)],
|
279 |
+
[Rational(1, 3), Rational(14, 15), Rational(2, 15)]]))
|
280 |
+
|
281 |
+
assert (q1.to_rotation_matrix((1, 1, 1)) ==
|
282 |
+
Matrix([
|
283 |
+
[Rational(-2, 3), Rational(2, 15), Rational(11, 15), Rational(4, 5)],
|
284 |
+
[Rational(2, 3), Rational(-1, 3), Rational(2, 3), S.Zero],
|
285 |
+
[Rational(1, 3), Rational(14, 15), Rational(2, 15), Rational(-2, 5)],
|
286 |
+
[S.Zero, S.Zero, S.Zero, S.One]]))
|
287 |
+
|
288 |
+
theta = symbols("theta", real=True)
|
289 |
+
q2 = Quaternion(cos(theta/2), 0, 0, sin(theta/2))
|
290 |
+
|
291 |
+
assert trigsimp(q2.to_rotation_matrix()) == Matrix([
|
292 |
+
[cos(theta), -sin(theta), 0],
|
293 |
+
[sin(theta), cos(theta), 0],
|
294 |
+
[0, 0, 1]])
|
295 |
+
|
296 |
+
assert q2.to_axis_angle() == ((0, 0, sin(theta/2)/Abs(sin(theta/2))),
|
297 |
+
2*acos(cos(theta/2)))
|
298 |
+
|
299 |
+
assert trigsimp(q2.to_rotation_matrix((1, 1, 1))) == Matrix([
|
300 |
+
[cos(theta), -sin(theta), 0, sin(theta) - cos(theta) + 1],
|
301 |
+
[sin(theta), cos(theta), 0, -sin(theta) - cos(theta) + 1],
|
302 |
+
[0, 0, 1, 0],
|
303 |
+
[0, 0, 0, 1]])
|
304 |
+
|
305 |
+
|
306 |
+
def test_rotation_matrix_homogeneous():
|
307 |
+
q = Quaternion(w, x, y, z)
|
308 |
+
R1 = q.to_rotation_matrix(homogeneous=True) * q.norm()**2
|
309 |
+
R2 = simplify(q.to_rotation_matrix(homogeneous=False) * q.norm()**2)
|
310 |
+
assert R1 == R2
|
311 |
+
|
312 |
+
|
313 |
+
def test_quaternion_rotation_iss1593():
|
314 |
+
"""
|
315 |
+
There was a sign mistake in the definition,
|
316 |
+
of the rotation matrix. This tests that particular sign mistake.
|
317 |
+
See issue 1593 for reference.
|
318 |
+
See wikipedia
|
319 |
+
https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix
|
320 |
+
for the correct definition
|
321 |
+
"""
|
322 |
+
q = Quaternion(cos(phi/2), sin(phi/2), 0, 0)
|
323 |
+
assert(trigsimp(q.to_rotation_matrix()) == Matrix([
|
324 |
+
[1, 0, 0],
|
325 |
+
[0, cos(phi), -sin(phi)],
|
326 |
+
[0, sin(phi), cos(phi)]]))
|
327 |
+
|
328 |
+
|
329 |
+
def test_quaternion_multiplication():
|
330 |
+
q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
331 |
+
q2 = Quaternion(1, 2, 3, 5)
|
332 |
+
q3 = Quaternion(1, 1, 1, y)
|
333 |
+
|
334 |
+
assert Quaternion._generic_mul(S(4), S.One) == 4
|
335 |
+
assert (Quaternion._generic_mul(S(4), q1) ==
|
336 |
+
Quaternion(12 + 16*I, 8 + 20*I, 0, 28 + 32*I))
|
337 |
+
assert q2.mul(2) == Quaternion(2, 4, 6, 10)
|
338 |
+
assert q2.mul(q3) == Quaternion(-5*y - 4, 3*y - 2, 9 - 2*y, y + 4)
|
339 |
+
assert q2.mul(q3) == q2*q3
|
340 |
+
|
341 |
+
z = symbols('z', complex=True)
|
342 |
+
z_quat = Quaternion(re(z), im(z), 0, 0)
|
343 |
+
q = Quaternion(*symbols('q:4', real=True))
|
344 |
+
|
345 |
+
assert z * q == z_quat * q
|
346 |
+
assert q * z == q * z_quat
|
347 |
+
|
348 |
+
|
349 |
+
def test_issue_16318():
|
350 |
+
#for rtruediv
|
351 |
+
q0 = Quaternion(0, 0, 0, 0)
|
352 |
+
raises(ValueError, lambda: 1/q0)
|
353 |
+
#for rotate_point
|
354 |
+
q = Quaternion(1, 2, 3, 4)
|
355 |
+
(axis, angle) = q.to_axis_angle()
|
356 |
+
assert Quaternion.rotate_point((1, 1, 1), (axis, angle)) == (S.One / 5, 1, S(7) / 5)
|
357 |
+
#test for to_axis_angle
|
358 |
+
q = Quaternion(-1, 1, 1, 1)
|
359 |
+
axis = (-sqrt(3)/3, -sqrt(3)/3, -sqrt(3)/3)
|
360 |
+
angle = 2*pi/3
|
361 |
+
assert (axis, angle) == q.to_axis_angle()
|
362 |
+
|
363 |
+
|
364 |
+
@slow
|
365 |
+
def test_to_euler():
|
366 |
+
q = Quaternion(w, x, y, z)
|
367 |
+
q_normalized = q.normalize()
|
368 |
+
|
369 |
+
seqs = ['zxy', 'zyx', 'zyz', 'zxz']
|
370 |
+
seqs += [seq.upper() for seq in seqs]
|
371 |
+
|
372 |
+
for seq in seqs:
|
373 |
+
euler_from_q = q.to_euler(seq)
|
374 |
+
q_back = simplify(Quaternion.from_euler(euler_from_q, seq))
|
375 |
+
assert q_back == q_normalized
|
376 |
+
|
377 |
+
|
378 |
+
def test_to_euler_iss24504():
|
379 |
+
"""
|
380 |
+
There was a mistake in the degenerate case testing
|
381 |
+
See issue 24504 for reference.
|
382 |
+
"""
|
383 |
+
q = Quaternion.from_euler((phi, 0, 0), 'zyz')
|
384 |
+
assert trigsimp(q.to_euler('zyz'), inverse=True) == (phi, 0, 0)
|
385 |
+
|
386 |
+
|
387 |
+
def test_to_euler_numerical_singilarities():
|
388 |
+
|
389 |
+
def test_one_case(angles, seq):
|
390 |
+
q = Quaternion.from_euler(angles, seq)
|
391 |
+
assert q.to_euler(seq) == angles
|
392 |
+
|
393 |
+
# symmetric
|
394 |
+
test_one_case((pi/2, 0, 0), 'zyz')
|
395 |
+
test_one_case((pi/2, 0, 0), 'ZYZ')
|
396 |
+
test_one_case((pi/2, pi, 0), 'zyz')
|
397 |
+
test_one_case((pi/2, pi, 0), 'ZYZ')
|
398 |
+
|
399 |
+
# asymmetric
|
400 |
+
test_one_case((pi/2, pi/2, 0), 'zyx')
|
401 |
+
test_one_case((pi/2, -pi/2, 0), 'zyx')
|
402 |
+
test_one_case((pi/2, pi/2, 0), 'ZYX')
|
403 |
+
test_one_case((pi/2, -pi/2, 0), 'ZYX')
|
404 |
+
|
405 |
+
|
406 |
+
@slow
|
407 |
+
def test_to_euler_options():
|
408 |
+
def test_one_case(q):
|
409 |
+
angles1 = Matrix(q.to_euler(seq, True, True))
|
410 |
+
angles2 = Matrix(q.to_euler(seq, False, False))
|
411 |
+
angle_errors = simplify(angles1-angles2).evalf()
|
412 |
+
for angle_error in angle_errors:
|
413 |
+
# forcing angles to set {-pi, pi}
|
414 |
+
angle_error = (angle_error + pi) % (2 * pi) - pi
|
415 |
+
assert angle_error < 10e-7
|
416 |
+
|
417 |
+
for xyz in ('xyz', 'XYZ'):
|
418 |
+
for seq_tuple in permutations(xyz):
|
419 |
+
for symmetric in (True, False):
|
420 |
+
if symmetric:
|
421 |
+
seq = ''.join([seq_tuple[0], seq_tuple[1], seq_tuple[0]])
|
422 |
+
else:
|
423 |
+
seq = ''.join(seq_tuple)
|
424 |
+
|
425 |
+
for elements in product([-1, 0, 1], repeat=4):
|
426 |
+
q = Quaternion(*elements)
|
427 |
+
if not q.is_zero_quaternion():
|
428 |
+
test_one_case(q)
|
MLPY/Lib/site-packages/sympy/assumptions/__init__.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
A module to implement logical predicates and assumption system.
|
3 |
+
"""
|
4 |
+
|
5 |
+
from .assume import (
|
6 |
+
AppliedPredicate, Predicate, AssumptionsContext, assuming,
|
7 |
+
global_assumptions
|
8 |
+
)
|
9 |
+
from .ask import Q, ask, register_handler, remove_handler
|
10 |
+
from .refine import refine
|
11 |
+
from .relation import BinaryRelation, AppliedBinaryRelation
|
12 |
+
|
13 |
+
__all__ = [
|
14 |
+
'AppliedPredicate', 'Predicate', 'AssumptionsContext', 'assuming',
|
15 |
+
'global_assumptions', 'Q', 'ask', 'register_handler', 'remove_handler',
|
16 |
+
'refine',
|
17 |
+
'BinaryRelation', 'AppliedBinaryRelation'
|
18 |
+
]
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (659 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/ask.cpython-39.pyc
ADDED
Binary file (20 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/ask_generated.cpython-39.pyc
ADDED
Binary file (10.3 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/assume.cpython-39.pyc
ADDED
Binary file (14.5 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/cnf.cpython-39.pyc
ADDED
Binary file (17.2 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/facts.cpython-39.pyc
ADDED
Binary file (6.73 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/lra_satask.cpython-39.pyc
ADDED
Binary file (6.49 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/refine.cpython-39.pyc
ADDED
Binary file (9.89 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/satask.cpython-39.pyc
ADDED
Binary file (11 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/sathandlers.cpython-39.pyc
ADDED
Binary file (10.6 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/__pycache__/wrapper.cpython-39.pyc
ADDED
Binary file (5.41 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/ask.py
ADDED
@@ -0,0 +1,651 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module for querying SymPy objects about assumptions."""
|
2 |
+
|
3 |
+
from sympy.assumptions.assume import (global_assumptions, Predicate,
|
4 |
+
AppliedPredicate)
|
5 |
+
from sympy.assumptions.cnf import CNF, EncodedCNF, Literal
|
6 |
+
from sympy.core import sympify
|
7 |
+
from sympy.core.kind import BooleanKind
|
8 |
+
from sympy.core.relational import Eq, Ne, Gt, Lt, Ge, Le
|
9 |
+
from sympy.logic.inference import satisfiable
|
10 |
+
from sympy.utilities.decorator import memoize_property
|
11 |
+
from sympy.utilities.exceptions import (sympy_deprecation_warning,
|
12 |
+
SymPyDeprecationWarning,
|
13 |
+
ignore_warnings)
|
14 |
+
|
15 |
+
|
16 |
+
# Memoization is necessary for the properties of AssumptionKeys to
|
17 |
+
# ensure that only one object of Predicate objects are created.
|
18 |
+
# This is because assumption handlers are registered on those objects.
|
19 |
+
|
20 |
+
|
21 |
+
class AssumptionKeys:
|
22 |
+
"""
|
23 |
+
This class contains all the supported keys by ``ask``.
|
24 |
+
It should be accessed via the instance ``sympy.Q``.
|
25 |
+
|
26 |
+
"""
|
27 |
+
|
28 |
+
# DO NOT add methods or properties other than predicate keys.
|
29 |
+
# SAT solver checks the properties of Q and use them to compute the
|
30 |
+
# fact system. Non-predicate attributes will break this.
|
31 |
+
|
32 |
+
@memoize_property
|
33 |
+
def hermitian(self):
|
34 |
+
from .handlers.sets import HermitianPredicate
|
35 |
+
return HermitianPredicate()
|
36 |
+
|
37 |
+
@memoize_property
|
38 |
+
def antihermitian(self):
|
39 |
+
from .handlers.sets import AntihermitianPredicate
|
40 |
+
return AntihermitianPredicate()
|
41 |
+
|
42 |
+
@memoize_property
|
43 |
+
def real(self):
|
44 |
+
from .handlers.sets import RealPredicate
|
45 |
+
return RealPredicate()
|
46 |
+
|
47 |
+
@memoize_property
|
48 |
+
def extended_real(self):
|
49 |
+
from .handlers.sets import ExtendedRealPredicate
|
50 |
+
return ExtendedRealPredicate()
|
51 |
+
|
52 |
+
@memoize_property
|
53 |
+
def imaginary(self):
|
54 |
+
from .handlers.sets import ImaginaryPredicate
|
55 |
+
return ImaginaryPredicate()
|
56 |
+
|
57 |
+
@memoize_property
|
58 |
+
def complex(self):
|
59 |
+
from .handlers.sets import ComplexPredicate
|
60 |
+
return ComplexPredicate()
|
61 |
+
|
62 |
+
@memoize_property
|
63 |
+
def algebraic(self):
|
64 |
+
from .handlers.sets import AlgebraicPredicate
|
65 |
+
return AlgebraicPredicate()
|
66 |
+
|
67 |
+
@memoize_property
|
68 |
+
def transcendental(self):
|
69 |
+
from .predicates.sets import TranscendentalPredicate
|
70 |
+
return TranscendentalPredicate()
|
71 |
+
|
72 |
+
@memoize_property
|
73 |
+
def integer(self):
|
74 |
+
from .handlers.sets import IntegerPredicate
|
75 |
+
return IntegerPredicate()
|
76 |
+
|
77 |
+
@memoize_property
|
78 |
+
def noninteger(self):
|
79 |
+
from .predicates.sets import NonIntegerPredicate
|
80 |
+
return NonIntegerPredicate()
|
81 |
+
|
82 |
+
@memoize_property
|
83 |
+
def rational(self):
|
84 |
+
from .handlers.sets import RationalPredicate
|
85 |
+
return RationalPredicate()
|
86 |
+
|
87 |
+
@memoize_property
|
88 |
+
def irrational(self):
|
89 |
+
from .handlers.sets import IrrationalPredicate
|
90 |
+
return IrrationalPredicate()
|
91 |
+
|
92 |
+
@memoize_property
|
93 |
+
def finite(self):
|
94 |
+
from .handlers.calculus import FinitePredicate
|
95 |
+
return FinitePredicate()
|
96 |
+
|
97 |
+
@memoize_property
|
98 |
+
def infinite(self):
|
99 |
+
from .handlers.calculus import InfinitePredicate
|
100 |
+
return InfinitePredicate()
|
101 |
+
|
102 |
+
@memoize_property
|
103 |
+
def positive_infinite(self):
|
104 |
+
from .handlers.calculus import PositiveInfinitePredicate
|
105 |
+
return PositiveInfinitePredicate()
|
106 |
+
|
107 |
+
@memoize_property
|
108 |
+
def negative_infinite(self):
|
109 |
+
from .handlers.calculus import NegativeInfinitePredicate
|
110 |
+
return NegativeInfinitePredicate()
|
111 |
+
|
112 |
+
@memoize_property
|
113 |
+
def positive(self):
|
114 |
+
from .handlers.order import PositivePredicate
|
115 |
+
return PositivePredicate()
|
116 |
+
|
117 |
+
@memoize_property
|
118 |
+
def negative(self):
|
119 |
+
from .handlers.order import NegativePredicate
|
120 |
+
return NegativePredicate()
|
121 |
+
|
122 |
+
@memoize_property
|
123 |
+
def zero(self):
|
124 |
+
from .handlers.order import ZeroPredicate
|
125 |
+
return ZeroPredicate()
|
126 |
+
|
127 |
+
@memoize_property
|
128 |
+
def extended_positive(self):
|
129 |
+
from .handlers.order import ExtendedPositivePredicate
|
130 |
+
return ExtendedPositivePredicate()
|
131 |
+
|
132 |
+
@memoize_property
|
133 |
+
def extended_negative(self):
|
134 |
+
from .handlers.order import ExtendedNegativePredicate
|
135 |
+
return ExtendedNegativePredicate()
|
136 |
+
|
137 |
+
@memoize_property
|
138 |
+
def nonzero(self):
|
139 |
+
from .handlers.order import NonZeroPredicate
|
140 |
+
return NonZeroPredicate()
|
141 |
+
|
142 |
+
@memoize_property
|
143 |
+
def nonpositive(self):
|
144 |
+
from .handlers.order import NonPositivePredicate
|
145 |
+
return NonPositivePredicate()
|
146 |
+
|
147 |
+
@memoize_property
|
148 |
+
def nonnegative(self):
|
149 |
+
from .handlers.order import NonNegativePredicate
|
150 |
+
return NonNegativePredicate()
|
151 |
+
|
152 |
+
@memoize_property
|
153 |
+
def extended_nonzero(self):
|
154 |
+
from .handlers.order import ExtendedNonZeroPredicate
|
155 |
+
return ExtendedNonZeroPredicate()
|
156 |
+
|
157 |
+
@memoize_property
|
158 |
+
def extended_nonpositive(self):
|
159 |
+
from .handlers.order import ExtendedNonPositivePredicate
|
160 |
+
return ExtendedNonPositivePredicate()
|
161 |
+
|
162 |
+
@memoize_property
|
163 |
+
def extended_nonnegative(self):
|
164 |
+
from .handlers.order import ExtendedNonNegativePredicate
|
165 |
+
return ExtendedNonNegativePredicate()
|
166 |
+
|
167 |
+
@memoize_property
|
168 |
+
def even(self):
|
169 |
+
from .handlers.ntheory import EvenPredicate
|
170 |
+
return EvenPredicate()
|
171 |
+
|
172 |
+
@memoize_property
|
173 |
+
def odd(self):
|
174 |
+
from .handlers.ntheory import OddPredicate
|
175 |
+
return OddPredicate()
|
176 |
+
|
177 |
+
@memoize_property
|
178 |
+
def prime(self):
|
179 |
+
from .handlers.ntheory import PrimePredicate
|
180 |
+
return PrimePredicate()
|
181 |
+
|
182 |
+
@memoize_property
|
183 |
+
def composite(self):
|
184 |
+
from .handlers.ntheory import CompositePredicate
|
185 |
+
return CompositePredicate()
|
186 |
+
|
187 |
+
@memoize_property
|
188 |
+
def commutative(self):
|
189 |
+
from .handlers.common import CommutativePredicate
|
190 |
+
return CommutativePredicate()
|
191 |
+
|
192 |
+
@memoize_property
|
193 |
+
def is_true(self):
|
194 |
+
from .handlers.common import IsTruePredicate
|
195 |
+
return IsTruePredicate()
|
196 |
+
|
197 |
+
@memoize_property
|
198 |
+
def symmetric(self):
|
199 |
+
from .handlers.matrices import SymmetricPredicate
|
200 |
+
return SymmetricPredicate()
|
201 |
+
|
202 |
+
@memoize_property
|
203 |
+
def invertible(self):
|
204 |
+
from .handlers.matrices import InvertiblePredicate
|
205 |
+
return InvertiblePredicate()
|
206 |
+
|
207 |
+
@memoize_property
|
208 |
+
def orthogonal(self):
|
209 |
+
from .handlers.matrices import OrthogonalPredicate
|
210 |
+
return OrthogonalPredicate()
|
211 |
+
|
212 |
+
@memoize_property
|
213 |
+
def unitary(self):
|
214 |
+
from .handlers.matrices import UnitaryPredicate
|
215 |
+
return UnitaryPredicate()
|
216 |
+
|
217 |
+
@memoize_property
|
218 |
+
def positive_definite(self):
|
219 |
+
from .handlers.matrices import PositiveDefinitePredicate
|
220 |
+
return PositiveDefinitePredicate()
|
221 |
+
|
222 |
+
@memoize_property
|
223 |
+
def upper_triangular(self):
|
224 |
+
from .handlers.matrices import UpperTriangularPredicate
|
225 |
+
return UpperTriangularPredicate()
|
226 |
+
|
227 |
+
@memoize_property
|
228 |
+
def lower_triangular(self):
|
229 |
+
from .handlers.matrices import LowerTriangularPredicate
|
230 |
+
return LowerTriangularPredicate()
|
231 |
+
|
232 |
+
@memoize_property
|
233 |
+
def diagonal(self):
|
234 |
+
from .handlers.matrices import DiagonalPredicate
|
235 |
+
return DiagonalPredicate()
|
236 |
+
|
237 |
+
@memoize_property
|
238 |
+
def fullrank(self):
|
239 |
+
from .handlers.matrices import FullRankPredicate
|
240 |
+
return FullRankPredicate()
|
241 |
+
|
242 |
+
@memoize_property
|
243 |
+
def square(self):
|
244 |
+
from .handlers.matrices import SquarePredicate
|
245 |
+
return SquarePredicate()
|
246 |
+
|
247 |
+
@memoize_property
|
248 |
+
def integer_elements(self):
|
249 |
+
from .handlers.matrices import IntegerElementsPredicate
|
250 |
+
return IntegerElementsPredicate()
|
251 |
+
|
252 |
+
@memoize_property
|
253 |
+
def real_elements(self):
|
254 |
+
from .handlers.matrices import RealElementsPredicate
|
255 |
+
return RealElementsPredicate()
|
256 |
+
|
257 |
+
@memoize_property
|
258 |
+
def complex_elements(self):
|
259 |
+
from .handlers.matrices import ComplexElementsPredicate
|
260 |
+
return ComplexElementsPredicate()
|
261 |
+
|
262 |
+
@memoize_property
|
263 |
+
def singular(self):
|
264 |
+
from .predicates.matrices import SingularPredicate
|
265 |
+
return SingularPredicate()
|
266 |
+
|
267 |
+
@memoize_property
|
268 |
+
def normal(self):
|
269 |
+
from .predicates.matrices import NormalPredicate
|
270 |
+
return NormalPredicate()
|
271 |
+
|
272 |
+
@memoize_property
|
273 |
+
def triangular(self):
|
274 |
+
from .predicates.matrices import TriangularPredicate
|
275 |
+
return TriangularPredicate()
|
276 |
+
|
277 |
+
@memoize_property
|
278 |
+
def unit_triangular(self):
|
279 |
+
from .predicates.matrices import UnitTriangularPredicate
|
280 |
+
return UnitTriangularPredicate()
|
281 |
+
|
282 |
+
@memoize_property
|
283 |
+
def eq(self):
|
284 |
+
from .relation.equality import EqualityPredicate
|
285 |
+
return EqualityPredicate()
|
286 |
+
|
287 |
+
@memoize_property
|
288 |
+
def ne(self):
|
289 |
+
from .relation.equality import UnequalityPredicate
|
290 |
+
return UnequalityPredicate()
|
291 |
+
|
292 |
+
@memoize_property
|
293 |
+
def gt(self):
|
294 |
+
from .relation.equality import StrictGreaterThanPredicate
|
295 |
+
return StrictGreaterThanPredicate()
|
296 |
+
|
297 |
+
@memoize_property
|
298 |
+
def ge(self):
|
299 |
+
from .relation.equality import GreaterThanPredicate
|
300 |
+
return GreaterThanPredicate()
|
301 |
+
|
302 |
+
@memoize_property
|
303 |
+
def lt(self):
|
304 |
+
from .relation.equality import StrictLessThanPredicate
|
305 |
+
return StrictLessThanPredicate()
|
306 |
+
|
307 |
+
@memoize_property
|
308 |
+
def le(self):
|
309 |
+
from .relation.equality import LessThanPredicate
|
310 |
+
return LessThanPredicate()
|
311 |
+
|
312 |
+
|
313 |
+
Q = AssumptionKeys()
|
314 |
+
|
315 |
+
def _extract_all_facts(assump, exprs):
|
316 |
+
"""
|
317 |
+
Extract all relevant assumptions from *assump* with respect to given *exprs*.
|
318 |
+
|
319 |
+
Parameters
|
320 |
+
==========
|
321 |
+
|
322 |
+
assump : sympy.assumptions.cnf.CNF
|
323 |
+
|
324 |
+
exprs : tuple of expressions
|
325 |
+
|
326 |
+
Returns
|
327 |
+
=======
|
328 |
+
|
329 |
+
sympy.assumptions.cnf.CNF
|
330 |
+
|
331 |
+
Examples
|
332 |
+
========
|
333 |
+
|
334 |
+
>>> from sympy import Q
|
335 |
+
>>> from sympy.assumptions.cnf import CNF
|
336 |
+
>>> from sympy.assumptions.ask import _extract_all_facts
|
337 |
+
>>> from sympy.abc import x, y
|
338 |
+
>>> assump = CNF.from_prop(Q.positive(x) & Q.integer(y))
|
339 |
+
>>> exprs = (x,)
|
340 |
+
>>> cnf = _extract_all_facts(assump, exprs)
|
341 |
+
>>> cnf.clauses
|
342 |
+
{frozenset({Literal(Q.positive, False)})}
|
343 |
+
|
344 |
+
"""
|
345 |
+
facts = set()
|
346 |
+
|
347 |
+
for clause in assump.clauses:
|
348 |
+
args = []
|
349 |
+
for literal in clause:
|
350 |
+
if isinstance(literal.lit, AppliedPredicate) and len(literal.lit.arguments) == 1:
|
351 |
+
if literal.lit.arg in exprs:
|
352 |
+
# Add literal if it has matching in it
|
353 |
+
args.append(Literal(literal.lit.function, literal.is_Not))
|
354 |
+
else:
|
355 |
+
# If any of the literals doesn't have matching expr don't add the whole clause.
|
356 |
+
break
|
357 |
+
else:
|
358 |
+
# If any of the literals aren't unary predicate don't add the whole clause.
|
359 |
+
break
|
360 |
+
|
361 |
+
else:
|
362 |
+
if args:
|
363 |
+
facts.add(frozenset(args))
|
364 |
+
return CNF(facts)
|
365 |
+
|
366 |
+
|
367 |
+
def ask(proposition, assumptions=True, context=global_assumptions):
|
368 |
+
"""
|
369 |
+
Function to evaluate the proposition with assumptions.
|
370 |
+
|
371 |
+
Explanation
|
372 |
+
===========
|
373 |
+
|
374 |
+
This function evaluates the proposition to ``True`` or ``False`` if
|
375 |
+
the truth value can be determined. If not, it returns ``None``.
|
376 |
+
|
377 |
+
It should be discerned from :func:`~.refine()` which, when applied to a
|
378 |
+
proposition, simplifies the argument to symbolic ``Boolean`` instead of
|
379 |
+
Python built-in ``True``, ``False`` or ``None``.
|
380 |
+
|
381 |
+
**Syntax**
|
382 |
+
|
383 |
+
* ask(proposition)
|
384 |
+
Evaluate the *proposition* in global assumption context.
|
385 |
+
|
386 |
+
* ask(proposition, assumptions)
|
387 |
+
Evaluate the *proposition* with respect to *assumptions* in
|
388 |
+
global assumption context.
|
389 |
+
|
390 |
+
Parameters
|
391 |
+
==========
|
392 |
+
|
393 |
+
proposition : Boolean
|
394 |
+
Proposition which will be evaluated to boolean value. If this is
|
395 |
+
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``.
|
396 |
+
|
397 |
+
assumptions : Boolean, optional
|
398 |
+
Local assumptions to evaluate the *proposition*.
|
399 |
+
|
400 |
+
context : AssumptionsContext, optional
|
401 |
+
Default assumptions to evaluate the *proposition*. By default,
|
402 |
+
this is ``sympy.assumptions.global_assumptions`` variable.
|
403 |
+
|
404 |
+
Returns
|
405 |
+
=======
|
406 |
+
|
407 |
+
``True``, ``False``, or ``None``
|
408 |
+
|
409 |
+
Raises
|
410 |
+
======
|
411 |
+
|
412 |
+
TypeError : *proposition* or *assumptions* is not valid logical expression.
|
413 |
+
|
414 |
+
ValueError : assumptions are inconsistent.
|
415 |
+
|
416 |
+
Examples
|
417 |
+
========
|
418 |
+
|
419 |
+
>>> from sympy import ask, Q, pi
|
420 |
+
>>> from sympy.abc import x, y
|
421 |
+
>>> ask(Q.rational(pi))
|
422 |
+
False
|
423 |
+
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y))
|
424 |
+
True
|
425 |
+
>>> ask(Q.prime(4*x), Q.integer(x))
|
426 |
+
False
|
427 |
+
|
428 |
+
If the truth value cannot be determined, ``None`` will be returned.
|
429 |
+
|
430 |
+
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x
|
431 |
+
None
|
432 |
+
|
433 |
+
``ValueError`` is raised if assumptions are inconsistent.
|
434 |
+
|
435 |
+
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x))
|
436 |
+
Traceback (most recent call last):
|
437 |
+
...
|
438 |
+
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x)
|
439 |
+
|
440 |
+
Notes
|
441 |
+
=====
|
442 |
+
|
443 |
+
Relations in assumptions are not implemented (yet), so the following
|
444 |
+
will not give a meaningful result.
|
445 |
+
|
446 |
+
>>> ask(Q.positive(x), x > 0)
|
447 |
+
|
448 |
+
It is however a work in progress.
|
449 |
+
|
450 |
+
See Also
|
451 |
+
========
|
452 |
+
|
453 |
+
sympy.assumptions.refine.refine : Simplification using assumptions.
|
454 |
+
Proposition is not reduced to ``None`` if the truth value cannot
|
455 |
+
be determined.
|
456 |
+
"""
|
457 |
+
from sympy.assumptions.satask import satask
|
458 |
+
from sympy.assumptions.lra_satask import lra_satask
|
459 |
+
from sympy.logic.algorithms.lra_theory import UnhandledInput
|
460 |
+
|
461 |
+
proposition = sympify(proposition)
|
462 |
+
assumptions = sympify(assumptions)
|
463 |
+
|
464 |
+
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind:
|
465 |
+
raise TypeError("proposition must be a valid logical expression")
|
466 |
+
|
467 |
+
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind:
|
468 |
+
raise TypeError("assumptions must be a valid logical expression")
|
469 |
+
|
470 |
+
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le}
|
471 |
+
if isinstance(proposition, AppliedPredicate):
|
472 |
+
key, args = proposition.function, proposition.arguments
|
473 |
+
elif proposition.func in binrelpreds:
|
474 |
+
key, args = binrelpreds[type(proposition)], proposition.args
|
475 |
+
else:
|
476 |
+
key, args = Q.is_true, (proposition,)
|
477 |
+
|
478 |
+
# convert local and global assumptions to CNF
|
479 |
+
assump_cnf = CNF.from_prop(assumptions)
|
480 |
+
assump_cnf.extend(context)
|
481 |
+
|
482 |
+
# extract the relevant facts from assumptions with respect to args
|
483 |
+
local_facts = _extract_all_facts(assump_cnf, args)
|
484 |
+
|
485 |
+
# convert default facts and assumed facts to encoded CNF
|
486 |
+
known_facts_cnf = get_all_known_facts()
|
487 |
+
enc_cnf = EncodedCNF()
|
488 |
+
enc_cnf.from_cnf(CNF(known_facts_cnf))
|
489 |
+
enc_cnf.add_from_cnf(local_facts)
|
490 |
+
|
491 |
+
# check the satisfiability of given assumptions
|
492 |
+
if local_facts.clauses and satisfiable(enc_cnf) is False:
|
493 |
+
raise ValueError("inconsistent assumptions %s" % assumptions)
|
494 |
+
|
495 |
+
# quick computation for single fact
|
496 |
+
res = _ask_single_fact(key, local_facts)
|
497 |
+
if res is not None:
|
498 |
+
return res
|
499 |
+
|
500 |
+
# direct resolution method, no logic
|
501 |
+
res = key(*args)._eval_ask(assumptions)
|
502 |
+
if res is not None:
|
503 |
+
return bool(res)
|
504 |
+
|
505 |
+
# using satask (still costly)
|
506 |
+
res = satask(proposition, assumptions=assumptions, context=context)
|
507 |
+
if res is not None:
|
508 |
+
return res
|
509 |
+
|
510 |
+
try:
|
511 |
+
res = lra_satask(proposition, assumptions=assumptions, context=context)
|
512 |
+
except UnhandledInput:
|
513 |
+
return None
|
514 |
+
|
515 |
+
return res
|
516 |
+
|
517 |
+
|
518 |
+
def _ask_single_fact(key, local_facts):
|
519 |
+
"""
|
520 |
+
Compute the truth value of single predicate using assumptions.
|
521 |
+
|
522 |
+
Parameters
|
523 |
+
==========
|
524 |
+
|
525 |
+
key : sympy.assumptions.assume.Predicate
|
526 |
+
Proposition predicate.
|
527 |
+
|
528 |
+
local_facts : sympy.assumptions.cnf.CNF
|
529 |
+
Local assumption in CNF form.
|
530 |
+
|
531 |
+
Returns
|
532 |
+
=======
|
533 |
+
|
534 |
+
``True``, ``False`` or ``None``
|
535 |
+
|
536 |
+
Examples
|
537 |
+
========
|
538 |
+
|
539 |
+
>>> from sympy import Q
|
540 |
+
>>> from sympy.assumptions.cnf import CNF
|
541 |
+
>>> from sympy.assumptions.ask import _ask_single_fact
|
542 |
+
|
543 |
+
If prerequisite of proposition is rejected by the assumption,
|
544 |
+
return ``False``.
|
545 |
+
|
546 |
+
>>> key, assump = Q.zero, ~Q.zero
|
547 |
+
>>> local_facts = CNF.from_prop(assump)
|
548 |
+
>>> _ask_single_fact(key, local_facts)
|
549 |
+
False
|
550 |
+
>>> key, assump = Q.zero, ~Q.even
|
551 |
+
>>> local_facts = CNF.from_prop(assump)
|
552 |
+
>>> _ask_single_fact(key, local_facts)
|
553 |
+
False
|
554 |
+
|
555 |
+
If assumption implies the proposition, return ``True``.
|
556 |
+
|
557 |
+
>>> key, assump = Q.even, Q.zero
|
558 |
+
>>> local_facts = CNF.from_prop(assump)
|
559 |
+
>>> _ask_single_fact(key, local_facts)
|
560 |
+
True
|
561 |
+
|
562 |
+
If proposition rejects the assumption, return ``False``.
|
563 |
+
|
564 |
+
>>> key, assump = Q.even, Q.odd
|
565 |
+
>>> local_facts = CNF.from_prop(assump)
|
566 |
+
>>> _ask_single_fact(key, local_facts)
|
567 |
+
False
|
568 |
+
"""
|
569 |
+
if local_facts.clauses:
|
570 |
+
|
571 |
+
known_facts_dict = get_known_facts_dict()
|
572 |
+
|
573 |
+
if len(local_facts.clauses) == 1:
|
574 |
+
cl, = local_facts.clauses
|
575 |
+
if len(cl) == 1:
|
576 |
+
f, = cl
|
577 |
+
prop_facts = known_facts_dict.get(key, None)
|
578 |
+
prop_req = prop_facts[0] if prop_facts is not None else set()
|
579 |
+
if f.is_Not and f.arg in prop_req:
|
580 |
+
# the prerequisite of proposition is rejected
|
581 |
+
return False
|
582 |
+
|
583 |
+
for clause in local_facts.clauses:
|
584 |
+
if len(clause) == 1:
|
585 |
+
f, = clause
|
586 |
+
prop_facts = known_facts_dict.get(f.arg, None) if not f.is_Not else None
|
587 |
+
if prop_facts is None:
|
588 |
+
continue
|
589 |
+
|
590 |
+
prop_req, prop_rej = prop_facts
|
591 |
+
if key in prop_req:
|
592 |
+
# assumption implies the proposition
|
593 |
+
return True
|
594 |
+
elif key in prop_rej:
|
595 |
+
# proposition rejects the assumption
|
596 |
+
return False
|
597 |
+
|
598 |
+
return None
|
599 |
+
|
600 |
+
|
601 |
+
def register_handler(key, handler):
|
602 |
+
"""
|
603 |
+
Register a handler in the ask system. key must be a string and handler a
|
604 |
+
class inheriting from AskHandler.
|
605 |
+
|
606 |
+
.. deprecated:: 1.8.
|
607 |
+
Use multipledispatch handler instead. See :obj:`~.Predicate`.
|
608 |
+
|
609 |
+
"""
|
610 |
+
sympy_deprecation_warning(
|
611 |
+
"""
|
612 |
+
The AskHandler system is deprecated. The register_handler() function
|
613 |
+
should be replaced with the multipledispatch handler of Predicate.
|
614 |
+
""",
|
615 |
+
deprecated_since_version="1.8",
|
616 |
+
active_deprecations_target='deprecated-askhandler',
|
617 |
+
)
|
618 |
+
if isinstance(key, Predicate):
|
619 |
+
key = key.name.name
|
620 |
+
Qkey = getattr(Q, key, None)
|
621 |
+
if Qkey is not None:
|
622 |
+
Qkey.add_handler(handler)
|
623 |
+
else:
|
624 |
+
setattr(Q, key, Predicate(key, handlers=[handler]))
|
625 |
+
|
626 |
+
|
627 |
+
def remove_handler(key, handler):
|
628 |
+
"""
|
629 |
+
Removes a handler from the ask system.
|
630 |
+
|
631 |
+
.. deprecated:: 1.8.
|
632 |
+
Use multipledispatch handler instead. See :obj:`~.Predicate`.
|
633 |
+
|
634 |
+
"""
|
635 |
+
sympy_deprecation_warning(
|
636 |
+
"""
|
637 |
+
The AskHandler system is deprecated. The remove_handler() function
|
638 |
+
should be replaced with the multipledispatch handler of Predicate.
|
639 |
+
""",
|
640 |
+
deprecated_since_version="1.8",
|
641 |
+
active_deprecations_target='deprecated-askhandler',
|
642 |
+
)
|
643 |
+
if isinstance(key, Predicate):
|
644 |
+
key = key.name.name
|
645 |
+
# Don't show the same warning again recursively
|
646 |
+
with ignore_warnings(SymPyDeprecationWarning):
|
647 |
+
getattr(Q, key).remove_handler(handler)
|
648 |
+
|
649 |
+
|
650 |
+
from sympy.assumptions.ask_generated import (get_all_known_facts,
|
651 |
+
get_known_facts_dict)
|
MLPY/Lib/site-packages/sympy/assumptions/ask_generated.py
ADDED
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Do NOT manually edit this file.
|
3 |
+
Instead, run ./bin/ask_update.py.
|
4 |
+
"""
|
5 |
+
|
6 |
+
from sympy.assumptions.ask import Q
|
7 |
+
from sympy.assumptions.cnf import Literal
|
8 |
+
from sympy.core.cache import cacheit
|
9 |
+
|
10 |
+
@cacheit
|
11 |
+
def get_all_known_facts():
|
12 |
+
"""
|
13 |
+
Known facts between unary predicates as CNF clauses.
|
14 |
+
"""
|
15 |
+
return {
|
16 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.imaginary, True), Literal(Q.transcendental, False))),
|
17 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.negative, True), Literal(Q.transcendental, False))),
|
18 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.positive, True), Literal(Q.transcendental, False))),
|
19 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.rational, True))),
|
20 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.transcendental, False), Literal(Q.zero, True))),
|
21 |
+
frozenset((Literal(Q.algebraic, True), Literal(Q.finite, False))),
|
22 |
+
frozenset((Literal(Q.algebraic, True), Literal(Q.transcendental, True))),
|
23 |
+
frozenset((Literal(Q.antihermitian, False), Literal(Q.hermitian, False), Literal(Q.zero, True))),
|
24 |
+
frozenset((Literal(Q.antihermitian, False), Literal(Q.imaginary, True))),
|
25 |
+
frozenset((Literal(Q.commutative, False), Literal(Q.finite, True))),
|
26 |
+
frozenset((Literal(Q.commutative, False), Literal(Q.infinite, True))),
|
27 |
+
frozenset((Literal(Q.complex_elements, False), Literal(Q.real_elements, True))),
|
28 |
+
frozenset((Literal(Q.composite, False), Literal(Q.even, True), Literal(Q.positive, True), Literal(Q.prime, False))),
|
29 |
+
frozenset((Literal(Q.composite, True), Literal(Q.even, False), Literal(Q.odd, False))),
|
30 |
+
frozenset((Literal(Q.composite, True), Literal(Q.positive, False))),
|
31 |
+
frozenset((Literal(Q.composite, True), Literal(Q.prime, True))),
|
32 |
+
frozenset((Literal(Q.diagonal, False), Literal(Q.lower_triangular, True), Literal(Q.upper_triangular, True))),
|
33 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.lower_triangular, False))),
|
34 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.normal, False))),
|
35 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.symmetric, False))),
|
36 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.upper_triangular, False))),
|
37 |
+
frozenset((Literal(Q.even, False), Literal(Q.odd, False), Literal(Q.prime, True))),
|
38 |
+
frozenset((Literal(Q.even, False), Literal(Q.zero, True))),
|
39 |
+
frozenset((Literal(Q.even, True), Literal(Q.odd, True))),
|
40 |
+
frozenset((Literal(Q.even, True), Literal(Q.rational, False))),
|
41 |
+
frozenset((Literal(Q.finite, False), Literal(Q.transcendental, True))),
|
42 |
+
frozenset((Literal(Q.finite, True), Literal(Q.infinite, True))),
|
43 |
+
frozenset((Literal(Q.fullrank, False), Literal(Q.invertible, True))),
|
44 |
+
frozenset((Literal(Q.fullrank, True), Literal(Q.invertible, False), Literal(Q.square, True))),
|
45 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.negative, True))),
|
46 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.positive, True))),
|
47 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.zero, True))),
|
48 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.negative, True))),
|
49 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.positive, True))),
|
50 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.zero, True))),
|
51 |
+
frozenset((Literal(Q.infinite, False), Literal(Q.negative_infinite, True))),
|
52 |
+
frozenset((Literal(Q.infinite, False), Literal(Q.positive_infinite, True))),
|
53 |
+
frozenset((Literal(Q.integer_elements, True), Literal(Q.real_elements, False))),
|
54 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.positive_definite, True))),
|
55 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.singular, False))),
|
56 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.unitary, True))),
|
57 |
+
frozenset((Literal(Q.invertible, True), Literal(Q.singular, True))),
|
58 |
+
frozenset((Literal(Q.invertible, True), Literal(Q.square, False))),
|
59 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.negative, True), Literal(Q.rational, False))),
|
60 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.positive, True), Literal(Q.rational, False))),
|
61 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.rational, False), Literal(Q.zero, True))),
|
62 |
+
frozenset((Literal(Q.irrational, True), Literal(Q.negative, False), Literal(Q.positive, False), Literal(Q.zero, False))),
|
63 |
+
frozenset((Literal(Q.irrational, True), Literal(Q.rational, True))),
|
64 |
+
frozenset((Literal(Q.lower_triangular, False), Literal(Q.triangular, True), Literal(Q.upper_triangular, False))),
|
65 |
+
frozenset((Literal(Q.lower_triangular, True), Literal(Q.triangular, False))),
|
66 |
+
frozenset((Literal(Q.negative, False), Literal(Q.positive, False), Literal(Q.rational, True), Literal(Q.zero, False))),
|
67 |
+
frozenset((Literal(Q.negative, True), Literal(Q.negative_infinite, True))),
|
68 |
+
frozenset((Literal(Q.negative, True), Literal(Q.positive, True))),
|
69 |
+
frozenset((Literal(Q.negative, True), Literal(Q.positive_infinite, True))),
|
70 |
+
frozenset((Literal(Q.negative, True), Literal(Q.zero, True))),
|
71 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.positive, True))),
|
72 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.positive_infinite, True))),
|
73 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.zero, True))),
|
74 |
+
frozenset((Literal(Q.normal, False), Literal(Q.unitary, True))),
|
75 |
+
frozenset((Literal(Q.normal, True), Literal(Q.square, False))),
|
76 |
+
frozenset((Literal(Q.odd, True), Literal(Q.rational, False))),
|
77 |
+
frozenset((Literal(Q.orthogonal, False), Literal(Q.real_elements, True), Literal(Q.unitary, True))),
|
78 |
+
frozenset((Literal(Q.orthogonal, True), Literal(Q.positive_definite, False))),
|
79 |
+
frozenset((Literal(Q.orthogonal, True), Literal(Q.unitary, False))),
|
80 |
+
frozenset((Literal(Q.positive, False), Literal(Q.prime, True))),
|
81 |
+
frozenset((Literal(Q.positive, True), Literal(Q.positive_infinite, True))),
|
82 |
+
frozenset((Literal(Q.positive, True), Literal(Q.zero, True))),
|
83 |
+
frozenset((Literal(Q.positive_infinite, True), Literal(Q.zero, True))),
|
84 |
+
frozenset((Literal(Q.square, False), Literal(Q.symmetric, True))),
|
85 |
+
frozenset((Literal(Q.triangular, False), Literal(Q.unit_triangular, True))),
|
86 |
+
frozenset((Literal(Q.triangular, False), Literal(Q.upper_triangular, True)))
|
87 |
+
}
|
88 |
+
|
89 |
+
@cacheit
|
90 |
+
def get_all_known_matrix_facts():
|
91 |
+
"""
|
92 |
+
Known facts between unary predicates for matrices as CNF clauses.
|
93 |
+
"""
|
94 |
+
return {
|
95 |
+
frozenset((Literal(Q.complex_elements, False), Literal(Q.real_elements, True))),
|
96 |
+
frozenset((Literal(Q.diagonal, False), Literal(Q.lower_triangular, True), Literal(Q.upper_triangular, True))),
|
97 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.lower_triangular, False))),
|
98 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.normal, False))),
|
99 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.symmetric, False))),
|
100 |
+
frozenset((Literal(Q.diagonal, True), Literal(Q.upper_triangular, False))),
|
101 |
+
frozenset((Literal(Q.fullrank, False), Literal(Q.invertible, True))),
|
102 |
+
frozenset((Literal(Q.fullrank, True), Literal(Q.invertible, False), Literal(Q.square, True))),
|
103 |
+
frozenset((Literal(Q.integer_elements, True), Literal(Q.real_elements, False))),
|
104 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.positive_definite, True))),
|
105 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.singular, False))),
|
106 |
+
frozenset((Literal(Q.invertible, False), Literal(Q.unitary, True))),
|
107 |
+
frozenset((Literal(Q.invertible, True), Literal(Q.singular, True))),
|
108 |
+
frozenset((Literal(Q.invertible, True), Literal(Q.square, False))),
|
109 |
+
frozenset((Literal(Q.lower_triangular, False), Literal(Q.triangular, True), Literal(Q.upper_triangular, False))),
|
110 |
+
frozenset((Literal(Q.lower_triangular, True), Literal(Q.triangular, False))),
|
111 |
+
frozenset((Literal(Q.normal, False), Literal(Q.unitary, True))),
|
112 |
+
frozenset((Literal(Q.normal, True), Literal(Q.square, False))),
|
113 |
+
frozenset((Literal(Q.orthogonal, False), Literal(Q.real_elements, True), Literal(Q.unitary, True))),
|
114 |
+
frozenset((Literal(Q.orthogonal, True), Literal(Q.positive_definite, False))),
|
115 |
+
frozenset((Literal(Q.orthogonal, True), Literal(Q.unitary, False))),
|
116 |
+
frozenset((Literal(Q.square, False), Literal(Q.symmetric, True))),
|
117 |
+
frozenset((Literal(Q.triangular, False), Literal(Q.unit_triangular, True))),
|
118 |
+
frozenset((Literal(Q.triangular, False), Literal(Q.upper_triangular, True)))
|
119 |
+
}
|
120 |
+
|
121 |
+
@cacheit
|
122 |
+
def get_all_known_number_facts():
|
123 |
+
"""
|
124 |
+
Known facts between unary predicates for numbers as CNF clauses.
|
125 |
+
"""
|
126 |
+
return {
|
127 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.imaginary, True), Literal(Q.transcendental, False))),
|
128 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.negative, True), Literal(Q.transcendental, False))),
|
129 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.positive, True), Literal(Q.transcendental, False))),
|
130 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.rational, True))),
|
131 |
+
frozenset((Literal(Q.algebraic, False), Literal(Q.transcendental, False), Literal(Q.zero, True))),
|
132 |
+
frozenset((Literal(Q.algebraic, True), Literal(Q.finite, False))),
|
133 |
+
frozenset((Literal(Q.algebraic, True), Literal(Q.transcendental, True))),
|
134 |
+
frozenset((Literal(Q.antihermitian, False), Literal(Q.hermitian, False), Literal(Q.zero, True))),
|
135 |
+
frozenset((Literal(Q.antihermitian, False), Literal(Q.imaginary, True))),
|
136 |
+
frozenset((Literal(Q.commutative, False), Literal(Q.finite, True))),
|
137 |
+
frozenset((Literal(Q.commutative, False), Literal(Q.infinite, True))),
|
138 |
+
frozenset((Literal(Q.composite, False), Literal(Q.even, True), Literal(Q.positive, True), Literal(Q.prime, False))),
|
139 |
+
frozenset((Literal(Q.composite, True), Literal(Q.even, False), Literal(Q.odd, False))),
|
140 |
+
frozenset((Literal(Q.composite, True), Literal(Q.positive, False))),
|
141 |
+
frozenset((Literal(Q.composite, True), Literal(Q.prime, True))),
|
142 |
+
frozenset((Literal(Q.even, False), Literal(Q.odd, False), Literal(Q.prime, True))),
|
143 |
+
frozenset((Literal(Q.even, False), Literal(Q.zero, True))),
|
144 |
+
frozenset((Literal(Q.even, True), Literal(Q.odd, True))),
|
145 |
+
frozenset((Literal(Q.even, True), Literal(Q.rational, False))),
|
146 |
+
frozenset((Literal(Q.finite, False), Literal(Q.transcendental, True))),
|
147 |
+
frozenset((Literal(Q.finite, True), Literal(Q.infinite, True))),
|
148 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.negative, True))),
|
149 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.positive, True))),
|
150 |
+
frozenset((Literal(Q.hermitian, False), Literal(Q.zero, True))),
|
151 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.negative, True))),
|
152 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.positive, True))),
|
153 |
+
frozenset((Literal(Q.imaginary, True), Literal(Q.zero, True))),
|
154 |
+
frozenset((Literal(Q.infinite, False), Literal(Q.negative_infinite, True))),
|
155 |
+
frozenset((Literal(Q.infinite, False), Literal(Q.positive_infinite, True))),
|
156 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.negative, True), Literal(Q.rational, False))),
|
157 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.positive, True), Literal(Q.rational, False))),
|
158 |
+
frozenset((Literal(Q.irrational, False), Literal(Q.rational, False), Literal(Q.zero, True))),
|
159 |
+
frozenset((Literal(Q.irrational, True), Literal(Q.negative, False), Literal(Q.positive, False), Literal(Q.zero, False))),
|
160 |
+
frozenset((Literal(Q.irrational, True), Literal(Q.rational, True))),
|
161 |
+
frozenset((Literal(Q.negative, False), Literal(Q.positive, False), Literal(Q.rational, True), Literal(Q.zero, False))),
|
162 |
+
frozenset((Literal(Q.negative, True), Literal(Q.negative_infinite, True))),
|
163 |
+
frozenset((Literal(Q.negative, True), Literal(Q.positive, True))),
|
164 |
+
frozenset((Literal(Q.negative, True), Literal(Q.positive_infinite, True))),
|
165 |
+
frozenset((Literal(Q.negative, True), Literal(Q.zero, True))),
|
166 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.positive, True))),
|
167 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.positive_infinite, True))),
|
168 |
+
frozenset((Literal(Q.negative_infinite, True), Literal(Q.zero, True))),
|
169 |
+
frozenset((Literal(Q.odd, True), Literal(Q.rational, False))),
|
170 |
+
frozenset((Literal(Q.positive, False), Literal(Q.prime, True))),
|
171 |
+
frozenset((Literal(Q.positive, True), Literal(Q.positive_infinite, True))),
|
172 |
+
frozenset((Literal(Q.positive, True), Literal(Q.zero, True))),
|
173 |
+
frozenset((Literal(Q.positive_infinite, True), Literal(Q.zero, True)))
|
174 |
+
}
|
175 |
+
|
176 |
+
@cacheit
|
177 |
+
def get_known_facts_dict():
|
178 |
+
"""
|
179 |
+
Logical relations between unary predicates as dictionary.
|
180 |
+
|
181 |
+
Each key is a predicate, and item is two groups of predicates.
|
182 |
+
First group contains the predicates which are implied by the key, and
|
183 |
+
second group contains the predicates which are rejected by the key.
|
184 |
+
|
185 |
+
"""
|
186 |
+
return {
|
187 |
+
Q.algebraic: (set([Q.algebraic, Q.commutative, Q.complex, Q.finite]),
|
188 |
+
set([Q.infinite, Q.negative_infinite, Q.positive_infinite,
|
189 |
+
Q.transcendental])),
|
190 |
+
Q.antihermitian: (set([Q.antihermitian]), set([])),
|
191 |
+
Q.commutative: (set([Q.commutative]), set([])),
|
192 |
+
Q.complex: (set([Q.commutative, Q.complex, Q.finite]),
|
193 |
+
set([Q.infinite, Q.negative_infinite, Q.positive_infinite])),
|
194 |
+
Q.complex_elements: (set([Q.complex_elements]), set([])),
|
195 |
+
Q.composite: (set([Q.algebraic, Q.commutative, Q.complex, Q.composite,
|
196 |
+
Q.extended_nonnegative, Q.extended_nonzero,
|
197 |
+
Q.extended_positive, Q.extended_real, Q.finite, Q.hermitian,
|
198 |
+
Q.integer, Q.nonnegative, Q.nonzero, Q.positive, Q.rational,
|
199 |
+
Q.real]), set([Q.extended_negative, Q.extended_nonpositive,
|
200 |
+
Q.imaginary, Q.infinite, Q.irrational, Q.negative,
|
201 |
+
Q.negative_infinite, Q.nonpositive, Q.positive_infinite,
|
202 |
+
Q.prime, Q.transcendental, Q.zero])),
|
203 |
+
Q.diagonal: (set([Q.diagonal, Q.lower_triangular, Q.normal, Q.square,
|
204 |
+
Q.symmetric, Q.triangular, Q.upper_triangular]), set([])),
|
205 |
+
Q.even: (set([Q.algebraic, Q.commutative, Q.complex, Q.even,
|
206 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.integer, Q.rational,
|
207 |
+
Q.real]), set([Q.imaginary, Q.infinite, Q.irrational,
|
208 |
+
Q.negative_infinite, Q.odd, Q.positive_infinite,
|
209 |
+
Q.transcendental])),
|
210 |
+
Q.extended_negative: (set([Q.commutative, Q.extended_negative,
|
211 |
+
Q.extended_nonpositive, Q.extended_nonzero, Q.extended_real]),
|
212 |
+
set([Q.composite, Q.extended_nonnegative, Q.extended_positive,
|
213 |
+
Q.imaginary, Q.nonnegative, Q.positive, Q.positive_infinite,
|
214 |
+
Q.prime, Q.zero])),
|
215 |
+
Q.extended_nonnegative: (set([Q.commutative, Q.extended_nonnegative,
|
216 |
+
Q.extended_real]), set([Q.extended_negative, Q.imaginary,
|
217 |
+
Q.negative, Q.negative_infinite])),
|
218 |
+
Q.extended_nonpositive: (set([Q.commutative, Q.extended_nonpositive,
|
219 |
+
Q.extended_real]), set([Q.composite, Q.extended_positive,
|
220 |
+
Q.imaginary, Q.positive, Q.positive_infinite, Q.prime])),
|
221 |
+
Q.extended_nonzero: (set([Q.commutative, Q.extended_nonzero,
|
222 |
+
Q.extended_real]), set([Q.imaginary, Q.zero])),
|
223 |
+
Q.extended_positive: (set([Q.commutative, Q.extended_nonnegative,
|
224 |
+
Q.extended_nonzero, Q.extended_positive, Q.extended_real]),
|
225 |
+
set([Q.extended_negative, Q.extended_nonpositive, Q.imaginary,
|
226 |
+
Q.negative, Q.negative_infinite, Q.nonpositive, Q.zero])),
|
227 |
+
Q.extended_real: (set([Q.commutative, Q.extended_real]),
|
228 |
+
set([Q.imaginary])),
|
229 |
+
Q.finite: (set([Q.commutative, Q.finite]), set([Q.infinite,
|
230 |
+
Q.negative_infinite, Q.positive_infinite])),
|
231 |
+
Q.fullrank: (set([Q.fullrank]), set([])),
|
232 |
+
Q.hermitian: (set([Q.hermitian]), set([])),
|
233 |
+
Q.imaginary: (set([Q.antihermitian, Q.commutative, Q.complex,
|
234 |
+
Q.finite, Q.imaginary]), set([Q.composite, Q.even,
|
235 |
+
Q.extended_negative, Q.extended_nonnegative,
|
236 |
+
Q.extended_nonpositive, Q.extended_nonzero,
|
237 |
+
Q.extended_positive, Q.extended_real, Q.infinite, Q.integer,
|
238 |
+
Q.irrational, Q.negative, Q.negative_infinite, Q.nonnegative,
|
239 |
+
Q.nonpositive, Q.nonzero, Q.odd, Q.positive,
|
240 |
+
Q.positive_infinite, Q.prime, Q.rational, Q.real, Q.zero])),
|
241 |
+
Q.infinite: (set([Q.commutative, Q.infinite]), set([Q.algebraic,
|
242 |
+
Q.complex, Q.composite, Q.even, Q.finite, Q.imaginary,
|
243 |
+
Q.integer, Q.irrational, Q.negative, Q.nonnegative,
|
244 |
+
Q.nonpositive, Q.nonzero, Q.odd, Q.positive, Q.prime,
|
245 |
+
Q.rational, Q.real, Q.transcendental, Q.zero])),
|
246 |
+
Q.integer: (set([Q.algebraic, Q.commutative, Q.complex,
|
247 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.integer, Q.rational,
|
248 |
+
Q.real]), set([Q.imaginary, Q.infinite, Q.irrational,
|
249 |
+
Q.negative_infinite, Q.positive_infinite, Q.transcendental])),
|
250 |
+
Q.integer_elements: (set([Q.complex_elements, Q.integer_elements,
|
251 |
+
Q.real_elements]), set([])),
|
252 |
+
Q.invertible: (set([Q.fullrank, Q.invertible, Q.square]),
|
253 |
+
set([Q.singular])),
|
254 |
+
Q.irrational: (set([Q.commutative, Q.complex, Q.extended_nonzero,
|
255 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.irrational,
|
256 |
+
Q.nonzero, Q.real]), set([Q.composite, Q.even, Q.imaginary,
|
257 |
+
Q.infinite, Q.integer, Q.negative_infinite, Q.odd,
|
258 |
+
Q.positive_infinite, Q.prime, Q.rational, Q.zero])),
|
259 |
+
Q.is_true: (set([Q.is_true]), set([])),
|
260 |
+
Q.lower_triangular: (set([Q.lower_triangular, Q.triangular]), set([])),
|
261 |
+
Q.negative: (set([Q.commutative, Q.complex, Q.extended_negative,
|
262 |
+
Q.extended_nonpositive, Q.extended_nonzero, Q.extended_real,
|
263 |
+
Q.finite, Q.hermitian, Q.negative, Q.nonpositive, Q.nonzero,
|
264 |
+
Q.real]), set([Q.composite, Q.extended_nonnegative,
|
265 |
+
Q.extended_positive, Q.imaginary, Q.infinite,
|
266 |
+
Q.negative_infinite, Q.nonnegative, Q.positive,
|
267 |
+
Q.positive_infinite, Q.prime, Q.zero])),
|
268 |
+
Q.negative_infinite: (set([Q.commutative, Q.extended_negative,
|
269 |
+
Q.extended_nonpositive, Q.extended_nonzero, Q.extended_real,
|
270 |
+
Q.infinite, Q.negative_infinite]), set([Q.algebraic,
|
271 |
+
Q.complex, Q.composite, Q.even, Q.extended_nonnegative,
|
272 |
+
Q.extended_positive, Q.finite, Q.imaginary, Q.integer,
|
273 |
+
Q.irrational, Q.negative, Q.nonnegative, Q.nonpositive,
|
274 |
+
Q.nonzero, Q.odd, Q.positive, Q.positive_infinite, Q.prime,
|
275 |
+
Q.rational, Q.real, Q.transcendental, Q.zero])),
|
276 |
+
Q.noninteger: (set([Q.noninteger]), set([])),
|
277 |
+
Q.nonnegative: (set([Q.commutative, Q.complex, Q.extended_nonnegative,
|
278 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.nonnegative,
|
279 |
+
Q.real]), set([Q.extended_negative, Q.imaginary, Q.infinite,
|
280 |
+
Q.negative, Q.negative_infinite, Q.positive_infinite])),
|
281 |
+
Q.nonpositive: (set([Q.commutative, Q.complex, Q.extended_nonpositive,
|
282 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.nonpositive,
|
283 |
+
Q.real]), set([Q.composite, Q.extended_positive, Q.imaginary,
|
284 |
+
Q.infinite, Q.negative_infinite, Q.positive,
|
285 |
+
Q.positive_infinite, Q.prime])),
|
286 |
+
Q.nonzero: (set([Q.commutative, Q.complex, Q.extended_nonzero,
|
287 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.nonzero, Q.real]),
|
288 |
+
set([Q.imaginary, Q.infinite, Q.negative_infinite,
|
289 |
+
Q.positive_infinite, Q.zero])),
|
290 |
+
Q.normal: (set([Q.normal, Q.square]), set([])),
|
291 |
+
Q.odd: (set([Q.algebraic, Q.commutative, Q.complex,
|
292 |
+
Q.extended_nonzero, Q.extended_real, Q.finite, Q.hermitian,
|
293 |
+
Q.integer, Q.nonzero, Q.odd, Q.rational, Q.real]),
|
294 |
+
set([Q.even, Q.imaginary, Q.infinite, Q.irrational,
|
295 |
+
Q.negative_infinite, Q.positive_infinite, Q.transcendental,
|
296 |
+
Q.zero])),
|
297 |
+
Q.orthogonal: (set([Q.fullrank, Q.invertible, Q.normal, Q.orthogonal,
|
298 |
+
Q.positive_definite, Q.square, Q.unitary]), set([Q.singular])),
|
299 |
+
Q.positive: (set([Q.commutative, Q.complex, Q.extended_nonnegative,
|
300 |
+
Q.extended_nonzero, Q.extended_positive, Q.extended_real,
|
301 |
+
Q.finite, Q.hermitian, Q.nonnegative, Q.nonzero, Q.positive,
|
302 |
+
Q.real]), set([Q.extended_negative, Q.extended_nonpositive,
|
303 |
+
Q.imaginary, Q.infinite, Q.negative, Q.negative_infinite,
|
304 |
+
Q.nonpositive, Q.positive_infinite, Q.zero])),
|
305 |
+
Q.positive_definite: (set([Q.fullrank, Q.invertible,
|
306 |
+
Q.positive_definite, Q.square]), set([Q.singular])),
|
307 |
+
Q.positive_infinite: (set([Q.commutative, Q.extended_nonnegative,
|
308 |
+
Q.extended_nonzero, Q.extended_positive, Q.extended_real,
|
309 |
+
Q.infinite, Q.positive_infinite]), set([Q.algebraic,
|
310 |
+
Q.complex, Q.composite, Q.even, Q.extended_negative,
|
311 |
+
Q.extended_nonpositive, Q.finite, Q.imaginary, Q.integer,
|
312 |
+
Q.irrational, Q.negative, Q.negative_infinite, Q.nonnegative,
|
313 |
+
Q.nonpositive, Q.nonzero, Q.odd, Q.positive, Q.prime,
|
314 |
+
Q.rational, Q.real, Q.transcendental, Q.zero])),
|
315 |
+
Q.prime: (set([Q.algebraic, Q.commutative, Q.complex,
|
316 |
+
Q.extended_nonnegative, Q.extended_nonzero,
|
317 |
+
Q.extended_positive, Q.extended_real, Q.finite, Q.hermitian,
|
318 |
+
Q.integer, Q.nonnegative, Q.nonzero, Q.positive, Q.prime,
|
319 |
+
Q.rational, Q.real]), set([Q.composite, Q.extended_negative,
|
320 |
+
Q.extended_nonpositive, Q.imaginary, Q.infinite, Q.irrational,
|
321 |
+
Q.negative, Q.negative_infinite, Q.nonpositive,
|
322 |
+
Q.positive_infinite, Q.transcendental, Q.zero])),
|
323 |
+
Q.rational: (set([Q.algebraic, Q.commutative, Q.complex,
|
324 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.rational, Q.real]),
|
325 |
+
set([Q.imaginary, Q.infinite, Q.irrational,
|
326 |
+
Q.negative_infinite, Q.positive_infinite, Q.transcendental])),
|
327 |
+
Q.real: (set([Q.commutative, Q.complex, Q.extended_real, Q.finite,
|
328 |
+
Q.hermitian, Q.real]), set([Q.imaginary, Q.infinite,
|
329 |
+
Q.negative_infinite, Q.positive_infinite])),
|
330 |
+
Q.real_elements: (set([Q.complex_elements, Q.real_elements]), set([])),
|
331 |
+
Q.singular: (set([Q.singular]), set([Q.invertible, Q.orthogonal,
|
332 |
+
Q.positive_definite, Q.unitary])),
|
333 |
+
Q.square: (set([Q.square]), set([])),
|
334 |
+
Q.symmetric: (set([Q.square, Q.symmetric]), set([])),
|
335 |
+
Q.transcendental: (set([Q.commutative, Q.complex, Q.finite,
|
336 |
+
Q.transcendental]), set([Q.algebraic, Q.composite, Q.even,
|
337 |
+
Q.infinite, Q.integer, Q.negative_infinite, Q.odd,
|
338 |
+
Q.positive_infinite, Q.prime, Q.rational, Q.zero])),
|
339 |
+
Q.triangular: (set([Q.triangular]), set([])),
|
340 |
+
Q.unit_triangular: (set([Q.triangular, Q.unit_triangular]), set([])),
|
341 |
+
Q.unitary: (set([Q.fullrank, Q.invertible, Q.normal, Q.square,
|
342 |
+
Q.unitary]), set([Q.singular])),
|
343 |
+
Q.upper_triangular: (set([Q.triangular, Q.upper_triangular]), set([])),
|
344 |
+
Q.zero: (set([Q.algebraic, Q.commutative, Q.complex, Q.even,
|
345 |
+
Q.extended_nonnegative, Q.extended_nonpositive,
|
346 |
+
Q.extended_real, Q.finite, Q.hermitian, Q.integer,
|
347 |
+
Q.nonnegative, Q.nonpositive, Q.rational, Q.real, Q.zero]),
|
348 |
+
set([Q.composite, Q.extended_negative, Q.extended_nonzero,
|
349 |
+
Q.extended_positive, Q.imaginary, Q.infinite, Q.irrational,
|
350 |
+
Q.negative, Q.negative_infinite, Q.nonzero, Q.odd, Q.positive,
|
351 |
+
Q.positive_infinite, Q.prime, Q.transcendental])),
|
352 |
+
}
|
MLPY/Lib/site-packages/sympy/assumptions/assume.py
ADDED
@@ -0,0 +1,485 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""A module which implements predicates and assumption context."""
|
2 |
+
|
3 |
+
from contextlib import contextmanager
|
4 |
+
import inspect
|
5 |
+
from sympy.core.symbol import Str
|
6 |
+
from sympy.core.sympify import _sympify
|
7 |
+
from sympy.logic.boolalg import Boolean, false, true
|
8 |
+
from sympy.multipledispatch.dispatcher import Dispatcher, str_signature
|
9 |
+
from sympy.utilities.exceptions import sympy_deprecation_warning
|
10 |
+
from sympy.utilities.iterables import is_sequence
|
11 |
+
from sympy.utilities.source import get_class
|
12 |
+
|
13 |
+
|
14 |
+
class AssumptionsContext(set):
|
15 |
+
"""
|
16 |
+
Set containing default assumptions which are applied to the ``ask()``
|
17 |
+
function.
|
18 |
+
|
19 |
+
Explanation
|
20 |
+
===========
|
21 |
+
|
22 |
+
This is used to represent global assumptions, but you can also use this
|
23 |
+
class to create your own local assumptions contexts. It is basically a thin
|
24 |
+
wrapper to Python's set, so see its documentation for advanced usage.
|
25 |
+
|
26 |
+
Examples
|
27 |
+
========
|
28 |
+
|
29 |
+
The default assumption context is ``global_assumptions``, which is initially empty:
|
30 |
+
|
31 |
+
>>> from sympy import ask, Q
|
32 |
+
>>> from sympy.assumptions import global_assumptions
|
33 |
+
>>> global_assumptions
|
34 |
+
AssumptionsContext()
|
35 |
+
|
36 |
+
You can add default assumptions:
|
37 |
+
|
38 |
+
>>> from sympy.abc import x
|
39 |
+
>>> global_assumptions.add(Q.real(x))
|
40 |
+
>>> global_assumptions
|
41 |
+
AssumptionsContext({Q.real(x)})
|
42 |
+
>>> ask(Q.real(x))
|
43 |
+
True
|
44 |
+
|
45 |
+
And remove them:
|
46 |
+
|
47 |
+
>>> global_assumptions.remove(Q.real(x))
|
48 |
+
>>> print(ask(Q.real(x)))
|
49 |
+
None
|
50 |
+
|
51 |
+
The ``clear()`` method removes every assumption:
|
52 |
+
|
53 |
+
>>> global_assumptions.add(Q.positive(x))
|
54 |
+
>>> global_assumptions
|
55 |
+
AssumptionsContext({Q.positive(x)})
|
56 |
+
>>> global_assumptions.clear()
|
57 |
+
>>> global_assumptions
|
58 |
+
AssumptionsContext()
|
59 |
+
|
60 |
+
See Also
|
61 |
+
========
|
62 |
+
|
63 |
+
assuming
|
64 |
+
|
65 |
+
"""
|
66 |
+
|
67 |
+
def add(self, *assumptions):
|
68 |
+
"""Add assumptions."""
|
69 |
+
for a in assumptions:
|
70 |
+
super().add(a)
|
71 |
+
|
72 |
+
def _sympystr(self, printer):
|
73 |
+
if not self:
|
74 |
+
return "%s()" % self.__class__.__name__
|
75 |
+
return "{}({})".format(self.__class__.__name__, printer._print_set(self))
|
76 |
+
|
77 |
+
global_assumptions = AssumptionsContext()
|
78 |
+
|
79 |
+
|
80 |
+
class AppliedPredicate(Boolean):
|
81 |
+
"""
|
82 |
+
The class of expressions resulting from applying ``Predicate`` to
|
83 |
+
the arguments. ``AppliedPredicate`` merely wraps its argument and
|
84 |
+
remain unevaluated. To evaluate it, use the ``ask()`` function.
|
85 |
+
|
86 |
+
Examples
|
87 |
+
========
|
88 |
+
|
89 |
+
>>> from sympy import Q, ask
|
90 |
+
>>> Q.integer(1)
|
91 |
+
Q.integer(1)
|
92 |
+
|
93 |
+
The ``function`` attribute returns the predicate, and the ``arguments``
|
94 |
+
attribute returns the tuple of arguments.
|
95 |
+
|
96 |
+
>>> type(Q.integer(1))
|
97 |
+
<class 'sympy.assumptions.assume.AppliedPredicate'>
|
98 |
+
>>> Q.integer(1).function
|
99 |
+
Q.integer
|
100 |
+
>>> Q.integer(1).arguments
|
101 |
+
(1,)
|
102 |
+
|
103 |
+
Applied predicates can be evaluated to a boolean value with ``ask``:
|
104 |
+
|
105 |
+
>>> ask(Q.integer(1))
|
106 |
+
True
|
107 |
+
|
108 |
+
"""
|
109 |
+
__slots__ = ()
|
110 |
+
|
111 |
+
def __new__(cls, predicate, *args):
|
112 |
+
if not isinstance(predicate, Predicate):
|
113 |
+
raise TypeError("%s is not a Predicate." % predicate)
|
114 |
+
args = map(_sympify, args)
|
115 |
+
return super().__new__(cls, predicate, *args)
|
116 |
+
|
117 |
+
@property
|
118 |
+
def arg(self):
|
119 |
+
"""
|
120 |
+
Return the expression used by this assumption.
|
121 |
+
|
122 |
+
Examples
|
123 |
+
========
|
124 |
+
|
125 |
+
>>> from sympy import Q, Symbol
|
126 |
+
>>> x = Symbol('x')
|
127 |
+
>>> a = Q.integer(x + 1)
|
128 |
+
>>> a.arg
|
129 |
+
x + 1
|
130 |
+
|
131 |
+
"""
|
132 |
+
# Will be deprecated
|
133 |
+
args = self._args
|
134 |
+
if len(args) == 2:
|
135 |
+
# backwards compatibility
|
136 |
+
return args[1]
|
137 |
+
raise TypeError("'arg' property is allowed only for unary predicates.")
|
138 |
+
|
139 |
+
@property
|
140 |
+
def function(self):
|
141 |
+
"""
|
142 |
+
Return the predicate.
|
143 |
+
"""
|
144 |
+
# Will be changed to self.args[0] after args overriding is removed
|
145 |
+
return self._args[0]
|
146 |
+
|
147 |
+
@property
|
148 |
+
def arguments(self):
|
149 |
+
"""
|
150 |
+
Return the arguments which are applied to the predicate.
|
151 |
+
"""
|
152 |
+
# Will be changed to self.args[1:] after args overriding is removed
|
153 |
+
return self._args[1:]
|
154 |
+
|
155 |
+
def _eval_ask(self, assumptions):
|
156 |
+
return self.function.eval(self.arguments, assumptions)
|
157 |
+
|
158 |
+
@property
|
159 |
+
def binary_symbols(self):
|
160 |
+
from .ask import Q
|
161 |
+
if self.function == Q.is_true:
|
162 |
+
i = self.arguments[0]
|
163 |
+
if i.is_Boolean or i.is_Symbol:
|
164 |
+
return i.binary_symbols
|
165 |
+
if self.function in (Q.eq, Q.ne):
|
166 |
+
if true in self.arguments or false in self.arguments:
|
167 |
+
if self.arguments[0].is_Symbol:
|
168 |
+
return {self.arguments[0]}
|
169 |
+
elif self.arguments[1].is_Symbol:
|
170 |
+
return {self.arguments[1]}
|
171 |
+
return set()
|
172 |
+
|
173 |
+
|
174 |
+
class PredicateMeta(type):
|
175 |
+
def __new__(cls, clsname, bases, dct):
|
176 |
+
# If handler is not defined, assign empty dispatcher.
|
177 |
+
if "handler" not in dct:
|
178 |
+
name = f"Ask{clsname.capitalize()}Handler"
|
179 |
+
handler = Dispatcher(name, doc="Handler for key %s" % name)
|
180 |
+
dct["handler"] = handler
|
181 |
+
|
182 |
+
dct["_orig_doc"] = dct.get("__doc__", "")
|
183 |
+
|
184 |
+
return super().__new__(cls, clsname, bases, dct)
|
185 |
+
|
186 |
+
@property
|
187 |
+
def __doc__(cls):
|
188 |
+
handler = cls.handler
|
189 |
+
doc = cls._orig_doc
|
190 |
+
if cls is not Predicate and handler is not None:
|
191 |
+
doc += "Handler\n"
|
192 |
+
doc += " =======\n\n"
|
193 |
+
|
194 |
+
# Append the handler's doc without breaking sphinx documentation.
|
195 |
+
docs = [" Multiply dispatched method: %s" % handler.name]
|
196 |
+
if handler.doc:
|
197 |
+
for line in handler.doc.splitlines():
|
198 |
+
if not line:
|
199 |
+
continue
|
200 |
+
docs.append(" %s" % line)
|
201 |
+
other = []
|
202 |
+
for sig in handler.ordering[::-1]:
|
203 |
+
func = handler.funcs[sig]
|
204 |
+
if func.__doc__:
|
205 |
+
s = ' Inputs: <%s>' % str_signature(sig)
|
206 |
+
lines = []
|
207 |
+
for line in func.__doc__.splitlines():
|
208 |
+
lines.append(" %s" % line)
|
209 |
+
s += "\n".join(lines)
|
210 |
+
docs.append(s)
|
211 |
+
else:
|
212 |
+
other.append(str_signature(sig))
|
213 |
+
if other:
|
214 |
+
othersig = " Other signatures:"
|
215 |
+
for line in other:
|
216 |
+
othersig += "\n * %s" % line
|
217 |
+
docs.append(othersig)
|
218 |
+
|
219 |
+
doc += '\n\n'.join(docs)
|
220 |
+
|
221 |
+
return doc
|
222 |
+
|
223 |
+
|
224 |
+
class Predicate(Boolean, metaclass=PredicateMeta):
|
225 |
+
"""
|
226 |
+
Base class for mathematical predicates. It also serves as a
|
227 |
+
constructor for undefined predicate objects.
|
228 |
+
|
229 |
+
Explanation
|
230 |
+
===========
|
231 |
+
|
232 |
+
Predicate is a function that returns a boolean value [1].
|
233 |
+
|
234 |
+
Predicate function is object, and it is instance of predicate class.
|
235 |
+
When a predicate is applied to arguments, ``AppliedPredicate``
|
236 |
+
instance is returned. This merely wraps the argument and remain
|
237 |
+
unevaluated. To obtain the truth value of applied predicate, use the
|
238 |
+
function ``ask``.
|
239 |
+
|
240 |
+
Evaluation of predicate is done by multiple dispatching. You can
|
241 |
+
register new handler to the predicate to support new types.
|
242 |
+
|
243 |
+
Every predicate in SymPy can be accessed via the property of ``Q``.
|
244 |
+
For example, ``Q.even`` returns the predicate which checks if the
|
245 |
+
argument is even number.
|
246 |
+
|
247 |
+
To define a predicate which can be evaluated, you must subclass this
|
248 |
+
class, make an instance of it, and register it to ``Q``. After then,
|
249 |
+
dispatch the handler by argument types.
|
250 |
+
|
251 |
+
If you directly construct predicate using this class, you will get
|
252 |
+
``UndefinedPredicate`` which cannot be dispatched. This is useful
|
253 |
+
when you are building boolean expressions which do not need to be
|
254 |
+
evaluated.
|
255 |
+
|
256 |
+
Examples
|
257 |
+
========
|
258 |
+
|
259 |
+
Applying and evaluating to boolean value:
|
260 |
+
|
261 |
+
>>> from sympy import Q, ask
|
262 |
+
>>> ask(Q.prime(7))
|
263 |
+
True
|
264 |
+
|
265 |
+
You can define a new predicate by subclassing and dispatching. Here,
|
266 |
+
we define a predicate for sexy primes [2] as an example.
|
267 |
+
|
268 |
+
>>> from sympy import Predicate, Integer
|
269 |
+
>>> class SexyPrimePredicate(Predicate):
|
270 |
+
... name = "sexyprime"
|
271 |
+
>>> Q.sexyprime = SexyPrimePredicate()
|
272 |
+
>>> @Q.sexyprime.register(Integer, Integer)
|
273 |
+
... def _(int1, int2, assumptions):
|
274 |
+
... args = sorted([int1, int2])
|
275 |
+
... if not all(ask(Q.prime(a), assumptions) for a in args):
|
276 |
+
... return False
|
277 |
+
... return args[1] - args[0] == 6
|
278 |
+
>>> ask(Q.sexyprime(5, 11))
|
279 |
+
True
|
280 |
+
|
281 |
+
Direct constructing returns ``UndefinedPredicate``, which can be
|
282 |
+
applied but cannot be dispatched.
|
283 |
+
|
284 |
+
>>> from sympy import Predicate, Integer
|
285 |
+
>>> Q.P = Predicate("P")
|
286 |
+
>>> type(Q.P)
|
287 |
+
<class 'sympy.assumptions.assume.UndefinedPredicate'>
|
288 |
+
>>> Q.P(1)
|
289 |
+
Q.P(1)
|
290 |
+
>>> Q.P.register(Integer)(lambda expr, assump: True)
|
291 |
+
Traceback (most recent call last):
|
292 |
+
...
|
293 |
+
TypeError: <class 'sympy.assumptions.assume.UndefinedPredicate'> cannot be dispatched.
|
294 |
+
|
295 |
+
References
|
296 |
+
==========
|
297 |
+
|
298 |
+
.. [1] https://en.wikipedia.org/wiki/Predicate_%28mathematical_logic%29
|
299 |
+
.. [2] https://en.wikipedia.org/wiki/Sexy_prime
|
300 |
+
|
301 |
+
"""
|
302 |
+
|
303 |
+
is_Atom = True
|
304 |
+
|
305 |
+
def __new__(cls, *args, **kwargs):
|
306 |
+
if cls is Predicate:
|
307 |
+
return UndefinedPredicate(*args, **kwargs)
|
308 |
+
obj = super().__new__(cls, *args)
|
309 |
+
return obj
|
310 |
+
|
311 |
+
@property
|
312 |
+
def name(self):
|
313 |
+
# May be overridden
|
314 |
+
return type(self).__name__
|
315 |
+
|
316 |
+
@classmethod
|
317 |
+
def register(cls, *types, **kwargs):
|
318 |
+
"""
|
319 |
+
Register the signature to the handler.
|
320 |
+
"""
|
321 |
+
if cls.handler is None:
|
322 |
+
raise TypeError("%s cannot be dispatched." % type(cls))
|
323 |
+
return cls.handler.register(*types, **kwargs)
|
324 |
+
|
325 |
+
@classmethod
|
326 |
+
def register_many(cls, *types, **kwargs):
|
327 |
+
"""
|
328 |
+
Register multiple signatures to same handler.
|
329 |
+
"""
|
330 |
+
def _(func):
|
331 |
+
for t in types:
|
332 |
+
if not is_sequence(t):
|
333 |
+
t = (t,) # for convenience, allow passing `type` to mean `(type,)`
|
334 |
+
cls.register(*t, **kwargs)(func)
|
335 |
+
return _
|
336 |
+
|
337 |
+
def __call__(self, *args):
|
338 |
+
return AppliedPredicate(self, *args)
|
339 |
+
|
340 |
+
def eval(self, args, assumptions=True):
|
341 |
+
"""
|
342 |
+
Evaluate ``self(*args)`` under the given assumptions.
|
343 |
+
|
344 |
+
This uses only direct resolution methods, not logical inference.
|
345 |
+
"""
|
346 |
+
result = None
|
347 |
+
try:
|
348 |
+
result = self.handler(*args, assumptions=assumptions)
|
349 |
+
except NotImplementedError:
|
350 |
+
pass
|
351 |
+
return result
|
352 |
+
|
353 |
+
def _eval_refine(self, assumptions):
|
354 |
+
# When Predicate is no longer Boolean, delete this method
|
355 |
+
return self
|
356 |
+
|
357 |
+
|
358 |
+
class UndefinedPredicate(Predicate):
|
359 |
+
"""
|
360 |
+
Predicate without handler.
|
361 |
+
|
362 |
+
Explanation
|
363 |
+
===========
|
364 |
+
|
365 |
+
This predicate is generated by using ``Predicate`` directly for
|
366 |
+
construction. It does not have a handler, and evaluating this with
|
367 |
+
arguments is done by SAT solver.
|
368 |
+
|
369 |
+
Examples
|
370 |
+
========
|
371 |
+
|
372 |
+
>>> from sympy import Predicate, Q
|
373 |
+
>>> Q.P = Predicate('P')
|
374 |
+
>>> Q.P.func
|
375 |
+
<class 'sympy.assumptions.assume.UndefinedPredicate'>
|
376 |
+
>>> Q.P.name
|
377 |
+
Str('P')
|
378 |
+
|
379 |
+
"""
|
380 |
+
|
381 |
+
handler = None
|
382 |
+
|
383 |
+
def __new__(cls, name, handlers=None):
|
384 |
+
# "handlers" parameter supports old design
|
385 |
+
if not isinstance(name, Str):
|
386 |
+
name = Str(name)
|
387 |
+
obj = super(Boolean, cls).__new__(cls, name)
|
388 |
+
obj.handlers = handlers or []
|
389 |
+
return obj
|
390 |
+
|
391 |
+
@property
|
392 |
+
def name(self):
|
393 |
+
return self.args[0]
|
394 |
+
|
395 |
+
def _hashable_content(self):
|
396 |
+
return (self.name,)
|
397 |
+
|
398 |
+
def __getnewargs__(self):
|
399 |
+
return (self.name,)
|
400 |
+
|
401 |
+
def __call__(self, expr):
|
402 |
+
return AppliedPredicate(self, expr)
|
403 |
+
|
404 |
+
def add_handler(self, handler):
|
405 |
+
sympy_deprecation_warning(
|
406 |
+
"""
|
407 |
+
The AskHandler system is deprecated. Predicate.add_handler()
|
408 |
+
should be replaced with the multipledispatch handler of Predicate.
|
409 |
+
""",
|
410 |
+
deprecated_since_version="1.8",
|
411 |
+
active_deprecations_target='deprecated-askhandler',
|
412 |
+
)
|
413 |
+
self.handlers.append(handler)
|
414 |
+
|
415 |
+
def remove_handler(self, handler):
|
416 |
+
sympy_deprecation_warning(
|
417 |
+
"""
|
418 |
+
The AskHandler system is deprecated. Predicate.remove_handler()
|
419 |
+
should be replaced with the multipledispatch handler of Predicate.
|
420 |
+
""",
|
421 |
+
deprecated_since_version="1.8",
|
422 |
+
active_deprecations_target='deprecated-askhandler',
|
423 |
+
)
|
424 |
+
self.handlers.remove(handler)
|
425 |
+
|
426 |
+
def eval(self, args, assumptions=True):
|
427 |
+
# Support for deprecated design
|
428 |
+
# When old design is removed, this will always return None
|
429 |
+
sympy_deprecation_warning(
|
430 |
+
"""
|
431 |
+
The AskHandler system is deprecated. Evaluating UndefinedPredicate
|
432 |
+
objects should be replaced with the multipledispatch handler of
|
433 |
+
Predicate.
|
434 |
+
""",
|
435 |
+
deprecated_since_version="1.8",
|
436 |
+
active_deprecations_target='deprecated-askhandler',
|
437 |
+
stacklevel=5,
|
438 |
+
)
|
439 |
+
expr, = args
|
440 |
+
res, _res = None, None
|
441 |
+
mro = inspect.getmro(type(expr))
|
442 |
+
for handler in self.handlers:
|
443 |
+
cls = get_class(handler)
|
444 |
+
for subclass in mro:
|
445 |
+
eval_ = getattr(cls, subclass.__name__, None)
|
446 |
+
if eval_ is None:
|
447 |
+
continue
|
448 |
+
res = eval_(expr, assumptions)
|
449 |
+
# Do not stop if value returned is None
|
450 |
+
# Try to check for higher classes
|
451 |
+
if res is None:
|
452 |
+
continue
|
453 |
+
if _res is None:
|
454 |
+
_res = res
|
455 |
+
else:
|
456 |
+
# only check consistency if both resolutors have concluded
|
457 |
+
if _res != res:
|
458 |
+
raise ValueError('incompatible resolutors')
|
459 |
+
break
|
460 |
+
return res
|
461 |
+
|
462 |
+
|
463 |
+
@contextmanager
|
464 |
+
def assuming(*assumptions):
|
465 |
+
"""
|
466 |
+
Context manager for assumptions.
|
467 |
+
|
468 |
+
Examples
|
469 |
+
========
|
470 |
+
|
471 |
+
>>> from sympy import assuming, Q, ask
|
472 |
+
>>> from sympy.abc import x, y
|
473 |
+
>>> print(ask(Q.integer(x + y)))
|
474 |
+
None
|
475 |
+
>>> with assuming(Q.integer(x), Q.integer(y)):
|
476 |
+
... print(ask(Q.integer(x + y)))
|
477 |
+
True
|
478 |
+
"""
|
479 |
+
old_global_assumptions = global_assumptions.copy()
|
480 |
+
global_assumptions.update(assumptions)
|
481 |
+
try:
|
482 |
+
yield
|
483 |
+
finally:
|
484 |
+
global_assumptions.clear()
|
485 |
+
global_assumptions.update(old_global_assumptions)
|
MLPY/Lib/site-packages/sympy/assumptions/cnf.py
ADDED
@@ -0,0 +1,445 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
The classes used here are for the internal use of assumptions system
|
3 |
+
only and should not be used anywhere else as these do not possess the
|
4 |
+
signatures common to SymPy objects. For general use of logic constructs
|
5 |
+
please refer to sympy.logic classes And, Or, Not, etc.
|
6 |
+
"""
|
7 |
+
from itertools import combinations, product, zip_longest
|
8 |
+
from sympy.assumptions.assume import AppliedPredicate, Predicate
|
9 |
+
from sympy.core.relational import Eq, Ne, Gt, Lt, Ge, Le
|
10 |
+
from sympy.core.singleton import S
|
11 |
+
from sympy.logic.boolalg import Or, And, Not, Xnor
|
12 |
+
from sympy.logic.boolalg import (Equivalent, ITE, Implies, Nand, Nor, Xor)
|
13 |
+
|
14 |
+
|
15 |
+
class Literal:
|
16 |
+
"""
|
17 |
+
The smallest element of a CNF object.
|
18 |
+
|
19 |
+
Parameters
|
20 |
+
==========
|
21 |
+
|
22 |
+
lit : Boolean expression
|
23 |
+
|
24 |
+
is_Not : bool
|
25 |
+
|
26 |
+
Examples
|
27 |
+
========
|
28 |
+
|
29 |
+
>>> from sympy import Q
|
30 |
+
>>> from sympy.assumptions.cnf import Literal
|
31 |
+
>>> from sympy.abc import x
|
32 |
+
>>> Literal(Q.even(x))
|
33 |
+
Literal(Q.even(x), False)
|
34 |
+
>>> Literal(~Q.even(x))
|
35 |
+
Literal(Q.even(x), True)
|
36 |
+
"""
|
37 |
+
|
38 |
+
def __new__(cls, lit, is_Not=False):
|
39 |
+
if isinstance(lit, Not):
|
40 |
+
lit = lit.args[0]
|
41 |
+
is_Not = True
|
42 |
+
elif isinstance(lit, (AND, OR, Literal)):
|
43 |
+
return ~lit if is_Not else lit
|
44 |
+
obj = super().__new__(cls)
|
45 |
+
obj.lit = lit
|
46 |
+
obj.is_Not = is_Not
|
47 |
+
return obj
|
48 |
+
|
49 |
+
@property
|
50 |
+
def arg(self):
|
51 |
+
return self.lit
|
52 |
+
|
53 |
+
def rcall(self, expr):
|
54 |
+
if callable(self.lit):
|
55 |
+
lit = self.lit(expr)
|
56 |
+
else:
|
57 |
+
lit = self.lit.apply(expr)
|
58 |
+
return type(self)(lit, self.is_Not)
|
59 |
+
|
60 |
+
def __invert__(self):
|
61 |
+
is_Not = not self.is_Not
|
62 |
+
return Literal(self.lit, is_Not)
|
63 |
+
|
64 |
+
def __str__(self):
|
65 |
+
return '{}({}, {})'.format(type(self).__name__, self.lit, self.is_Not)
|
66 |
+
|
67 |
+
__repr__ = __str__
|
68 |
+
|
69 |
+
def __eq__(self, other):
|
70 |
+
return self.arg == other.arg and self.is_Not == other.is_Not
|
71 |
+
|
72 |
+
def __hash__(self):
|
73 |
+
h = hash((type(self).__name__, self.arg, self.is_Not))
|
74 |
+
return h
|
75 |
+
|
76 |
+
|
77 |
+
class OR:
|
78 |
+
"""
|
79 |
+
A low-level implementation for Or
|
80 |
+
"""
|
81 |
+
def __init__(self, *args):
|
82 |
+
self._args = args
|
83 |
+
|
84 |
+
@property
|
85 |
+
def args(self):
|
86 |
+
return sorted(self._args, key=str)
|
87 |
+
|
88 |
+
def rcall(self, expr):
|
89 |
+
return type(self)(*[arg.rcall(expr)
|
90 |
+
for arg in self._args
|
91 |
+
])
|
92 |
+
|
93 |
+
def __invert__(self):
|
94 |
+
return AND(*[~arg for arg in self._args])
|
95 |
+
|
96 |
+
def __hash__(self):
|
97 |
+
return hash((type(self).__name__,) + tuple(self.args))
|
98 |
+
|
99 |
+
def __eq__(self, other):
|
100 |
+
return self.args == other.args
|
101 |
+
|
102 |
+
def __str__(self):
|
103 |
+
s = '(' + ' | '.join([str(arg) for arg in self.args]) + ')'
|
104 |
+
return s
|
105 |
+
|
106 |
+
__repr__ = __str__
|
107 |
+
|
108 |
+
|
109 |
+
class AND:
|
110 |
+
"""
|
111 |
+
A low-level implementation for And
|
112 |
+
"""
|
113 |
+
def __init__(self, *args):
|
114 |
+
self._args = args
|
115 |
+
|
116 |
+
def __invert__(self):
|
117 |
+
return OR(*[~arg for arg in self._args])
|
118 |
+
|
119 |
+
@property
|
120 |
+
def args(self):
|
121 |
+
return sorted(self._args, key=str)
|
122 |
+
|
123 |
+
def rcall(self, expr):
|
124 |
+
return type(self)(*[arg.rcall(expr)
|
125 |
+
for arg in self._args
|
126 |
+
])
|
127 |
+
|
128 |
+
def __hash__(self):
|
129 |
+
return hash((type(self).__name__,) + tuple(self.args))
|
130 |
+
|
131 |
+
def __eq__(self, other):
|
132 |
+
return self.args == other.args
|
133 |
+
|
134 |
+
def __str__(self):
|
135 |
+
s = '('+' & '.join([str(arg) for arg in self.args])+')'
|
136 |
+
return s
|
137 |
+
|
138 |
+
__repr__ = __str__
|
139 |
+
|
140 |
+
|
141 |
+
def to_NNF(expr, composite_map=None):
|
142 |
+
"""
|
143 |
+
Generates the Negation Normal Form of any boolean expression in terms
|
144 |
+
of AND, OR, and Literal objects.
|
145 |
+
|
146 |
+
Examples
|
147 |
+
========
|
148 |
+
|
149 |
+
>>> from sympy import Q, Eq
|
150 |
+
>>> from sympy.assumptions.cnf import to_NNF
|
151 |
+
>>> from sympy.abc import x, y
|
152 |
+
>>> expr = Q.even(x) & ~Q.positive(x)
|
153 |
+
>>> to_NNF(expr)
|
154 |
+
(Literal(Q.even(x), False) & Literal(Q.positive(x), True))
|
155 |
+
|
156 |
+
Supported boolean objects are converted to corresponding predicates.
|
157 |
+
|
158 |
+
>>> to_NNF(Eq(x, y))
|
159 |
+
Literal(Q.eq(x, y), False)
|
160 |
+
|
161 |
+
If ``composite_map`` argument is given, ``to_NNF`` decomposes the
|
162 |
+
specified predicate into a combination of primitive predicates.
|
163 |
+
|
164 |
+
>>> cmap = {Q.nonpositive: Q.negative | Q.zero}
|
165 |
+
>>> to_NNF(Q.nonpositive, cmap)
|
166 |
+
(Literal(Q.negative, False) | Literal(Q.zero, False))
|
167 |
+
>>> to_NNF(Q.nonpositive(x), cmap)
|
168 |
+
(Literal(Q.negative(x), False) | Literal(Q.zero(x), False))
|
169 |
+
"""
|
170 |
+
from sympy.assumptions.ask import Q
|
171 |
+
|
172 |
+
if composite_map is None:
|
173 |
+
composite_map = {}
|
174 |
+
|
175 |
+
|
176 |
+
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le}
|
177 |
+
if type(expr) in binrelpreds:
|
178 |
+
pred = binrelpreds[type(expr)]
|
179 |
+
expr = pred(*expr.args)
|
180 |
+
|
181 |
+
if isinstance(expr, Not):
|
182 |
+
arg = expr.args[0]
|
183 |
+
tmp = to_NNF(arg, composite_map) # Strategy: negate the NNF of expr
|
184 |
+
return ~tmp
|
185 |
+
|
186 |
+
if isinstance(expr, Or):
|
187 |
+
return OR(*[to_NNF(x, composite_map) for x in Or.make_args(expr)])
|
188 |
+
|
189 |
+
if isinstance(expr, And):
|
190 |
+
return AND(*[to_NNF(x, composite_map) for x in And.make_args(expr)])
|
191 |
+
|
192 |
+
if isinstance(expr, Nand):
|
193 |
+
tmp = AND(*[to_NNF(x, composite_map) for x in expr.args])
|
194 |
+
return ~tmp
|
195 |
+
|
196 |
+
if isinstance(expr, Nor):
|
197 |
+
tmp = OR(*[to_NNF(x, composite_map) for x in expr.args])
|
198 |
+
return ~tmp
|
199 |
+
|
200 |
+
if isinstance(expr, Xor):
|
201 |
+
cnfs = []
|
202 |
+
for i in range(0, len(expr.args) + 1, 2):
|
203 |
+
for neg in combinations(expr.args, i):
|
204 |
+
clause = [~to_NNF(s, composite_map) if s in neg else to_NNF(s, composite_map)
|
205 |
+
for s in expr.args]
|
206 |
+
cnfs.append(OR(*clause))
|
207 |
+
return AND(*cnfs)
|
208 |
+
|
209 |
+
if isinstance(expr, Xnor):
|
210 |
+
cnfs = []
|
211 |
+
for i in range(0, len(expr.args) + 1, 2):
|
212 |
+
for neg in combinations(expr.args, i):
|
213 |
+
clause = [~to_NNF(s, composite_map) if s in neg else to_NNF(s, composite_map)
|
214 |
+
for s in expr.args]
|
215 |
+
cnfs.append(OR(*clause))
|
216 |
+
return ~AND(*cnfs)
|
217 |
+
|
218 |
+
if isinstance(expr, Implies):
|
219 |
+
L, R = to_NNF(expr.args[0], composite_map), to_NNF(expr.args[1], composite_map)
|
220 |
+
return OR(~L, R)
|
221 |
+
|
222 |
+
if isinstance(expr, Equivalent):
|
223 |
+
cnfs = []
|
224 |
+
for a, b in zip_longest(expr.args, expr.args[1:], fillvalue=expr.args[0]):
|
225 |
+
a = to_NNF(a, composite_map)
|
226 |
+
b = to_NNF(b, composite_map)
|
227 |
+
cnfs.append(OR(~a, b))
|
228 |
+
return AND(*cnfs)
|
229 |
+
|
230 |
+
if isinstance(expr, ITE):
|
231 |
+
L = to_NNF(expr.args[0], composite_map)
|
232 |
+
M = to_NNF(expr.args[1], composite_map)
|
233 |
+
R = to_NNF(expr.args[2], composite_map)
|
234 |
+
return AND(OR(~L, M), OR(L, R))
|
235 |
+
|
236 |
+
if isinstance(expr, AppliedPredicate):
|
237 |
+
pred, args = expr.function, expr.arguments
|
238 |
+
newpred = composite_map.get(pred, None)
|
239 |
+
if newpred is not None:
|
240 |
+
return to_NNF(newpred.rcall(*args), composite_map)
|
241 |
+
|
242 |
+
if isinstance(expr, Predicate):
|
243 |
+
newpred = composite_map.get(expr, None)
|
244 |
+
if newpred is not None:
|
245 |
+
return to_NNF(newpred, composite_map)
|
246 |
+
|
247 |
+
return Literal(expr)
|
248 |
+
|
249 |
+
|
250 |
+
def distribute_AND_over_OR(expr):
|
251 |
+
"""
|
252 |
+
Distributes AND over OR in the NNF expression.
|
253 |
+
Returns the result( Conjunctive Normal Form of expression)
|
254 |
+
as a CNF object.
|
255 |
+
"""
|
256 |
+
if not isinstance(expr, (AND, OR)):
|
257 |
+
tmp = set()
|
258 |
+
tmp.add(frozenset((expr,)))
|
259 |
+
return CNF(tmp)
|
260 |
+
|
261 |
+
if isinstance(expr, OR):
|
262 |
+
return CNF.all_or(*[distribute_AND_over_OR(arg)
|
263 |
+
for arg in expr._args])
|
264 |
+
|
265 |
+
if isinstance(expr, AND):
|
266 |
+
return CNF.all_and(*[distribute_AND_over_OR(arg)
|
267 |
+
for arg in expr._args])
|
268 |
+
|
269 |
+
|
270 |
+
class CNF:
|
271 |
+
"""
|
272 |
+
Class to represent CNF of a Boolean expression.
|
273 |
+
Consists of set of clauses, which themselves are stored as
|
274 |
+
frozenset of Literal objects.
|
275 |
+
|
276 |
+
Examples
|
277 |
+
========
|
278 |
+
|
279 |
+
>>> from sympy import Q
|
280 |
+
>>> from sympy.assumptions.cnf import CNF
|
281 |
+
>>> from sympy.abc import x
|
282 |
+
>>> cnf = CNF.from_prop(Q.real(x) & ~Q.zero(x))
|
283 |
+
>>> cnf.clauses
|
284 |
+
{frozenset({Literal(Q.zero(x), True)}),
|
285 |
+
frozenset({Literal(Q.negative(x), False),
|
286 |
+
Literal(Q.positive(x), False), Literal(Q.zero(x), False)})}
|
287 |
+
"""
|
288 |
+
def __init__(self, clauses=None):
|
289 |
+
if not clauses:
|
290 |
+
clauses = set()
|
291 |
+
self.clauses = clauses
|
292 |
+
|
293 |
+
def add(self, prop):
|
294 |
+
clauses = CNF.to_CNF(prop).clauses
|
295 |
+
self.add_clauses(clauses)
|
296 |
+
|
297 |
+
def __str__(self):
|
298 |
+
s = ' & '.join(
|
299 |
+
['(' + ' | '.join([str(lit) for lit in clause]) +')'
|
300 |
+
for clause in self.clauses]
|
301 |
+
)
|
302 |
+
return s
|
303 |
+
|
304 |
+
def extend(self, props):
|
305 |
+
for p in props:
|
306 |
+
self.add(p)
|
307 |
+
return self
|
308 |
+
|
309 |
+
def copy(self):
|
310 |
+
return CNF(set(self.clauses))
|
311 |
+
|
312 |
+
def add_clauses(self, clauses):
|
313 |
+
self.clauses |= clauses
|
314 |
+
|
315 |
+
@classmethod
|
316 |
+
def from_prop(cls, prop):
|
317 |
+
res = cls()
|
318 |
+
res.add(prop)
|
319 |
+
return res
|
320 |
+
|
321 |
+
def __iand__(self, other):
|
322 |
+
self.add_clauses(other.clauses)
|
323 |
+
return self
|
324 |
+
|
325 |
+
def all_predicates(self):
|
326 |
+
predicates = set()
|
327 |
+
for c in self.clauses:
|
328 |
+
predicates |= {arg.lit for arg in c}
|
329 |
+
return predicates
|
330 |
+
|
331 |
+
def _or(self, cnf):
|
332 |
+
clauses = set()
|
333 |
+
for a, b in product(self.clauses, cnf.clauses):
|
334 |
+
tmp = set(a)
|
335 |
+
tmp.update(b)
|
336 |
+
clauses.add(frozenset(tmp))
|
337 |
+
return CNF(clauses)
|
338 |
+
|
339 |
+
def _and(self, cnf):
|
340 |
+
clauses = self.clauses.union(cnf.clauses)
|
341 |
+
return CNF(clauses)
|
342 |
+
|
343 |
+
def _not(self):
|
344 |
+
clss = list(self.clauses)
|
345 |
+
ll = {frozenset((~x,)) for x in clss[-1]}
|
346 |
+
ll = CNF(ll)
|
347 |
+
|
348 |
+
for rest in clss[:-1]:
|
349 |
+
p = {frozenset((~x,)) for x in rest}
|
350 |
+
ll = ll._or(CNF(p))
|
351 |
+
return ll
|
352 |
+
|
353 |
+
def rcall(self, expr):
|
354 |
+
clause_list = []
|
355 |
+
for clause in self.clauses:
|
356 |
+
lits = [arg.rcall(expr) for arg in clause]
|
357 |
+
clause_list.append(OR(*lits))
|
358 |
+
expr = AND(*clause_list)
|
359 |
+
return distribute_AND_over_OR(expr)
|
360 |
+
|
361 |
+
@classmethod
|
362 |
+
def all_or(cls, *cnfs):
|
363 |
+
b = cnfs[0].copy()
|
364 |
+
for rest in cnfs[1:]:
|
365 |
+
b = b._or(rest)
|
366 |
+
return b
|
367 |
+
|
368 |
+
@classmethod
|
369 |
+
def all_and(cls, *cnfs):
|
370 |
+
b = cnfs[0].copy()
|
371 |
+
for rest in cnfs[1:]:
|
372 |
+
b = b._and(rest)
|
373 |
+
return b
|
374 |
+
|
375 |
+
@classmethod
|
376 |
+
def to_CNF(cls, expr):
|
377 |
+
from sympy.assumptions.facts import get_composite_predicates
|
378 |
+
expr = to_NNF(expr, get_composite_predicates())
|
379 |
+
expr = distribute_AND_over_OR(expr)
|
380 |
+
return expr
|
381 |
+
|
382 |
+
@classmethod
|
383 |
+
def CNF_to_cnf(cls, cnf):
|
384 |
+
"""
|
385 |
+
Converts CNF object to SymPy's boolean expression
|
386 |
+
retaining the form of expression.
|
387 |
+
"""
|
388 |
+
def remove_literal(arg):
|
389 |
+
return Not(arg.lit) if arg.is_Not else arg.lit
|
390 |
+
|
391 |
+
return And(*(Or(*(remove_literal(arg) for arg in clause)) for clause in cnf.clauses))
|
392 |
+
|
393 |
+
|
394 |
+
class EncodedCNF:
|
395 |
+
"""
|
396 |
+
Class for encoding the CNF expression.
|
397 |
+
"""
|
398 |
+
def __init__(self, data=None, encoding=None):
|
399 |
+
if not data and not encoding:
|
400 |
+
data = []
|
401 |
+
encoding = {}
|
402 |
+
self.data = data
|
403 |
+
self.encoding = encoding
|
404 |
+
self._symbols = list(encoding.keys())
|
405 |
+
|
406 |
+
def from_cnf(self, cnf):
|
407 |
+
self._symbols = list(cnf.all_predicates())
|
408 |
+
n = len(self._symbols)
|
409 |
+
self.encoding = dict(zip(self._symbols, range(1, n + 1)))
|
410 |
+
self.data = [self.encode(clause) for clause in cnf.clauses]
|
411 |
+
|
412 |
+
@property
|
413 |
+
def symbols(self):
|
414 |
+
return self._symbols
|
415 |
+
|
416 |
+
@property
|
417 |
+
def variables(self):
|
418 |
+
return range(1, len(self._symbols) + 1)
|
419 |
+
|
420 |
+
def copy(self):
|
421 |
+
new_data = [set(clause) for clause in self.data]
|
422 |
+
return EncodedCNF(new_data, dict(self.encoding))
|
423 |
+
|
424 |
+
def add_prop(self, prop):
|
425 |
+
cnf = CNF.from_prop(prop)
|
426 |
+
self.add_from_cnf(cnf)
|
427 |
+
|
428 |
+
def add_from_cnf(self, cnf):
|
429 |
+
clauses = [self.encode(clause) for clause in cnf.clauses]
|
430 |
+
self.data += clauses
|
431 |
+
|
432 |
+
def encode_arg(self, arg):
|
433 |
+
literal = arg.lit
|
434 |
+
value = self.encoding.get(literal, None)
|
435 |
+
if value is None:
|
436 |
+
n = len(self._symbols)
|
437 |
+
self._symbols.append(literal)
|
438 |
+
value = self.encoding[literal] = n + 1
|
439 |
+
if arg.is_Not:
|
440 |
+
return -value
|
441 |
+
else:
|
442 |
+
return value
|
443 |
+
|
444 |
+
def encode(self, clause):
|
445 |
+
return {self.encode_arg(arg) if not arg.lit == S.false else 0 for arg in clause}
|
MLPY/Lib/site-packages/sympy/assumptions/facts.py
ADDED
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Known facts in assumptions module.
|
3 |
+
|
4 |
+
This module defines the facts between unary predicates in ``get_known_facts()``,
|
5 |
+
and supports functions to generate the contents in
|
6 |
+
``sympy.assumptions.ask_generated`` file.
|
7 |
+
"""
|
8 |
+
|
9 |
+
from sympy.assumptions.ask import Q
|
10 |
+
from sympy.assumptions.assume import AppliedPredicate
|
11 |
+
from sympy.core.cache import cacheit
|
12 |
+
from sympy.core.symbol import Symbol
|
13 |
+
from sympy.logic.boolalg import (to_cnf, And, Not, Implies, Equivalent,
|
14 |
+
Exclusive,)
|
15 |
+
from sympy.logic.inference import satisfiable
|
16 |
+
|
17 |
+
|
18 |
+
@cacheit
|
19 |
+
def get_composite_predicates():
|
20 |
+
# To reduce the complexity of sat solver, these predicates are
|
21 |
+
# transformed into the combination of primitive predicates.
|
22 |
+
return {
|
23 |
+
Q.real : Q.negative | Q.zero | Q.positive,
|
24 |
+
Q.integer : Q.even | Q.odd,
|
25 |
+
Q.nonpositive : Q.negative | Q.zero,
|
26 |
+
Q.nonzero : Q.negative | Q.positive,
|
27 |
+
Q.nonnegative : Q.zero | Q.positive,
|
28 |
+
Q.extended_real : Q.negative_infinite | Q.negative | Q.zero | Q.positive | Q.positive_infinite,
|
29 |
+
Q.extended_positive: Q.positive | Q.positive_infinite,
|
30 |
+
Q.extended_negative: Q.negative | Q.negative_infinite,
|
31 |
+
Q.extended_nonzero: Q.negative_infinite | Q.negative | Q.positive | Q.positive_infinite,
|
32 |
+
Q.extended_nonpositive: Q.negative_infinite | Q.negative | Q.zero,
|
33 |
+
Q.extended_nonnegative: Q.zero | Q.positive | Q.positive_infinite,
|
34 |
+
Q.complex : Q.algebraic | Q.transcendental
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
@cacheit
|
39 |
+
def get_known_facts(x=None):
|
40 |
+
"""
|
41 |
+
Facts between unary predicates.
|
42 |
+
|
43 |
+
Parameters
|
44 |
+
==========
|
45 |
+
|
46 |
+
x : Symbol, optional
|
47 |
+
Placeholder symbol for unary facts. Default is ``Symbol('x')``.
|
48 |
+
|
49 |
+
Returns
|
50 |
+
=======
|
51 |
+
|
52 |
+
fact : Known facts in conjugated normal form.
|
53 |
+
|
54 |
+
"""
|
55 |
+
if x is None:
|
56 |
+
x = Symbol('x')
|
57 |
+
|
58 |
+
fact = And(
|
59 |
+
get_number_facts(x),
|
60 |
+
get_matrix_facts(x)
|
61 |
+
)
|
62 |
+
return fact
|
63 |
+
|
64 |
+
|
65 |
+
@cacheit
|
66 |
+
def get_number_facts(x = None):
|
67 |
+
"""
|
68 |
+
Facts between unary number predicates.
|
69 |
+
|
70 |
+
Parameters
|
71 |
+
==========
|
72 |
+
|
73 |
+
x : Symbol, optional
|
74 |
+
Placeholder symbol for unary facts. Default is ``Symbol('x')``.
|
75 |
+
|
76 |
+
Returns
|
77 |
+
=======
|
78 |
+
|
79 |
+
fact : Known facts in conjugated normal form.
|
80 |
+
|
81 |
+
"""
|
82 |
+
if x is None:
|
83 |
+
x = Symbol('x')
|
84 |
+
|
85 |
+
fact = And(
|
86 |
+
# primitive predicates for extended real exclude each other.
|
87 |
+
Exclusive(Q.negative_infinite(x), Q.negative(x), Q.zero(x),
|
88 |
+
Q.positive(x), Q.positive_infinite(x)),
|
89 |
+
|
90 |
+
# build complex plane
|
91 |
+
Exclusive(Q.real(x), Q.imaginary(x)),
|
92 |
+
Implies(Q.real(x) | Q.imaginary(x), Q.complex(x)),
|
93 |
+
|
94 |
+
# other subsets of complex
|
95 |
+
Exclusive(Q.transcendental(x), Q.algebraic(x)),
|
96 |
+
Equivalent(Q.real(x), Q.rational(x) | Q.irrational(x)),
|
97 |
+
Exclusive(Q.irrational(x), Q.rational(x)),
|
98 |
+
Implies(Q.rational(x), Q.algebraic(x)),
|
99 |
+
|
100 |
+
# integers
|
101 |
+
Exclusive(Q.even(x), Q.odd(x)),
|
102 |
+
Implies(Q.integer(x), Q.rational(x)),
|
103 |
+
Implies(Q.zero(x), Q.even(x)),
|
104 |
+
Exclusive(Q.composite(x), Q.prime(x)),
|
105 |
+
Implies(Q.composite(x) | Q.prime(x), Q.integer(x) & Q.positive(x)),
|
106 |
+
Implies(Q.even(x) & Q.positive(x) & ~Q.prime(x), Q.composite(x)),
|
107 |
+
|
108 |
+
# hermitian and antihermitian
|
109 |
+
Implies(Q.real(x), Q.hermitian(x)),
|
110 |
+
Implies(Q.imaginary(x), Q.antihermitian(x)),
|
111 |
+
Implies(Q.zero(x), Q.hermitian(x) | Q.antihermitian(x)),
|
112 |
+
|
113 |
+
# define finity and infinity, and build extended real line
|
114 |
+
Exclusive(Q.infinite(x), Q.finite(x)),
|
115 |
+
Implies(Q.complex(x), Q.finite(x)),
|
116 |
+
Implies(Q.negative_infinite(x) | Q.positive_infinite(x), Q.infinite(x)),
|
117 |
+
|
118 |
+
# commutativity
|
119 |
+
Implies(Q.finite(x) | Q.infinite(x), Q.commutative(x)),
|
120 |
+
)
|
121 |
+
return fact
|
122 |
+
|
123 |
+
|
124 |
+
@cacheit
|
125 |
+
def get_matrix_facts(x = None):
|
126 |
+
"""
|
127 |
+
Facts between unary matrix predicates.
|
128 |
+
|
129 |
+
Parameters
|
130 |
+
==========
|
131 |
+
|
132 |
+
x : Symbol, optional
|
133 |
+
Placeholder symbol for unary facts. Default is ``Symbol('x')``.
|
134 |
+
|
135 |
+
Returns
|
136 |
+
=======
|
137 |
+
|
138 |
+
fact : Known facts in conjugated normal form.
|
139 |
+
|
140 |
+
"""
|
141 |
+
if x is None:
|
142 |
+
x = Symbol('x')
|
143 |
+
|
144 |
+
fact = And(
|
145 |
+
# matrices
|
146 |
+
Implies(Q.orthogonal(x), Q.positive_definite(x)),
|
147 |
+
Implies(Q.orthogonal(x), Q.unitary(x)),
|
148 |
+
Implies(Q.unitary(x) & Q.real_elements(x), Q.orthogonal(x)),
|
149 |
+
Implies(Q.unitary(x), Q.normal(x)),
|
150 |
+
Implies(Q.unitary(x), Q.invertible(x)),
|
151 |
+
Implies(Q.normal(x), Q.square(x)),
|
152 |
+
Implies(Q.diagonal(x), Q.normal(x)),
|
153 |
+
Implies(Q.positive_definite(x), Q.invertible(x)),
|
154 |
+
Implies(Q.diagonal(x), Q.upper_triangular(x)),
|
155 |
+
Implies(Q.diagonal(x), Q.lower_triangular(x)),
|
156 |
+
Implies(Q.lower_triangular(x), Q.triangular(x)),
|
157 |
+
Implies(Q.upper_triangular(x), Q.triangular(x)),
|
158 |
+
Implies(Q.triangular(x), Q.upper_triangular(x) | Q.lower_triangular(x)),
|
159 |
+
Implies(Q.upper_triangular(x) & Q.lower_triangular(x), Q.diagonal(x)),
|
160 |
+
Implies(Q.diagonal(x), Q.symmetric(x)),
|
161 |
+
Implies(Q.unit_triangular(x), Q.triangular(x)),
|
162 |
+
Implies(Q.invertible(x), Q.fullrank(x)),
|
163 |
+
Implies(Q.invertible(x), Q.square(x)),
|
164 |
+
Implies(Q.symmetric(x), Q.square(x)),
|
165 |
+
Implies(Q.fullrank(x) & Q.square(x), Q.invertible(x)),
|
166 |
+
Equivalent(Q.invertible(x), ~Q.singular(x)),
|
167 |
+
Implies(Q.integer_elements(x), Q.real_elements(x)),
|
168 |
+
Implies(Q.real_elements(x), Q.complex_elements(x)),
|
169 |
+
)
|
170 |
+
return fact
|
171 |
+
|
172 |
+
|
173 |
+
|
174 |
+
def generate_known_facts_dict(keys, fact):
|
175 |
+
"""
|
176 |
+
Computes and returns a dictionary which contains the relations between
|
177 |
+
unary predicates.
|
178 |
+
|
179 |
+
Each key is a predicate, and item is two groups of predicates.
|
180 |
+
First group contains the predicates which are implied by the key, and
|
181 |
+
second group contains the predicates which are rejected by the key.
|
182 |
+
|
183 |
+
All predicates in *keys* and *fact* must be unary and have same placeholder
|
184 |
+
symbol.
|
185 |
+
|
186 |
+
Parameters
|
187 |
+
==========
|
188 |
+
|
189 |
+
keys : list of AppliedPredicate instances.
|
190 |
+
|
191 |
+
fact : Fact between predicates in conjugated normal form.
|
192 |
+
|
193 |
+
Examples
|
194 |
+
========
|
195 |
+
|
196 |
+
>>> from sympy import Q, And, Implies
|
197 |
+
>>> from sympy.assumptions.facts import generate_known_facts_dict
|
198 |
+
>>> from sympy.abc import x
|
199 |
+
>>> keys = [Q.even(x), Q.odd(x), Q.zero(x)]
|
200 |
+
>>> fact = And(Implies(Q.even(x), ~Q.odd(x)),
|
201 |
+
... Implies(Q.zero(x), Q.even(x)))
|
202 |
+
>>> generate_known_facts_dict(keys, fact)
|
203 |
+
{Q.even: ({Q.even}, {Q.odd}),
|
204 |
+
Q.odd: ({Q.odd}, {Q.even, Q.zero}),
|
205 |
+
Q.zero: ({Q.even, Q.zero}, {Q.odd})}
|
206 |
+
"""
|
207 |
+
fact_cnf = to_cnf(fact)
|
208 |
+
mapping = single_fact_lookup(keys, fact_cnf)
|
209 |
+
|
210 |
+
ret = {}
|
211 |
+
for key, value in mapping.items():
|
212 |
+
implied = set()
|
213 |
+
rejected = set()
|
214 |
+
for expr in value:
|
215 |
+
if isinstance(expr, AppliedPredicate):
|
216 |
+
implied.add(expr.function)
|
217 |
+
elif isinstance(expr, Not):
|
218 |
+
pred = expr.args[0]
|
219 |
+
rejected.add(pred.function)
|
220 |
+
ret[key.function] = (implied, rejected)
|
221 |
+
return ret
|
222 |
+
|
223 |
+
|
224 |
+
@cacheit
|
225 |
+
def get_known_facts_keys():
|
226 |
+
"""
|
227 |
+
Return every unary predicates registered to ``Q``.
|
228 |
+
|
229 |
+
This function is used to generate the keys for
|
230 |
+
``generate_known_facts_dict``.
|
231 |
+
|
232 |
+
"""
|
233 |
+
# exclude polyadic predicates
|
234 |
+
exclude = {Q.eq, Q.ne, Q.gt, Q.lt, Q.ge, Q.le}
|
235 |
+
|
236 |
+
result = []
|
237 |
+
for attr in Q.__class__.__dict__:
|
238 |
+
if attr.startswith('__'):
|
239 |
+
continue
|
240 |
+
pred = getattr(Q, attr)
|
241 |
+
if pred in exclude:
|
242 |
+
continue
|
243 |
+
result.append(pred)
|
244 |
+
return result
|
245 |
+
|
246 |
+
|
247 |
+
def single_fact_lookup(known_facts_keys, known_facts_cnf):
|
248 |
+
# Return the dictionary for quick lookup of single fact
|
249 |
+
mapping = {}
|
250 |
+
for key in known_facts_keys:
|
251 |
+
mapping[key] = {key}
|
252 |
+
for other_key in known_facts_keys:
|
253 |
+
if other_key != key:
|
254 |
+
if ask_full_inference(other_key, key, known_facts_cnf):
|
255 |
+
mapping[key].add(other_key)
|
256 |
+
if ask_full_inference(~other_key, key, known_facts_cnf):
|
257 |
+
mapping[key].add(~other_key)
|
258 |
+
return mapping
|
259 |
+
|
260 |
+
|
261 |
+
def ask_full_inference(proposition, assumptions, known_facts_cnf):
|
262 |
+
"""
|
263 |
+
Method for inferring properties about objects.
|
264 |
+
|
265 |
+
"""
|
266 |
+
if not satisfiable(And(known_facts_cnf, assumptions, proposition)):
|
267 |
+
return False
|
268 |
+
if not satisfiable(And(known_facts_cnf, assumptions, Not(proposition))):
|
269 |
+
return True
|
270 |
+
return None
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__init__.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Multipledispatch handlers for ``Predicate`` are implemented here.
|
3 |
+
Handlers in this module are not directly imported to other modules in
|
4 |
+
order to avoid circular import problem.
|
5 |
+
"""
|
6 |
+
|
7 |
+
from .common import (AskHandler, CommonHandler,
|
8 |
+
test_closed_group)
|
9 |
+
|
10 |
+
__all__ = [
|
11 |
+
'AskHandler', 'CommonHandler',
|
12 |
+
'test_closed_group'
|
13 |
+
]
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (469 Bytes). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/calculus.cpython-39.pyc
ADDED
Binary file (6.38 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/common.cpython-39.pyc
ADDED
Binary file (4.7 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/matrices.cpython-39.pyc
ADDED
Binary file (20.9 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/ntheory.cpython-39.pyc
ADDED
Binary file (6.19 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/order.cpython-39.pyc
ADDED
Binary file (10.7 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/__pycache__/sets.cpython-39.pyc
ADDED
Binary file (18.6 kB). View file
|
|
MLPY/Lib/site-packages/sympy/assumptions/handlers/calculus.py
ADDED
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
This module contains query handlers responsible for calculus queries:
|
3 |
+
infinitesimal, finite, etc.
|
4 |
+
"""
|
5 |
+
|
6 |
+
from sympy.assumptions import Q, ask
|
7 |
+
from sympy.core import Add, Mul, Pow, Symbol
|
8 |
+
from sympy.core.numbers import (NegativeInfinity, GoldenRatio,
|
9 |
+
Infinity, Exp1, ComplexInfinity, ImaginaryUnit, NaN, Number, Pi, E,
|
10 |
+
TribonacciConstant)
|
11 |
+
from sympy.functions import cos, exp, log, sign, sin
|
12 |
+
from sympy.logic.boolalg import conjuncts
|
13 |
+
|
14 |
+
from ..predicates.calculus import (FinitePredicate, InfinitePredicate,
|
15 |
+
PositiveInfinitePredicate, NegativeInfinitePredicate)
|
16 |
+
|
17 |
+
|
18 |
+
# FinitePredicate
|
19 |
+
|
20 |
+
|
21 |
+
@FinitePredicate.register(Symbol)
|
22 |
+
def _(expr, assumptions):
|
23 |
+
"""
|
24 |
+
Handles Symbol.
|
25 |
+
"""
|
26 |
+
if expr.is_finite is not None:
|
27 |
+
return expr.is_finite
|
28 |
+
if Q.finite(expr) in conjuncts(assumptions):
|
29 |
+
return True
|
30 |
+
return None
|
31 |
+
|
32 |
+
@FinitePredicate.register(Add)
|
33 |
+
def _(expr, assumptions):
|
34 |
+
"""
|
35 |
+
Return True if expr is bounded, False if not and None if unknown.
|
36 |
+
|
37 |
+
Truth Table:
|
38 |
+
|
39 |
+
+-------+-----+-----------+-----------+
|
40 |
+
| | | | |
|
41 |
+
| | B | U | ? |
|
42 |
+
| | | | |
|
43 |
+
+-------+-----+---+---+---+---+---+---+
|
44 |
+
| | | | | | | | |
|
45 |
+
| | |'+'|'-'|'x'|'+'|'-'|'x'|
|
46 |
+
| | | | | | | | |
|
47 |
+
+-------+-----+---+---+---+---+---+---+
|
48 |
+
| | | | |
|
49 |
+
| B | B | U | ? |
|
50 |
+
| | | | |
|
51 |
+
+---+---+-----+---+---+---+---+---+---+
|
52 |
+
| | | | | | | | | |
|
53 |
+
| |'+'| | U | ? | ? | U | ? | ? |
|
54 |
+
| | | | | | | | | |
|
55 |
+
| +---+-----+---+---+---+---+---+---+
|
56 |
+
| | | | | | | | | |
|
57 |
+
| U |'-'| | ? | U | ? | ? | U | ? |
|
58 |
+
| | | | | | | | | |
|
59 |
+
| +---+-----+---+---+---+---+---+---+
|
60 |
+
| | | | | |
|
61 |
+
| |'x'| | ? | ? |
|
62 |
+
| | | | | |
|
63 |
+
+---+---+-----+---+---+---+---+---+---+
|
64 |
+
| | | | |
|
65 |
+
| ? | | | ? |
|
66 |
+
| | | | |
|
67 |
+
+-------+-----+-----------+---+---+---+
|
68 |
+
|
69 |
+
* 'B' = Bounded
|
70 |
+
|
71 |
+
* 'U' = Unbounded
|
72 |
+
|
73 |
+
* '?' = unknown boundedness
|
74 |
+
|
75 |
+
* '+' = positive sign
|
76 |
+
|
77 |
+
* '-' = negative sign
|
78 |
+
|
79 |
+
* 'x' = sign unknown
|
80 |
+
|
81 |
+
* All Bounded -> True
|
82 |
+
|
83 |
+
* 1 Unbounded and the rest Bounded -> False
|
84 |
+
|
85 |
+
* >1 Unbounded, all with same known sign -> False
|
86 |
+
|
87 |
+
* Any Unknown and unknown sign -> None
|
88 |
+
|
89 |
+
* Else -> None
|
90 |
+
|
91 |
+
When the signs are not the same you can have an undefined
|
92 |
+
result as in oo - oo, hence 'bounded' is also undefined.
|
93 |
+
"""
|
94 |
+
sign = -1 # sign of unknown or infinite
|
95 |
+
result = True
|
96 |
+
for arg in expr.args:
|
97 |
+
_bounded = ask(Q.finite(arg), assumptions)
|
98 |
+
if _bounded:
|
99 |
+
continue
|
100 |
+
s = ask(Q.extended_positive(arg), assumptions)
|
101 |
+
# if there has been more than one sign or if the sign of this arg
|
102 |
+
# is None and Bounded is None or there was already
|
103 |
+
# an unknown sign, return None
|
104 |
+
if sign != -1 and s != sign or \
|
105 |
+
s is None and None in (_bounded, sign):
|
106 |
+
return None
|
107 |
+
else:
|
108 |
+
sign = s
|
109 |
+
# once False, do not change
|
110 |
+
if result is not False:
|
111 |
+
result = _bounded
|
112 |
+
return result
|
113 |
+
|
114 |
+
@FinitePredicate.register(Mul)
|
115 |
+
def _(expr, assumptions):
|
116 |
+
"""
|
117 |
+
Return True if expr is bounded, False if not and None if unknown.
|
118 |
+
|
119 |
+
Truth Table:
|
120 |
+
|
121 |
+
+---+---+---+--------+
|
122 |
+
| | | | |
|
123 |
+
| | B | U | ? |
|
124 |
+
| | | | |
|
125 |
+
+---+---+---+---+----+
|
126 |
+
| | | | | |
|
127 |
+
| | | | s | /s |
|
128 |
+
| | | | | |
|
129 |
+
+---+---+---+---+----+
|
130 |
+
| | | | |
|
131 |
+
| B | B | U | ? |
|
132 |
+
| | | | |
|
133 |
+
+---+---+---+---+----+
|
134 |
+
| | | | | |
|
135 |
+
| U | | U | U | ? |
|
136 |
+
| | | | | |
|
137 |
+
+---+---+---+---+----+
|
138 |
+
| | | | |
|
139 |
+
| ? | | | ? |
|
140 |
+
| | | | |
|
141 |
+
+---+---+---+---+----+
|
142 |
+
|
143 |
+
* B = Bounded
|
144 |
+
|
145 |
+
* U = Unbounded
|
146 |
+
|
147 |
+
* ? = unknown boundedness
|
148 |
+
|
149 |
+
* s = signed (hence nonzero)
|
150 |
+
|
151 |
+
* /s = not signed
|
152 |
+
"""
|
153 |
+
result = True
|
154 |
+
for arg in expr.args:
|
155 |
+
_bounded = ask(Q.finite(arg), assumptions)
|
156 |
+
if _bounded:
|
157 |
+
continue
|
158 |
+
elif _bounded is None:
|
159 |
+
if result is None:
|
160 |
+
return None
|
161 |
+
if ask(Q.extended_nonzero(arg), assumptions) is None:
|
162 |
+
return None
|
163 |
+
if result is not False:
|
164 |
+
result = None
|
165 |
+
else:
|
166 |
+
result = False
|
167 |
+
return result
|
168 |
+
|
169 |
+
@FinitePredicate.register(Pow)
|
170 |
+
def _(expr, assumptions):
|
171 |
+
"""
|
172 |
+
* Unbounded ** NonZero -> Unbounded
|
173 |
+
|
174 |
+
* Bounded ** Bounded -> Bounded
|
175 |
+
|
176 |
+
* Abs()<=1 ** Positive -> Bounded
|
177 |
+
|
178 |
+
* Abs()>=1 ** Negative -> Bounded
|
179 |
+
|
180 |
+
* Otherwise unknown
|
181 |
+
"""
|
182 |
+
if expr.base == E:
|
183 |
+
return ask(Q.finite(expr.exp), assumptions)
|
184 |
+
|
185 |
+
base_bounded = ask(Q.finite(expr.base), assumptions)
|
186 |
+
exp_bounded = ask(Q.finite(expr.exp), assumptions)
|
187 |
+
if base_bounded is None and exp_bounded is None: # Common Case
|
188 |
+
return None
|
189 |
+
if base_bounded is False and ask(Q.extended_nonzero(expr.exp), assumptions):
|
190 |
+
return False
|
191 |
+
if base_bounded and exp_bounded:
|
192 |
+
return True
|
193 |
+
if (abs(expr.base) <= 1) == True and ask(Q.extended_positive(expr.exp), assumptions):
|
194 |
+
return True
|
195 |
+
if (abs(expr.base) >= 1) == True and ask(Q.extended_negative(expr.exp), assumptions):
|
196 |
+
return True
|
197 |
+
if (abs(expr.base) >= 1) == True and exp_bounded is False:
|
198 |
+
return False
|
199 |
+
return None
|
200 |
+
|
201 |
+
@FinitePredicate.register(exp)
|
202 |
+
def _(expr, assumptions):
|
203 |
+
return ask(Q.finite(expr.exp), assumptions)
|
204 |
+
|
205 |
+
@FinitePredicate.register(log)
|
206 |
+
def _(expr, assumptions):
|
207 |
+
# After complex -> finite fact is registered to new assumption system,
|
208 |
+
# querying Q.infinite may be removed.
|
209 |
+
if ask(Q.infinite(expr.args[0]), assumptions):
|
210 |
+
return False
|
211 |
+
return ask(~Q.zero(expr.args[0]), assumptions)
|
212 |
+
|
213 |
+
@FinitePredicate.register_many(cos, sin, Number, Pi, Exp1, GoldenRatio,
|
214 |
+
TribonacciConstant, ImaginaryUnit, sign)
|
215 |
+
def _(expr, assumptions):
|
216 |
+
return True
|
217 |
+
|
218 |
+
@FinitePredicate.register_many(ComplexInfinity, Infinity, NegativeInfinity)
|
219 |
+
def _(expr, assumptions):
|
220 |
+
return False
|
221 |
+
|
222 |
+
@FinitePredicate.register(NaN)
|
223 |
+
def _(expr, assumptions):
|
224 |
+
return None
|
225 |
+
|
226 |
+
|
227 |
+
# InfinitePredicate
|
228 |
+
|
229 |
+
|
230 |
+
@InfinitePredicate.register_many(ComplexInfinity, Infinity, NegativeInfinity)
|
231 |
+
def _(expr, assumptions):
|
232 |
+
return True
|
233 |
+
|
234 |
+
|
235 |
+
# PositiveInfinitePredicate
|
236 |
+
|
237 |
+
|
238 |
+
@PositiveInfinitePredicate.register(Infinity)
|
239 |
+
def _(expr, assumptions):
|
240 |
+
return True
|
241 |
+
|
242 |
+
|
243 |
+
@PositiveInfinitePredicate.register_many(NegativeInfinity, ComplexInfinity)
|
244 |
+
def _(expr, assumptions):
|
245 |
+
return False
|
246 |
+
|
247 |
+
|
248 |
+
# NegativeInfinitePredicate
|
249 |
+
|
250 |
+
|
251 |
+
@NegativeInfinitePredicate.register(NegativeInfinity)
|
252 |
+
def _(expr, assumptions):
|
253 |
+
return True
|
254 |
+
|
255 |
+
|
256 |
+
@NegativeInfinitePredicate.register_many(Infinity, ComplexInfinity)
|
257 |
+
def _(expr, assumptions):
|
258 |
+
return False
|