Instructions to use dl1wjd2/Logistics_AX with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use dl1wjd2/Logistics_AX with ultralytics:
from huggingface_hub import hf_hub_download from ultralytics import YOLO # pick the weights file from this repo's "Files and versions" tab weights = hf_hub_download("dl1wjd2/Logistics_AX", "<weights>.pt") model = YOLO(weights) source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
Upload folder using huggingface_hub (part 20)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +35 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/INSTALLER +1 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/METADATA +319 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/RECORD +0 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/WHEEL +5 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/entry_points.txt +2 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/AUTHORS +1379 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/LICENSE +153 -0
- hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/top_level.txt +2 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/sample_scipy.py +167 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__init__.py +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_continuous_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_discrete_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_finite_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_continuous_rv.py +181 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_discrete_rv.py +109 -0
- hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_finite_rv.py +94 -0
- hug/lib/python3.12/site-packages/sympy/stats/stochastic_process.py +66 -0
- hug/lib/python3.12/site-packages/sympy/stats/stochastic_process_types.py +2383 -0
- hug/lib/python3.12/site-packages/sympy/stats/symbolic_multivariate_probability.py +308 -0
- hug/lib/python3.12/site-packages/sympy/stats/symbolic_probability.py +698 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__init__.py +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_compound_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_continuous_rv.cpython-312.pyc +3 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_discrete_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_error_prop.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_finite_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_joint_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_matrix_distributions.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_mix.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_random_matrix.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_rv.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_stochastic_process.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_multivariate.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_probability.cpython-312.pyc +0 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_compound_rv.py +159 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_continuous_rv.py +1583 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_discrete_rv.py +312 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_error_prop.py +60 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_finite_rv.py +509 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_joint_rv.py +436 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_matrix_distributions.py +186 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_mix.py +82 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_random_matrix.py +135 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_rv.py +441 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_stochastic_process.py +763 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_symbolic_multivariate.py +172 -0
- hug/lib/python3.12/site-packages/sympy/stats/tests/test_symbolic_probability.py +175 -0
.gitattributes
CHANGED
|
@@ -382,3 +382,38 @@ hug/lib/python3.12/site-packages/sympy/solvers/tests/__pycache__/test_solvers.cp
|
|
| 382 |
hug/lib/python3.12/site-packages/sympy/solvers/tests/__pycache__/test_solveset.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 383 |
hug/lib/python3.12/site-packages/sympy/stats/__pycache__/crv_types.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 384 |
hug/lib/python3.12/site-packages/sympy/stats/__pycache__/stochastic_process_types.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
hug/lib/python3.12/site-packages/sympy/solvers/tests/__pycache__/test_solveset.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 383 |
hug/lib/python3.12/site-packages/sympy/stats/__pycache__/crv_types.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 384 |
hug/lib/python3.12/site-packages/sympy/stats/__pycache__/stochastic_process_types.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 385 |
+
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_continuous_rv.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 386 |
+
hug/lib/python3.12/site-packages/sympy/tensor/__pycache__/tensor.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 387 |
+
hug/lib/python3.12/site-packages/sympy/tensor/array/expressions/__pycache__/array_expressions.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 388 |
+
hug/lib/python3.12/site-packages/sympy/tensor/tests/__pycache__/test_tensor.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 389 |
+
hug/lib/python3.12/site-packages/sympy/utilities/__pycache__/iterables.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 390 |
+
hug/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_lambdify.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 391 |
+
hug/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_wester.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 392 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/__init__.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 393 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/_meta_registrations.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 394 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/_precompile.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 395 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/_tensor_docs.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 396 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/_torch_docs.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 397 |
+
hug/lib/python3.12/site-packages/torch/__pycache__/overrides.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 398 |
+
hug/lib/python3.12/site-packages/torch/_decomp/__pycache__/decompositions.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 399 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/aot_compile.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 400 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/convert_frame.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 401 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/eval_frame.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 402 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/guards.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 403 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/output_graph.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 404 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/symbolic_convert.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 405 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/trace_rules.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 406 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/__pycache__/utils.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 407 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/base.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 408 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/builder.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 409 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/builtin.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 410 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/functions.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 411 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/higher_order_ops.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 412 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/lists.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 413 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/misc.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 414 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/tensor.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 415 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/torch.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 416 |
+
hug/lib/python3.12/site-packages/torch/_dynamo/variables/__pycache__/user_defined.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 417 |
+
hug/lib/python3.12/site-packages/torch/_export/serde/__pycache__/serialize.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 418 |
+
hug/lib/python3.12/site-packages/torch/_functorch/__pycache__/partitioners.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
| 419 |
+
hug/lib/python3.12/site-packages/torch/_functorch/_aot_autograd/__pycache__/runtime_wrappers.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: sympy
|
| 3 |
+
Version: 1.14.0
|
| 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.9
|
| 19 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 23 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
| 24 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 25 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 26 |
+
Requires-Python: >=3.9
|
| 27 |
+
Description-Content-Type: text/markdown
|
| 28 |
+
License-File: LICENSE
|
| 29 |
+
License-File: AUTHORS
|
| 30 |
+
Requires-Dist: mpmath<1.4,>=1.1.0
|
| 31 |
+
Provides-Extra: dev
|
| 32 |
+
Requires-Dist: pytest>=7.1.0; extra == "dev"
|
| 33 |
+
Requires-Dist: hypothesis>=6.70.0; extra == "dev"
|
| 34 |
+
Dynamic: author
|
| 35 |
+
Dynamic: author-email
|
| 36 |
+
Dynamic: classifier
|
| 37 |
+
Dynamic: description
|
| 38 |
+
Dynamic: description-content-type
|
| 39 |
+
Dynamic: home-page
|
| 40 |
+
Dynamic: keywords
|
| 41 |
+
Dynamic: license
|
| 42 |
+
Dynamic: license-file
|
| 43 |
+
Dynamic: project-url
|
| 44 |
+
Dynamic: provides-extra
|
| 45 |
+
Dynamic: requires-dist
|
| 46 |
+
Dynamic: requires-python
|
| 47 |
+
Dynamic: summary
|
| 48 |
+
|
| 49 |
+
# SymPy
|
| 50 |
+
|
| 51 |
+
[](https://pypi.python.org/pypi/sympy)
|
| 52 |
+
[](https://gitter.im/sympy/sympy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
| 53 |
+
[](https://zenodo.org/badge/latestdoi/18918/sympy/sympy)
|
| 54 |
+
[](https://pepy.tech/project/sympy)
|
| 55 |
+
[](https://github.com/sympy/sympy/issues)
|
| 56 |
+
[](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project)
|
| 57 |
+
[](https://numfocus.org)
|
| 58 |
+
[](https://github.com/sympy/sympy/releases)
|
| 59 |
+
|
| 60 |
+
[](https://sympy.org/)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
See the [AUTHORS](AUTHORS) file for the list of authors.
|
| 64 |
+
|
| 65 |
+
And many more people helped on the SymPy mailing list, reported bugs,
|
| 66 |
+
helped organize SymPy's participation in the Google Summer of Code, the
|
| 67 |
+
Google Highly Open Participation Contest, Google Code-In, wrote and
|
| 68 |
+
blogged about SymPy...
|
| 69 |
+
|
| 70 |
+
License: New BSD License (see the [LICENSE](LICENSE) file for details) covers all
|
| 71 |
+
files in the sympy repository unless stated otherwise.
|
| 72 |
+
|
| 73 |
+
Our mailing list is at
|
| 74 |
+
<https://groups.google.com/forum/?fromgroups#!forum/sympy>.
|
| 75 |
+
|
| 76 |
+
We have a community chat at [Gitter](https://gitter.im/sympy/sympy). Feel
|
| 77 |
+
free to ask us anything there. We have a very welcoming and helpful
|
| 78 |
+
community.
|
| 79 |
+
|
| 80 |
+
## Download
|
| 81 |
+
|
| 82 |
+
The recommended installation method is through Anaconda,
|
| 83 |
+
<https://www.anaconda.com/products/distribution>
|
| 84 |
+
|
| 85 |
+
You can also get the latest version of SymPy from
|
| 86 |
+
<https://pypi.python.org/pypi/sympy/>
|
| 87 |
+
|
| 88 |
+
To get the git version do
|
| 89 |
+
|
| 90 |
+
$ git clone https://github.com/sympy/sympy.git
|
| 91 |
+
|
| 92 |
+
For other options (tarballs, debs, etc.), see
|
| 93 |
+
<https://docs.sympy.org/dev/install.html>.
|
| 94 |
+
|
| 95 |
+
## Documentation and Usage
|
| 96 |
+
|
| 97 |
+
For in-depth instructions on installation and building the
|
| 98 |
+
documentation, see the [SymPy Documentation Style Guide](https://docs.sympy.org/dev/documentation-style-guide.html).
|
| 99 |
+
|
| 100 |
+
Everything is at:
|
| 101 |
+
|
| 102 |
+
<https://docs.sympy.org/>
|
| 103 |
+
|
| 104 |
+
You can generate everything at the above site in your local copy of
|
| 105 |
+
SymPy by:
|
| 106 |
+
|
| 107 |
+
$ cd doc
|
| 108 |
+
$ make html
|
| 109 |
+
|
| 110 |
+
Then the docs will be in <span class="title-ref">\_build/html</span>. If
|
| 111 |
+
you don't want to read that, here is a short usage:
|
| 112 |
+
|
| 113 |
+
From this directory, start Python and:
|
| 114 |
+
|
| 115 |
+
``` python
|
| 116 |
+
>>> from sympy import Symbol, cos
|
| 117 |
+
>>> x = Symbol('x')
|
| 118 |
+
>>> e = 1/cos(x)
|
| 119 |
+
>>> print(e.series(x, 0, 10))
|
| 120 |
+
1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
SymPy also comes with a console that is a simple wrapper around the
|
| 124 |
+
classic python console (or IPython when available) that loads the SymPy
|
| 125 |
+
namespace and executes some common commands for you.
|
| 126 |
+
|
| 127 |
+
To start it, issue:
|
| 128 |
+
|
| 129 |
+
$ bin/isympy
|
| 130 |
+
|
| 131 |
+
from this directory, if SymPy is not installed or simply:
|
| 132 |
+
|
| 133 |
+
$ isympy
|
| 134 |
+
|
| 135 |
+
if SymPy is installed.
|
| 136 |
+
|
| 137 |
+
## Installation
|
| 138 |
+
|
| 139 |
+
To install SymPy using PyPI, run the following command:
|
| 140 |
+
|
| 141 |
+
$ pip install sympy
|
| 142 |
+
|
| 143 |
+
To install SymPy using Anaconda, run the following command:
|
| 144 |
+
|
| 145 |
+
$ conda install -c anaconda sympy
|
| 146 |
+
|
| 147 |
+
To install SymPy from GitHub source, first clone SymPy using `git`:
|
| 148 |
+
|
| 149 |
+
$ git clone https://github.com/sympy/sympy.git
|
| 150 |
+
|
| 151 |
+
Then, in the `sympy` repository that you cloned, simply run:
|
| 152 |
+
|
| 153 |
+
$ pip install .
|
| 154 |
+
|
| 155 |
+
See <https://docs.sympy.org/dev/install.html> for more information.
|
| 156 |
+
|
| 157 |
+
## Contributing
|
| 158 |
+
|
| 159 |
+
We welcome contributions from anyone, even if you are new to open
|
| 160 |
+
source. Please read our [Introduction to Contributing](https://docs.sympy.org/dev/contributing/introduction-to-contributing.html)
|
| 161 |
+
page and the [SymPy Documentation Style Guide](https://docs.sympy.org/dev/documentation-style-guide.html). If you
|
| 162 |
+
are new and looking for some way to contribute, a good place to start is
|
| 163 |
+
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).
|
| 164 |
+
|
| 165 |
+
Please note that all participants in this project are expected to follow
|
| 166 |
+
our Code of Conduct. By participating in this project you agree to abide
|
| 167 |
+
by its terms. See [CODE\_OF\_CONDUCT.md](CODE_OF_CONDUCT.md).
|
| 168 |
+
|
| 169 |
+
## Tests
|
| 170 |
+
|
| 171 |
+
To execute all tests, run:
|
| 172 |
+
|
| 173 |
+
$./setup.py test
|
| 174 |
+
|
| 175 |
+
in the current directory.
|
| 176 |
+
|
| 177 |
+
For the more fine-grained running of tests or doctests, use `bin/test`
|
| 178 |
+
or respectively `bin/doctest`. The master branch is automatically tested
|
| 179 |
+
by GitHub Actions.
|
| 180 |
+
|
| 181 |
+
To test pull requests, use
|
| 182 |
+
[sympy-bot](https://github.com/sympy/sympy-bot).
|
| 183 |
+
|
| 184 |
+
## Regenerate Experimental <span class="title-ref">LaTeX</span> Parser/Lexer
|
| 185 |
+
|
| 186 |
+
The parser and lexer were generated with the [ANTLR4](http://antlr4.org)
|
| 187 |
+
toolchain in `sympy/parsing/latex/_antlr` and checked into the repo.
|
| 188 |
+
Presently, most users should not need to regenerate these files, but
|
| 189 |
+
if you plan to work on this feature, you will need the `antlr4`
|
| 190 |
+
command-line tool (and you must ensure that it is in your `PATH`).
|
| 191 |
+
One way to get it is:
|
| 192 |
+
|
| 193 |
+
$ conda install -c conda-forge antlr=4.11.1
|
| 194 |
+
|
| 195 |
+
Alternatively, follow the instructions on the ANTLR website and download
|
| 196 |
+
the `antlr-4.11.1-complete.jar`. Then export the `CLASSPATH` as instructed
|
| 197 |
+
and instead of creating `antlr4` as an alias, make it an executable file
|
| 198 |
+
with the following contents:
|
| 199 |
+
``` bash
|
| 200 |
+
#!/bin/bash
|
| 201 |
+
java -jar /usr/local/lib/antlr-4.11.1-complete.jar "$@"
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
After making changes to `sympy/parsing/latex/LaTeX.g4`, run:
|
| 205 |
+
|
| 206 |
+
$ ./setup.py antlr
|
| 207 |
+
|
| 208 |
+
## Clean
|
| 209 |
+
|
| 210 |
+
To clean everything (thus getting the same tree as in the repository):
|
| 211 |
+
|
| 212 |
+
$ git clean -Xdf
|
| 213 |
+
|
| 214 |
+
which will clear everything ignored by `.gitignore`, and:
|
| 215 |
+
|
| 216 |
+
$ git clean -df
|
| 217 |
+
|
| 218 |
+
to clear all untracked files. You can revert the most recent changes in
|
| 219 |
+
git with:
|
| 220 |
+
|
| 221 |
+
$ git reset --hard
|
| 222 |
+
|
| 223 |
+
WARNING: The above commands will all clear changes you may have made,
|
| 224 |
+
and you will lose them forever. Be sure to check things with `git
|
| 225 |
+
status`, `git diff`, `git clean -Xn`, and `git clean -n` before doing any
|
| 226 |
+
of those.
|
| 227 |
+
|
| 228 |
+
## Bugs
|
| 229 |
+
|
| 230 |
+
Our issue tracker is at <https://github.com/sympy/sympy/issues>. Please
|
| 231 |
+
report any bugs that you find. Or, even better, fork the repository on
|
| 232 |
+
GitHub and create a pull request. We welcome all changes, big or small,
|
| 233 |
+
and we will help you make the pull request if you are new to git (just
|
| 234 |
+
ask on our mailing list or Gitter Channel). If you further have any queries, you can find answers
|
| 235 |
+
on Stack Overflow using the [sympy](https://stackoverflow.com/questions/tagged/sympy) tag.
|
| 236 |
+
|
| 237 |
+
## Brief History
|
| 238 |
+
|
| 239 |
+
SymPy was started by Ondřej Čertík in 2005, he wrote some code during
|
| 240 |
+
the summer, then he wrote some more code during summer 2006. In February
|
| 241 |
+
2007, Fabian Pedregosa joined the project and helped fix many things,
|
| 242 |
+
contributed documentation, and made it alive again. 5 students (Mateusz
|
| 243 |
+
Paprocki, Brian Jorgensen, Jason Gedge, Robert Schwarz, and Chris Wu)
|
| 244 |
+
improved SymPy incredibly during summer 2007 as part of the Google
|
| 245 |
+
Summer of Code. Pearu Peterson joined the development during the summer
|
| 246 |
+
2007 and he has made SymPy much more competitive by rewriting the core
|
| 247 |
+
from scratch, which has made it from 10x to 100x faster. Jurjen N.E. Bos
|
| 248 |
+
has contributed pretty-printing and other patches. Fredrik Johansson has
|
| 249 |
+
written mpmath and contributed a lot of patches.
|
| 250 |
+
|
| 251 |
+
SymPy has participated in every Google Summer of Code since 2007. You
|
| 252 |
+
can see <https://github.com/sympy/sympy/wiki#google-summer-of-code> for
|
| 253 |
+
full details. Each year has improved SymPy by bounds. Most of SymPy's
|
| 254 |
+
development has come from Google Summer of Code students.
|
| 255 |
+
|
| 256 |
+
In 2011, Ondřej Čertík stepped down as lead developer, with Aaron
|
| 257 |
+
Meurer, who also started as a Google Summer of Code student, taking his
|
| 258 |
+
place. Ondřej Čertík is still active in the community but is too busy
|
| 259 |
+
with work and family to play a lead development role.
|
| 260 |
+
|
| 261 |
+
Since then, a lot more people have joined the development and some
|
| 262 |
+
people have also left. You can see the full list in doc/src/aboutus.rst,
|
| 263 |
+
or online at:
|
| 264 |
+
|
| 265 |
+
<https://docs.sympy.org/dev/aboutus.html#sympy-development-team>
|
| 266 |
+
|
| 267 |
+
The git history goes back to 2007 when development moved from svn to hg.
|
| 268 |
+
To see the history before that point, look at
|
| 269 |
+
<https://github.com/sympy/sympy-old>.
|
| 270 |
+
|
| 271 |
+
You can use git to see the biggest developers. The command:
|
| 272 |
+
|
| 273 |
+
$ git shortlog -ns
|
| 274 |
+
|
| 275 |
+
will show each developer, sorted by commits to the project. The command:
|
| 276 |
+
|
| 277 |
+
$ git shortlog -ns --since="1 year"
|
| 278 |
+
|
| 279 |
+
will show the top developers from the last year.
|
| 280 |
+
|
| 281 |
+
## Citation
|
| 282 |
+
|
| 283 |
+
To cite SymPy in publications use
|
| 284 |
+
|
| 285 |
+
> Meurer A, Smith CP, Paprocki M, Čertík O, Kirpichev SB, Rocklin M,
|
| 286 |
+
> Kumar A, Ivanov S, Moore JK, Singh S, Rathnayake T, Vig S, Granger BE,
|
| 287 |
+
> Muller RP, Bonazzi F, Gupta H, Vats S, Johansson F, Pedregosa F, Curry
|
| 288 |
+
> MJ, Terrel AR, Roučka Š, Saboo A, Fernando I, Kulal S, Cimrman R,
|
| 289 |
+
> Scopatz A. (2017) SymPy: symbolic computing in Python. *PeerJ Computer
|
| 290 |
+
> Science* 3:e103 <https://doi.org/10.7717/peerj-cs.103>
|
| 291 |
+
|
| 292 |
+
A BibTeX entry for LaTeX users is
|
| 293 |
+
|
| 294 |
+
``` bibtex
|
| 295 |
+
@article{10.7717/peerj-cs.103,
|
| 296 |
+
title = {SymPy: symbolic computing in Python},
|
| 297 |
+
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},
|
| 298 |
+
year = 2017,
|
| 299 |
+
month = Jan,
|
| 300 |
+
keywords = {Python, Computer algebra system, Symbolics},
|
| 301 |
+
abstract = {
|
| 302 |
+
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.
|
| 303 |
+
},
|
| 304 |
+
volume = 3,
|
| 305 |
+
pages = {e103},
|
| 306 |
+
journal = {PeerJ Computer Science},
|
| 307 |
+
issn = {2376-5992},
|
| 308 |
+
url = {https://doi.org/10.7717/peerj-cs.103},
|
| 309 |
+
doi = {10.7717/peerj-cs.103}
|
| 310 |
+
}
|
| 311 |
+
```
|
| 312 |
+
|
| 313 |
+
SymPy is BSD licensed, so you are free to use it whatever you like, be
|
| 314 |
+
it academic, commercial, creating forks or derivatives, as long as you
|
| 315 |
+
copy the BSD statement if you redistribute it (see the LICENSE file for
|
| 316 |
+
details). That said, although not required by the SymPy license, if it
|
| 317 |
+
is convenient for you, please cite SymPy when using it in your work and
|
| 318 |
+
also consider contributing all your changes back, so that we can
|
| 319 |
+
incorporate it and all of us will benefit in the end.
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/RECORD
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (79.0.1)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/entry_points.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[console_scripts]
|
| 2 |
+
isympy = isympy:main
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/AUTHORS
ADDED
|
@@ -0,0 +1,1379 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 1371 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 |
+
Michael Boyle <michael.oliver.boyle@gmail.com>
|
| 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 |
+
Alistair Lynn <arplynn@gmail.com>
|
| 410 |
+
Govind Sahai <gsiitbhu@gmail.com>
|
| 411 |
+
Adam Bloomston <adam@glitterfram.es>
|
| 412 |
+
Kyle McDaniel <mcdanie5@illinois.edu>
|
| 413 |
+
Nguyen Truong Duy <truongduy134@yahoo.com>
|
| 414 |
+
Alex Lindsay <adlinds3@ncsu.edu>
|
| 415 |
+
Mathew Chong <mathewchong.dev@gmail.com>
|
| 416 |
+
Jason Siefken <siefkenj@gmail.com>
|
| 417 |
+
Gaurav Dhingra <gauravdhingra.gxyd@gmail.com>
|
| 418 |
+
Gao, Xiang <qasdfgtyuiop@gmail.com>
|
| 419 |
+
Kevin Ventullo <kevin.ventullo@gmail.com>
|
| 420 |
+
mao8 <thisisma08@gmail.com>
|
| 421 |
+
Isuru Fernando <isuruf@gmail.com>
|
| 422 |
+
Shivam Tyagi <shivam.tyagi.apm13@itbhu.ac.in>
|
| 423 |
+
Richard Otis <richard.otis@outlook.com>
|
| 424 |
+
Rich LaSota <rjlasota@gmail.com>
|
| 425 |
+
dustyrockpyle <dustyrockpyle@gmail.com>
|
| 426 |
+
Anton Akhmerov <anton.akhmerov@gmail.com>
|
| 427 |
+
Michael Zingale <michael.zingale@stonybrook.edu>
|
| 428 |
+
Chak-Pong Chung <chakpongchung@gmail.com>
|
| 429 |
+
David T <derDavidT@users.noreply.github.com>
|
| 430 |
+
Phil Ruffwind <rf@rufflewind.com>
|
| 431 |
+
Sebastian Koslowski <koslowski@kit.edu>
|
| 432 |
+
Kumar Krishna Agrawal <kumar.1994.14@gmail.com>
|
| 433 |
+
Dustin Gadal <Dustin.Gadal@gmail.com>
|
| 434 |
+
João Moura <operte@gmail.com>
|
| 435 |
+
Yu Kobayashi <yukoba@accelart.jp>
|
| 436 |
+
Shashank Kumar <shashank.kumar.apc13@iitbhu.ac.in>
|
| 437 |
+
Timothy Cyrus <tcyrus@users.noreply.github.com>
|
| 438 |
+
Devyani Kota <devyanikota@gmail.com>
|
| 439 |
+
Keval Shah <kevalshah_96@yahoo.co.in>
|
| 440 |
+
Dzhelil Rufat <drufat@caltech.edu>
|
| 441 |
+
Pastafarianist <mr.pastafarianist@gmail.com>
|
| 442 |
+
Sourav Singh <souravsingh@users.noreply.github.com>
|
| 443 |
+
Jacob Garber <jgarber1@ualberta.ca>
|
| 444 |
+
Vinay Singh <csvinay.d@gmail.com>
|
| 445 |
+
GolimarOurHero <metalera94@hotmail.com>
|
| 446 |
+
Prashant Tyagi <prashanttyagi221295@gmail.com>
|
| 447 |
+
Matthew Davis <davisml.md@gmail.com>
|
| 448 |
+
Tschijnmo TSCHAU <tschijnmotschau@gmail.com>
|
| 449 |
+
Alexander Bentkamp <bentkamp@gmail.com>
|
| 450 |
+
Jack Kemp <metaknightdrake-git@yahoo.co.uk>
|
| 451 |
+
Kshitij Saraogi <KshitijSaraogi@gmail.com>
|
| 452 |
+
Thomas Baruchel <baruchel@gmx.com>
|
| 453 |
+
Nicolás Guarín-Zapata <nicoguarin@gmail.com>
|
| 454 |
+
Jens Jørgen Mortensen <jj@smoerhul.dk>
|
| 455 |
+
Sampad Kumar Saha <sampadsaha5@gmail.com>
|
| 456 |
+
Eva Charlotte Mayer <eva-charlotte.mayer@posteo.de>
|
| 457 |
+
Laura Domine <temigo@gmx.com>
|
| 458 |
+
Justin Blythe <jblythe29@gmail.com>
|
| 459 |
+
Meghana Madhyastha <meghana.madhyastha@gmail.com>
|
| 460 |
+
Tanu Hari Dixit <tokencolour@gmail.com>
|
| 461 |
+
Shekhar Prasad Rajak <shekharrajak@live.com>
|
| 462 |
+
Aqnouch Mohammed <aqnouch.mohammed@gmail.com>
|
| 463 |
+
Arafat Dad Khan <arafat.da.khan@gmail.com>
|
| 464 |
+
Boris Atamanovskiy <shaomoron@gmail.com>
|
| 465 |
+
Sam Tygier <sam.tygier@hep.manchester.ac.uk>
|
| 466 |
+
Jai Luthra <me@jailuthra.in>
|
| 467 |
+
Guo Xingjian <Seeker1995@gmail.com>
|
| 468 |
+
Sandeep Veethu <sandeep.veethu@gmail.com>
|
| 469 |
+
Archit Verma <architv07@gmail.com>
|
| 470 |
+
Shubham Tibra <shubh.tibra@gmail.com>
|
| 471 |
+
Ashutosh Saboo <ashutosh.saboo96@gmail.com>
|
| 472 |
+
Michael S. Hansen <michael.hansen@nih.gov>
|
| 473 |
+
Anish Shah <shah.anish07@gmail.com>
|
| 474 |
+
Guillaume Jacquenot <guillaume.jacquenot@gmail.com>
|
| 475 |
+
Bhautik Mavani <mavanibhautik@gmail.com>
|
| 476 |
+
Michał Radwański <enedil.isildur@gmail.com>
|
| 477 |
+
Jerry Li <jerry@jerryli.ca>
|
| 478 |
+
Pablo Zubieta <pabloferz@yahoo.com.mx>
|
| 479 |
+
Shivam Agarwal <knowthyself2503@gmail.com>
|
| 480 |
+
Chaitanya Sai Alaparthi <achaitanyasai@gmail.com>
|
| 481 |
+
Arihant Parsoya <parsoyaarihant@gmail.com>
|
| 482 |
+
Ruslan Pisarev <rpisarev@cloudlinux.com>
|
| 483 |
+
Akash Trehan <akash.trehan123@gmail.com>
|
| 484 |
+
Nishant Nikhil <nishantiam@gmail.com>
|
| 485 |
+
Vladimir Poluhsin <vovapolu@gmail.com>
|
| 486 |
+
Akshay Nagar <awesomeay13@yahoo.com>
|
| 487 |
+
James Brandon Milam <jmilam343@gmail.com>
|
| 488 |
+
Abhinav Agarwal <abhinavagarwal1996@gmail.com>
|
| 489 |
+
Rishabh Daal <rishabhdaal@gmail.com>
|
| 490 |
+
Sanya Khurana <sanya@monica.in>
|
| 491 |
+
Aman Deep <amandeep1024@gmail.com>
|
| 492 |
+
Aravind Reddy <aravindreddy255@gmail.com>
|
| 493 |
+
Abhishek Verma <iamvermaabhishek@gmail.com>
|
| 494 |
+
Matthew Parnell <matt@parnmatt.co.uk>
|
| 495 |
+
Thomas Hickman <Thomas.Hickman42@gmail.com>
|
| 496 |
+
Akshay Siramdas <akshaysiramdas@gmail.com>
|
| 497 |
+
YiDing Jiang <yidinggjiangg@gmail.com>
|
| 498 |
+
Jatin Yadav <jatinyadav25@gmail.com>
|
| 499 |
+
Matthew Thomas <mnmt@users.noreply.github.com>
|
| 500 |
+
Rehas Sachdeva <aquannie@gmail.com>
|
| 501 |
+
Michael Mueller <michaeldmueller7@gmail.com>
|
| 502 |
+
Srajan Garg <srajan.garg@gmail.com>
|
| 503 |
+
Prabhjot Singh <prabhjot.nith@gmail.com>
|
| 504 |
+
Haruki Moriguchi <harukimoriguchi@gmail.com>
|
| 505 |
+
Tom Gijselinck <tomgijselinck@gmail.com>
|
| 506 |
+
Nitin Chaudhary <nitinmax1000@gmail.com>
|
| 507 |
+
Alex Argunov <sajkoooo@gmail.com>
|
| 508 |
+
Nathan Musoke <nathan.musoke@gmail.com>
|
| 509 |
+
Abhishek Garg <abhishekgarg119@gmail.com>
|
| 510 |
+
Dana Jacobsen <dana@acm.org>
|
| 511 |
+
Vasiliy Dommes <vasdommes@gmail.com>
|
| 512 |
+
Phillip Berndt <phillip.berndt@googlemail.com>
|
| 513 |
+
Haimo Zhang <zh.hammer.dev@gmail.com>
|
| 514 |
+
Anthony Scopatz <scopatz@gmail.com>
|
| 515 |
+
bluebrook <perl4logic@gmail.com>
|
| 516 |
+
Leonid Kovalev <leonidvkovalev@gmail.com>
|
| 517 |
+
Josh Burkart <jburkart@gmail.com>
|
| 518 |
+
Dimitra Konomi <t8130064@dias.aueb.gr>
|
| 519 |
+
Christina Zografou <t8130048@dias.aueb.gr>
|
| 520 |
+
Fiach Antaw <fiach.antaw+github@gmail.com>
|
| 521 |
+
Langston Barrett <langston.barrett@gmail.com>
|
| 522 |
+
Krit Karan <kritkaran.b13@iiits.in>
|
| 523 |
+
G. D. McBain <gdmcbain@protonmail.com>
|
| 524 |
+
Prempal Singh <prempal.42@gmail.com>
|
| 525 |
+
Gabriel Orisaka <orisaka@gmail.com>
|
| 526 |
+
Matthias Bussonnier <bussonniermatthias@gmail.com>
|
| 527 |
+
rahuldan <rahul02013@gmail.com>
|
| 528 |
+
Colin Marquardt <github@marquardt-home.de>
|
| 529 |
+
Andrew Taber <andrew.e.taber@gmail.com>
|
| 530 |
+
Yash Reddy <write2yashreddy@gmail.com>
|
| 531 |
+
Peter Stangl <peter.stangl@ph.tum.de>
|
| 532 |
+
elvis-sik <e.sikora@grad.ufsc.br>
|
| 533 |
+
Nikos Karagiannakis <nikoskaragiannakis@gmail.com>
|
| 534 |
+
Jainul Vaghasia <jainulvaghasia@gmail.com>
|
| 535 |
+
Dennis Meckel <meckel@datenschuppen.de>
|
| 536 |
+
Harshil Meena <harshil.7535@gmail.com>
|
| 537 |
+
Micky <mickydroch@gmail.com>
|
| 538 |
+
Nick Curtis <nicholas.curtis@uconn.edu>
|
| 539 |
+
Michele Zaffalon <michele.zaffalon@gmail.com>
|
| 540 |
+
Martha Giannoudovardi <maapxa@gmail.com>
|
| 541 |
+
Devang Kulshreshtha <devang.kulshreshtha.cse14@itbhu.ac.in>
|
| 542 |
+
Steph Papanik <spapanik21@gmail.com>
|
| 543 |
+
Mohammad Sadeq Dousti <msdousti@gmail.com>
|
| 544 |
+
Arif Ahmed <arif.ahmed.5.10.1995@gmail.com>
|
| 545 |
+
Abdullah Javed Nesar <abduljaved1994@gmail.com>
|
| 546 |
+
Lakshya Agrawal <zeeshan.lakshya@gmail.com>
|
| 547 |
+
shruti <shrutishrm512@gmail.com>
|
| 548 |
+
Rohit Rango <rohit.rango@gmail.com>
|
| 549 |
+
Hong Xu <hong@topbug.net>
|
| 550 |
+
Ivan Petuhov <ivan@ostrovok.ru>
|
| 551 |
+
Alsheh <alsheh@rpi.edu>
|
| 552 |
+
Marcel Stimberg <marcel.stimberg@ens.fr>
|
| 553 |
+
Alexey Pakhocmhik <cool.Bakov@yandex.ru>
|
| 554 |
+
Tommy Olofsson <tommy.olofsson.90@gmail.com>
|
| 555 |
+
Zulfikar <zulfikar97@gmail.com>
|
| 556 |
+
Blair Azzopardi <blairuk@gmail.com>
|
| 557 |
+
Danny Hermes <daniel.j.hermes@gmail.com>
|
| 558 |
+
Sergey Pestov <pestov-sa@yandex.ru>
|
| 559 |
+
Mohit Chandra <mohit.chandra@research.iiit.ac.in>
|
| 560 |
+
Karthik Chintapalli <karthik.chintapalli@students.iiit.ac.in>
|
| 561 |
+
Marcin Briański <marcin.brianski@student.uj.edu.pl>
|
| 562 |
+
andreo <andrey.torba@gmail.com>
|
| 563 |
+
Flamy Owl <flamyowl@protonmail.ch>
|
| 564 |
+
Yicong Guo <guoyicong100@gmail.com>
|
| 565 |
+
Varun Garg <varun.garg03@gmail.com>
|
| 566 |
+
Rishabh Madan <rishabhmadan96@gmail.com>
|
| 567 |
+
Aditya Kapoor <aditya.kapoor.apm12@itbhu.ac.in>
|
| 568 |
+
Karan Sharma <karan1276@gmail.com>
|
| 569 |
+
Vedant Rathore <vedantr1998@gmail.com>
|
| 570 |
+
Johan Blåbäck <johan_bluecreek@riseup.net>
|
| 571 |
+
Pranjal Tale <pranjaltale16@gmail.com>
|
| 572 |
+
Jason Tokayer <jason.tokayer@gmail.com>
|
| 573 |
+
Raghav Jajodia <jajodia.raghav@gmail.com>
|
| 574 |
+
Rajat Thakur <rajatthakur1997@gmail.com>
|
| 575 |
+
Dhruv Bhanushali <dhruv_b@live.com>
|
| 576 |
+
Anjul Kumar Tyagi <anjul.ten@gmail.com>
|
| 577 |
+
Barun Parruck <barun.parruck@gmail.com>
|
| 578 |
+
Bao Chau <chauquocbao0907@gmail.com>
|
| 579 |
+
Tanay Agrawal <tanay_agrawal@hotmail.com>
|
| 580 |
+
Ranjith Kumar <ranjith.dakshana2015@gmail.com>
|
| 581 |
+
Shikhar Makhija <shikharmakhija2@gmail.com>
|
| 582 |
+
Yathartha Joshi <yathartha32@gmail.com>
|
| 583 |
+
Valeriia Gladkova <valeriia.gladkova@gmail.com>
|
| 584 |
+
Sagar Bharadwaj <sagarbharadwaj50@gmail.com>
|
| 585 |
+
Daniel Mahler <dmahler@gmail.com>
|
| 586 |
+
Ka Yi <chua.kayi@yahoo.com.sg>
|
| 587 |
+
Rishat Iskhakov <iskhakov@frtk.ru>
|
| 588 |
+
Szymon Mieszczak <szymon.mieszczak@gmail.com>
|
| 589 |
+
Sachin Agarwal <sachinagarwal0499@gmail.com>
|
| 590 |
+
Priyank Patel <pspbot7@gmail.com>
|
| 591 |
+
Satya Prakash Dwibedi <akash581050@gmail.com>
|
| 592 |
+
tools4origins <tools4origins@gmail.com>
|
| 593 |
+
Nico Schlömer <nico.schloemer@gmail.com>
|
| 594 |
+
Fermi Paradox <FermiParadox@users.noreply.github.com>
|
| 595 |
+
Ekansh Purohit <purohit.e15@gmail.com>
|
| 596 |
+
Vedarth Sharma <vedarth.sharma@gmail.com>
|
| 597 |
+
Peeyush Kushwaha <peeyush.p97@gmail.com>
|
| 598 |
+
Jayjayyy <vfhsln8s3l4b87t4c3@byom.de>
|
| 599 |
+
Christopher J. Wright <cjwright4242gh@gmail.com>
|
| 600 |
+
Jakub Wilk <jwilk@jwilk.net>
|
| 601 |
+
Mauro Garavello <mauro.garavello@unimib.it>
|
| 602 |
+
Chris Tefer <ctefer@gmail.com>
|
| 603 |
+
Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
| 604 |
+
Chiu-Hsiang Hsu <wdv4758h@gmail.com>
|
| 605 |
+
Carlos Cordoba <ccordoba12@gmail.com>
|
| 606 |
+
Fabian Ball <fabian.ball@kit.edu>
|
| 607 |
+
Yerniyaz <yerniyaz.nurgabylov@nu.edu.kz>
|
| 608 |
+
Christiano Anderson <canderson@riseup.net>
|
| 609 |
+
Robin Neatherway <robin.neatherway@gmail.com>
|
| 610 |
+
Thomas Hunt <thomashunt13@gmail.com>
|
| 611 |
+
Theodore Han <theodorehan@hotmail.com>
|
| 612 |
+
Duc-Minh Phan <alephvn@gmail.com>
|
| 613 |
+
Lejla Metohajrova <l.metohajrova@gmail.com>
|
| 614 |
+
Samyak Jain <samyak.jain2016a@vitstudent.ac.in>
|
| 615 |
+
Aditya Rohan <riyuzakiiitk@gmail.com>
|
| 616 |
+
Vincent Delecroix <vincent.delecroix@labri.fr>
|
| 617 |
+
Michael Sparapany <msparapa@purdue.edu>
|
| 618 |
+
Harsh Jain <harshjniitr@gmail.com>
|
| 619 |
+
Nathan Goldbaum <ngoldbau@illinois.edu>
|
| 620 |
+
latot <felipematas@yahoo.com>
|
| 621 |
+
Kenneth Lyons <ixjlyons@gmail.com>
|
| 622 |
+
Stan Schymanski <stan.schymanski@env.ethz.ch>
|
| 623 |
+
David Daly <david.daly12@kzoo.edu>
|
| 624 |
+
Ayush Shridhar <ayush.shridhar1999@gmail.com>
|
| 625 |
+
Javed Nissar <javednissar@gmail.com>
|
| 626 |
+
Jiri Kuncar <jiri.kuncar@gmail.com>
|
| 627 |
+
vedantc98 <vedantc98@gmail.com>
|
| 628 |
+
Rupesh Harode <rupeshharode@gmail.com>
|
| 629 |
+
Rob Zinkov <rob@zinkov.com>
|
| 630 |
+
James Harrop <ebc121@gmail.com>
|
| 631 |
+
James Taylor <user234683@tutanota.com>
|
| 632 |
+
Ishan Joshi <ishanaj98@gmail.com>
|
| 633 |
+
Marco Mancini <marco.mancini@obspm.fr>
|
| 634 |
+
Boris Ettinger <ettinger.boris@gmail.com>
|
| 635 |
+
Micah Fitch <micahscopes@gmail.com>
|
| 636 |
+
Daniel Wennberg <daniel.wennberg@gmail.com>
|
| 637 |
+
ylemkimon <ylemkimon@naver.com>
|
| 638 |
+
Akash Vaish <akash.9712@gmail.com>
|
| 639 |
+
Peter Enenkel <peter.enenkel+git@gmail.com>
|
| 640 |
+
Waldir Pimenta <waldyrious@gmail.com>
|
| 641 |
+
Jithin D. George <jithindgeorge93@gmail.com>
|
| 642 |
+
Lev Chelyadinov <leva181777@gmail.com>
|
| 643 |
+
Lucas Wiman <lucas.wiman@gmail.com>
|
| 644 |
+
Rhea Parekh <rheaparekh12@gmail.com>
|
| 645 |
+
James Cotton <peabody124@gmail.com>
|
| 646 |
+
Robert Pollak <robert.pollak@posteo.net>
|
| 647 |
+
anca-mc <anca-mc@users.noreply.github.com>
|
| 648 |
+
Sourav Ghosh <souravghosh2197@gmail.com>
|
| 649 |
+
Jonathan Allan <jjallan@users.noreply.github.com>
|
| 650 |
+
Nikhil Pappu <nkhlpappu@gmail.com>
|
| 651 |
+
Ethan Ward <etkewa@gmail.com>
|
| 652 |
+
Cezary Marczak <zeddq1@gmail.com>
|
| 653 |
+
dps7ud <dps7ud@virginia.edu>
|
| 654 |
+
Nilabja Bhattacharya <nilabja10201992@gmail.com>
|
| 655 |
+
Itay4 <31018228+Itay4@users.noreply.github.com>
|
| 656 |
+
Poom Chiarawongse <eight1911@gmail.com>
|
| 657 |
+
Yang Yang <wdscxsj@gmail.com>
|
| 658 |
+
Cavendish McKay <cmckay@tachycline.com>
|
| 659 |
+
Bradley Gannon <bradley.m.gannon@gmail.com>
|
| 660 |
+
B McG <bmcg0890@gmail.com>
|
| 661 |
+
Rob Drynkin <rob.drynkin@gmail.com>
|
| 662 |
+
Seth Ebner <murgrehk@gmail.com>
|
| 663 |
+
Akash Kundu <sk.sayakkundu1997@gmail.com>
|
| 664 |
+
Mark Jeromin <mark.jeromin@sysfrog.net>
|
| 665 |
+
Roberto Díaz Pérez <r.r.1994a@gmail.com>
|
| 666 |
+
Gleb Siroki <g.shiroki@gmail.com>
|
| 667 |
+
Segev Finer <segev208@gmail.com>
|
| 668 |
+
Alex Lubbock <code@alexlubbock.com>
|
| 669 |
+
Ayodeji Ige <ayodeji18@outlook.com>
|
| 670 |
+
Matthew Wardrop <matthew.wardrop@airbnb.com>
|
| 671 |
+
Hugo van Kemenade <hugovk@users.noreply.github.com>
|
| 672 |
+
Austin Palmer <ap4000@nyu.edu>
|
| 673 |
+
der-blaue-elefant <github@kklein.de>
|
| 674 |
+
Filip Gokstorp <filip@gokstorp.se>
|
| 675 |
+
Yuki Matsuda <yuki.matsuda.w@gmail.com>
|
| 676 |
+
Aaron Miller <acmiller273@gmail.com>
|
| 677 |
+
Salil Vishnu Kapur <salilvishnukapur@gmail.com>
|
| 678 |
+
Atharva Khare <khareatharva@gmail.com>
|
| 679 |
+
Shubham Maheshwari <rmaheshwari05@gmail.com>
|
| 680 |
+
Pavel Tkachenko <paveltkachenko@email.com>
|
| 681 |
+
Ashish Kumar Gaurav <ashishkg0022@gmail.com>
|
| 682 |
+
Rajeev Singh <rajs2010@gmail.com>
|
| 683 |
+
Keno Goertz <keno@goertz-berlin.com>
|
| 684 |
+
Lucas Gallindo <lgallindo@gmail.com>
|
| 685 |
+
Himanshu <hs80941@gmail.com>
|
| 686 |
+
David Menéndez Hurtado <david.menendez.hurtado@scilifelab.se>
|
| 687 |
+
Amit Manchanda <amitdelhi1995@gmail.com>
|
| 688 |
+
Rohit Jain <rohitjain3241@gmail.com>
|
| 689 |
+
Jonathan A. Gross <jarthurgross@gmail.com>
|
| 690 |
+
Unknown <kunda@scribus.net>
|
| 691 |
+
Sayan Goswami <Sayan98@users.noreply.github.com>
|
| 692 |
+
Subhash Saurabh <subhashsaurabh419@gmail.com>
|
| 693 |
+
Rastislav Rabatin <rastislav.rabatin@gmail.com>
|
| 694 |
+
Vishal <vishalg2235@gmail.com>
|
| 695 |
+
Jeremey Gluck <jeremygluck@yahoo.com>
|
| 696 |
+
Akshat Maheshwari <akshat14714@gmail.com>
|
| 697 |
+
symbolique <symbolique@users.noreply.github.com>
|
| 698 |
+
Saloni Jain <tosalonijain@gmail.com>
|
| 699 |
+
Arighna Chakrabarty <arighna.chakrabarty100@gmail.com>
|
| 700 |
+
Abhigyan Khaund <mail@abhigyan.xyz>
|
| 701 |
+
Jashanpreet Singh <jashansingh.4398@gmail.com>
|
| 702 |
+
Saurabh Agarwal <shourabh.agarwal@gmail.com>
|
| 703 |
+
luzpaz <luzpaz@users.noreply.github.com>
|
| 704 |
+
P. Sai Prasanth <psai.prasanth.min16@itbhu.ac.in>
|
| 705 |
+
Nirmal Sarswat <nirmalsarswat400@gmail.com>
|
| 706 |
+
Cristian Di Pietrantonio <cristiandipietrantonio@gmail.com>
|
| 707 |
+
Ravi charan <ravicharan.vsp@gmail.com>
|
| 708 |
+
Nityananda Gohain <nityanandagohain@gmail.com>
|
| 709 |
+
Cédric Travelletti <cedrictravelletti@gmail.com>
|
| 710 |
+
Nicholas Bollweg <nick.bollweg@gmail.com>
|
| 711 |
+
Himanshu Ladia <hladia199811@gmail.com>
|
| 712 |
+
Adwait Baokar <adwaitbaokar18@gmail.com>
|
| 713 |
+
Mihail Tarigradschi <m.tarigradschi@gmail.com>
|
| 714 |
+
Saketh <alurusaisaketh@gmail.com>
|
| 715 |
+
rushyam <rushyamsonu@gmail.com>
|
| 716 |
+
sfoo <sfoohei@gmail.com>
|
| 717 |
+
Rahil Hastu <rahilhastu@gmail.com>
|
| 718 |
+
Zach Raines <raineszm@gmail.com>
|
| 719 |
+
Sidhant Nagpal <sidhantnagpal97@gmail.com>
|
| 720 |
+
Gagandeep Singh <singh.23@iitj.ac.in>
|
| 721 |
+
Rishav Chakraborty <annonymousxyz@outlook.com>
|
| 722 |
+
Malkhan Singh <malkhansinghrathaur@gmail.com>
|
| 723 |
+
Joaquim Monserrat <qmonserrat@mailoo.org>
|
| 724 |
+
Mayank Singh <mayank.singh081997@gmail.com>
|
| 725 |
+
Rémy Léone <rleone@online.net>
|
| 726 |
+
Maxence Mayrand <35958639+maxencemayrand@users.noreply.github.com>
|
| 727 |
+
Nikoleta Glynatsi <GlynatsiNE@cardiff.ac.uk>
|
| 728 |
+
helo9 <helo9@users.noreply.github.com>
|
| 729 |
+
Ken Wakita <wakita@is.titech.ac.jp>
|
| 730 |
+
Carl Sandrock <carl.sandrock@up.ac.za>
|
| 731 |
+
Fredrik Eriksson <freeriks@student.chalmers.se>
|
| 732 |
+
Ian Swire <oversizedpenguin@gmail.com>
|
| 733 |
+
Bulat <daianovich@mail.ru>
|
| 734 |
+
Ehren Metcalfe <ehren.m@gmail.com>
|
| 735 |
+
Dmitry Savransky <dsavransky@gmail.com>
|
| 736 |
+
Kiyohito Yamazaki <kyamaz@openql.org>
|
| 737 |
+
Caley Finn <caleyreuben@gmail.com>
|
| 738 |
+
Zhi-Qiang Zhou <zzq_890709@hotmail.com>
|
| 739 |
+
Alexander Pozdneev <pozdneev@users.noreply.github.com>
|
| 740 |
+
Wes Turner <50891+westurner@users.noreply.github.com>
|
| 741 |
+
JMSS-Unknown <31131631+JMSS-Unknown@users.noreply.github.com>
|
| 742 |
+
Arshdeep Singh <singh.arshdeep1999@gmail.com>
|
| 743 |
+
cym1 <16437732+cym1@users.noreply.github.com>
|
| 744 |
+
Stewart Wadsworth <stewart.wadsworth@gmail.com>
|
| 745 |
+
Jared Lumpe <mjlumpe@gmail.com>
|
| 746 |
+
Avi Shrivastava <shrivastavaavi123@gmail.com>
|
| 747 |
+
ramvenkat98 <ramvenkat98@gmail.com>
|
| 748 |
+
Bilal Ahmed <b.ahmed0918@gmail.com>
|
| 749 |
+
Dimas Abreu Archanjo Dutra <dimasad@ufmg.br>
|
| 750 |
+
Yatna Verma <yatnavermaa@gmail.com>
|
| 751 |
+
S.Y. Lee <sylee957@gmail.com>
|
| 752 |
+
Miro Hrončok <miro@hroncok.cz>
|
| 753 |
+
Sudarshan Kamath <sudarshan.kamath97@gmail.com>
|
| 754 |
+
Ayushman Koul <ayushmankoul4570@gmail.com>
|
| 755 |
+
Robert Dougherty-Bliss <robert.w.bliss@gmail.com>
|
| 756 |
+
Andrey Grozin <A.G.Grozin@inp.nsk.su>
|
| 757 |
+
Bavish Kulur <bavishkulur@gmail.com>
|
| 758 |
+
Arun Singh <arunsin997@gmail.com>
|
| 759 |
+
sirnicolaf <43586954+sirnicolaf@users.noreply.github.com>
|
| 760 |
+
Zachariah Etienne <zachetie@gmail.com>
|
| 761 |
+
Prayush Dawda <35144226+iamprayush@users.noreply.github.com>
|
| 762 |
+
2torus <boris.ettinger@gmail.com>
|
| 763 |
+
Faisal Riyaz <faisalriyaz011@gmail.com>
|
| 764 |
+
Martin Roelfs <u0114255@kuleuven.be>
|
| 765 |
+
SirJohnFranklin <sirjfu@googlemail.com>
|
| 766 |
+
Anthony Sottile <asottile@umich.edu>
|
| 767 |
+
ViacheslavP <public.viacheslav@gmail.com>
|
| 768 |
+
Safiya03 <safiyanesar@gmail.com>
|
| 769 |
+
Alexander Dunlap <alexander.dunlap@gmail.com>
|
| 770 |
+
Rohit Sharma <31184621+rohitx007@users.noreply.github.com>
|
| 771 |
+
Jonathan Warner <warnerjon12@gmail.com>
|
| 772 |
+
Mohit Balwani <mohitbalwani.ict17@gmail.com>
|
| 773 |
+
Marduk Bolaños <mardukbp@mac.com>
|
| 774 |
+
amsuhane <ayushsuhane99@iitkgp.ac.in>
|
| 775 |
+
Matthias Geier <Matthias.Geier@gmail.com>
|
| 776 |
+
klaasvanaarsen <44929042+klaasvanaarsen@users.noreply.github.com>
|
| 777 |
+
Shubham Kumar Jha <skjha832@gmail.com>
|
| 778 |
+
rationa-kunal <kunalgk1999@gmail.com>
|
| 779 |
+
Animesh Sinha <animeshsinha1309@gmail.com>
|
| 780 |
+
Gaurang Tandon <1gaurangtandon@gmail.com>
|
| 781 |
+
Matthew Craven <clyring@users.noreply.github.com>
|
| 782 |
+
Daniel Ingram <ingramds@appstate.edu>
|
| 783 |
+
Jogi Miglani <jmig5776@gmail.com>
|
| 784 |
+
Takumasa Nakamura <n.takumasa@gmail.com>
|
| 785 |
+
Ritu Raj Singh <RituRajSingh878@gmail.com>
|
| 786 |
+
Rajiv Ranjan Singh <rajivperfect007@gmail.com>
|
| 787 |
+
Vera Lozhkina <veralozhkina@gmail.com>
|
| 788 |
+
adhoc-king <46354827+adhoc-king@users.noreply.github.com>
|
| 789 |
+
Mikel Rouco <mikel.mrm@gmail.com>
|
| 790 |
+
Oscar Gustafsson <oscar.gustafsson@gmail.com>
|
| 791 |
+
damianos <damianos@semmle.com>
|
| 792 |
+
Supreet Agrawal <supreet11agrawal@gmail.com>
|
| 793 |
+
shiksha11 <shiksharawat01@gmail.com>
|
| 794 |
+
Martin Ueding <dev@martin-ueding.de>
|
| 795 |
+
sharma-kunal <kunalsharma6914@gmail.com>
|
| 796 |
+
Divyanshu Thakur <divyanshu@iiitmanipur.ac.in>
|
| 797 |
+
Susumu Ishizuka <susumu.ishizuka@kii.com>
|
| 798 |
+
Samnan Rahee <namanush.rsr.16@gmail.com>
|
| 799 |
+
Fredrik Andersson <fredrik.andersson@fcc.chalmers.se>
|
| 800 |
+
Bhavya Srivastava <bhavya17037@iiitd.ac.in>
|
| 801 |
+
Alpesh Jamgade <alpeshjamgade21@gmail.com>
|
| 802 |
+
Shubham Abhang <shubhamabhang77@gmail.com>
|
| 803 |
+
Vishesh Mangla <manglavishesh64@gmail.com>
|
| 804 |
+
Nicko van Someren <nicko@nicko.org>
|
| 805 |
+
dandiez <47832466+dandiez@users.noreply.github.com>
|
| 806 |
+
Frédéric Chapoton <fchapoton2@gmail.com>
|
| 807 |
+
jhanwar <f2015463@pilani.bits-pilani.ac.in>
|
| 808 |
+
Noumbissi valere Gille Geovan <noumbissivalere@gmail.com>
|
| 809 |
+
Salmista-94 <alejandrogroso@hotmail.com>
|
| 810 |
+
Shivani Kohli <shivanikohli.09@gmail.com>
|
| 811 |
+
Parker Berry <parkereberry@gmail.com>
|
| 812 |
+
Pragyan Mehrotra <pragyan18168@iiitd.ac.in>
|
| 813 |
+
Nabanita Dash <dashnabanita@gmail.com>
|
| 814 |
+
Gaetano Guerriero <x.guerriero@tin.it>
|
| 815 |
+
Ankit Raj Pandey <pandeyan@grinnell.edu>
|
| 816 |
+
Ritesh Kumar <ritesh99rakesh@gmail.com>
|
| 817 |
+
kangzhiq <709563092@qq.com>
|
| 818 |
+
Jun Lin <junlin0604@gmail.com>
|
| 819 |
+
Petr Kungurtsev <corwinat@gmail.com>
|
| 820 |
+
Anway De <anway1756@gmail.com>
|
| 821 |
+
znxftw <vishnu2101@gmail.com>
|
| 822 |
+
Denis Ivanenko <ivanenko@ucu.edu.ua>
|
| 823 |
+
Orestis Vaggelis <orestisvaggelis@mail.com>
|
| 824 |
+
Nikhil Maan <nikhilmaan22@gmail.com>
|
| 825 |
+
Abhinav Anand <abhinav.anand2807@gmail.com>
|
| 826 |
+
Qingsha Shi <googol.sqs@gmail.com>
|
| 827 |
+
Juan Barbosa <js.barbosa10@uniandes.edu.co>
|
| 828 |
+
Prionti Nasir <pdn3628@rit.edu>
|
| 829 |
+
Bharat Raghunathan <bharatraghunthan9767@gmail.com>
|
| 830 |
+
arooshiverma <av22@iitbbs.ac.in>
|
| 831 |
+
Christoph Gohle <ctg@mpq.mpg.de>
|
| 832 |
+
Charalampos Tsiagkalis <ctsiagkalis@uth.gr>
|
| 833 |
+
Daniel Sears <highpost@users.noreply.github.com>
|
| 834 |
+
Megan Ly <megan.ly@learnosity.com>
|
| 835 |
+
Sean P. Cornelius <spcornelius@gmail.com>
|
| 836 |
+
Erik R. Gomez <gomez@kth.se>
|
| 837 |
+
Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
|
| 838 |
+
Henry Metlov <genrih.metlov@gmail.com>
|
| 839 |
+
pekochun <hamburg_hamburger2000@yahoo.co.jp>
|
| 840 |
+
Bendik Samseth <b.samseth@gmail.com>
|
| 841 |
+
Vighnesh Shenoy <vighneshq@gmail.com>
|
| 842 |
+
Versus Void <versusvoid@gmail.com>
|
| 843 |
+
Denys Rybalka <rybalka.denis@gmail.com>
|
| 844 |
+
Mark Dickinson <dickinsm@gmail.com>
|
| 845 |
+
Rimi <rimibis@umich.edu>
|
| 846 |
+
rimibis <33387803+rimibis@users.noreply.github.com>
|
| 847 |
+
Steven Lee <stevenlee123@protonmail.com>
|
| 848 |
+
Gilles Schintgen <gschintgen@hambier.lu>
|
| 849 |
+
Abhi58 <abhijithbharadwaj58@gmail.com>
|
| 850 |
+
Tomasz Pytel <tompytel@gmail.com>
|
| 851 |
+
Aadit Kamat <aadit.k12@gmail.com>
|
| 852 |
+
Samesh <samesh.lakhotia@gmail.com>
|
| 853 |
+
Velibor Zeli <velibor@mech.kth.se>
|
| 854 |
+
Gabriel Bernardino <gabriel.bernardino@upf.edu>
|
| 855 |
+
Joseph Redfern <joseph@redfern.me>
|
| 856 |
+
Evelyn King <evelyn.cameron.king@gmail.com>
|
| 857 |
+
Miguel Marco <mmarco@unizar.es>
|
| 858 |
+
David Hagen <david@drhagen.com>
|
| 859 |
+
Hannah Kari <hannah.kari@marquette.edu>
|
| 860 |
+
Soniya Nayak <soniyanayak51@gmail.com>
|
| 861 |
+
Harsh Agarwal <hagarwal9200@gmail.com>
|
| 862 |
+
Enric Florit <efz1005@gmail.com>
|
| 863 |
+
Yogesh Mishra <ymishra013@gmail.com>
|
| 864 |
+
Denis Rykov <rykovd@gmail.com>
|
| 865 |
+
Ivan Tkachenko <me@ratijas.tk>
|
| 866 |
+
Kenneth Emeka Odoh <kenneth.odoh@gmail.com>
|
| 867 |
+
Stephan Seitz <stephan.seitz@fau.de>
|
| 868 |
+
Yeshwanth N <yeshsurya@gmail.com>
|
| 869 |
+
Oscar Gerardo Lazo Arjona <oscar.lazoarjona@physics.ox.ac.uk>
|
| 870 |
+
Srinivasa Arun Yeragudipati <ysarun1999@gmail.com>
|
| 871 |
+
Kirtan Mali <kirtanmali555@gmail.com>
|
| 872 |
+
TitanSnow <sweeto@live.cn>
|
| 873 |
+
Pengning Chao <8857165+PengningChao@users.noreply.github.com>
|
| 874 |
+
Louis Abraham <louis.abraham@yahoo.fr>
|
| 875 |
+
Morten Olsen Lysgaard <morten@lysgaard.no>
|
| 876 |
+
Akash Nagaraj (akasnaga) <akasnaga@cisco.com>
|
| 877 |
+
Akash Nagaraj <grassknoted@gmail.com>
|
| 878 |
+
Lauren Glattly <laurenglattly@gmail.com>
|
| 879 |
+
Hou-Rui <houruinus@gmail.com>
|
| 880 |
+
George Korepanov <gkorepanov.gk@gmail.com>
|
| 881 |
+
dranknight09 <cbhaavan@gmail.com>
|
| 882 |
+
aditisingh2362 <aditisingh2362@gmail.com>
|
| 883 |
+
Gina <Dr-G@users.noreply.github.com>
|
| 884 |
+
gregmedlock <gmedlo@gmail.com>
|
| 885 |
+
Georgios Giapitzakis Tzintanos <giorgosgiapis@mail.com>
|
| 886 |
+
Eric Wieser <wieser.eric@gmail.com>
|
| 887 |
+
Bradley Dowling <34559056+btdow@users.noreply.github.com>
|
| 888 |
+
Maria Marginean <33810762+mmargin@users.noreply.github.com>
|
| 889 |
+
Akash Agrawall <akash.wanted@gmail.com>
|
| 890 |
+
jgulian <josephdgulian@gmail.com>
|
| 891 |
+
Sourav Goyal <souravgl0@gmail.com>
|
| 892 |
+
Zlatan Vasović <zlatanvasovic@gmail.com>
|
| 893 |
+
Alex Meiburg <timeroot.alex@gmail.com>
|
| 894 |
+
Smit Lunagariya <smitlunagariya.mat18@itbhu.ac.in>
|
| 895 |
+
Naman Gera <namangera15@gmail.com>
|
| 896 |
+
Julien Palard <julien@palard.fr>
|
| 897 |
+
Dhruv Mendiratta <dhruvmendiratta6@gmail.com>
|
| 898 |
+
erdOne <36414270+erdOne@users.noreply.github.com>
|
| 899 |
+
risubaba <risubhjain1010@gmail.com>
|
| 900 |
+
abhinav28071999 <41710346+abhinav28071999@users.noreply.github.com>
|
| 901 |
+
Jisoo Song <jeesoo9595@snu.ac.kr>
|
| 902 |
+
Jaime R <38530589+Jaime02@users.noreply.github.com>
|
| 903 |
+
Vikrant Malik <vikrantmalik051@gmail.com>
|
| 904 |
+
Hardik Saini <43683678+Guardianofgotham@users.noreply.github.com>
|
| 905 |
+
Abhishek <uchiha@pop-os.localdomain>
|
| 906 |
+
Johannes Hartung <joha2@gmx.net>
|
| 907 |
+
Milan Jolly <milan.cs16@iitp.ac.in>
|
| 908 |
+
faizan2700 <syedfaizan824@gmail.com>
|
| 909 |
+
mohit <39158356+mohitacecode@users.noreply.github.com>
|
| 910 |
+
Mohit Gupta <mohitgupta@gmail.com>
|
| 911 |
+
Psycho-Pirate <prakharsaxena.civ18@iitbhu.ac.in>
|
| 912 |
+
Chanakya-Ekbote <ca10@iitbbs.ac.in>
|
| 913 |
+
Rashmi Shehana <rashmi.watagedara@syscolabs.com>
|
| 914 |
+
Jonty16117 <jonty@DESKTOP-J1O6ANP.localdomain>
|
| 915 |
+
Anubhav Gupta <anubhav.gupta.cse19@itbhu.ac.in>
|
| 916 |
+
Michal Grňo <m93a.cz@gmail.com>
|
| 917 |
+
vezeli <37907135+vezeli@users.noreply.github.com>
|
| 918 |
+
Tim Gates <tim.gates@iress.com>
|
| 919 |
+
Sandeep Murthy <smurthy@protonmail.ch>
|
| 920 |
+
Neil <mistersheik@gmail.com>
|
| 921 |
+
V1krant <46847915+V1krant@users.noreply.github.com>
|
| 922 |
+
alejandro <amartinhernan@gmail.com>
|
| 923 |
+
Riyan Dhiman <Riyandhiman14@gmail.com>
|
| 924 |
+
sbt4104 <sthorat661@gmail.com>
|
| 925 |
+
Seth Troisi <sethtroisi@google.com>
|
| 926 |
+
Bhaskar Gupta <guptabhanu1999@gmail.com>
|
| 927 |
+
Smit Gajjar <smitgajjar.gs@gmail.com>
|
| 928 |
+
rbl <rlee@grove.co>
|
| 929 |
+
Ilya Pchelintsev <ilya.pchelintsev@outlook.com>
|
| 930 |
+
Omar Wagih <o.wagih.ow@gmail.com>
|
| 931 |
+
prshnt19 <prashant.rawat216@gmail.com>
|
| 932 |
+
Johan Guzman <jguzm022@ucr.edu>
|
| 933 |
+
Vasileios Kalos <kalosbasileios@gmail.com>
|
| 934 |
+
BasileiosKal <61801875+BasileiosKal@users.noreply.github.com>
|
| 935 |
+
Shubham Thorat <37049710+sbt4104@users.noreply.github.com>
|
| 936 |
+
Arpan Chattopadhyay <f20180319@pilani.bits-pilani.ac.in>
|
| 937 |
+
Ashutosh Hathidara <ashutoshhathidara98@gmail.com>
|
| 938 |
+
Moses Paul R <iammosespaulr@gmail.com>
|
| 939 |
+
Saanidhya vats <saanidhyavats@gmail.com>
|
| 940 |
+
tnzl <you@example.com>
|
| 941 |
+
Vatsal Srivastava <alstav.trivas.sava@gmail.com>
|
| 942 |
+
Jean-Luc Herren <jlh@gmx.ch>
|
| 943 |
+
Dhruv Kothari <dhruvkothari22@gmail.com>
|
| 944 |
+
seadavis <45022599+seadavis@users.noreply.github.com>
|
| 945 |
+
kamimura <kamimura@live.jp>
|
| 946 |
+
slacker404 <pchantza@gmail.com>
|
| 947 |
+
Jaime Resano <gemailpersonal02@gmail.com>
|
| 948 |
+
Ebrahim Byagowi <ebrahim@gnu.org>
|
| 949 |
+
wuyudi <wuyudi119@163.com>
|
| 950 |
+
Akira Kyle <ak@akirakyle.com>
|
| 951 |
+
Calvin Jay Ross <calvinjayross@gmail.com>
|
| 952 |
+
Martin Thoma <info@martin-thoma.de>
|
| 953 |
+
Thomas A Caswell <tcaswell@gmail.com>
|
| 954 |
+
Lagaras Stelios <stel.lag@hotmail.com>
|
| 955 |
+
Jerry James <loganjerry@gmail.com>
|
| 956 |
+
Jan Kruse <janckruse@t-online.de>
|
| 957 |
+
Nathan Taylor <pecan.pine@gmail.com>
|
| 958 |
+
Vaishnav Damani <vaishnavdamani3496@gmail.com>
|
| 959 |
+
Mohit Shah <mohitshah3111999@gmail.com>
|
| 960 |
+
Mathias Louboutin <mathias.louboutin@gmail.com>
|
| 961 |
+
Marijan Smetko <marijansmetko123@gmail.com>
|
| 962 |
+
Dave Witte Morris <Dave.Morris@uleth.ca>
|
| 963 |
+
soumi7 <soumibardhan10@gmail.com>
|
| 964 |
+
Zhongshi <zj495@nyu.edu>
|
| 965 |
+
Wes Galbraith <galbwe92@gmail.com>
|
| 966 |
+
KaustubhDamania <kaustubh.damania@gmail.com>
|
| 967 |
+
w495 <w495@yandex-team.ru>
|
| 968 |
+
Akhil Rajput <akh1lrjput@gmail.com>
|
| 969 |
+
Markus Mohrhard <markus.mohrhard@googlemail.com>
|
| 970 |
+
Benjamin Wolba <mail@benjaminwolba.com>
|
| 971 |
+
彭于斌 <1931127624@qq.com>
|
| 972 |
+
Rudr Tiwari <rudrtiwari@gmail.com>
|
| 973 |
+
Aaryan Dewan <aaryandewan@yahoo.com>
|
| 974 |
+
Benedikt Placke <benedikt.placke@outlook.com>
|
| 975 |
+
Sneha Goddu <s.goddu@wustl.edu>
|
| 976 |
+
goddus <39923708+goddus@users.noreply.github.com>
|
| 977 |
+
Shivang Dubey <shivangdubey8@gmail.com>
|
| 978 |
+
Michael Greminger <michael.greminger@gmail.com>
|
| 979 |
+
Peter Cock <p.j.a.cock@googlemail.com>
|
| 980 |
+
Willem Melching <willem.melching@gmail.com>
|
| 981 |
+
Elias Basler <e.e.basler@protonmail.com>
|
| 982 |
+
Brandon David <brandon.david@zoho.com>
|
| 983 |
+
Abhay_Dhiman <abhaysdhimans@gmail.com>
|
| 984 |
+
Tasha Kim <jae_young_kim@brown.edu>
|
| 985 |
+
Ayush Malik <ayushmalik779@gmail.com>
|
| 986 |
+
Devesh Sawant <devesh47cool@gmail.com>
|
| 987 |
+
Wolfgang Stöcher <wolfgang@stoecher.com>
|
| 988 |
+
Sudeep Sidhu <sudeepmanilsidhu@gmail.com>
|
| 989 |
+
foice <foice.news@gmail.com>
|
| 990 |
+
Ben Payne <ben.is.located@gmail.com>
|
| 991 |
+
Muskan Kumar <31043527+muskanvk@users.noreply.github.com>
|
| 992 |
+
noam simcha finkelstein <noam.finkelstein@protonmail.com>
|
| 993 |
+
Garrett Folbe <gmfolbe@yahoo.com>
|
| 994 |
+
Islam Mansour <is3mansour@gmail.com>
|
| 995 |
+
Sayandip Halder <sayandiph4@gmail.com>
|
| 996 |
+
Shubham Agrawal <shubham.ag6845@gmail.com>
|
| 997 |
+
numbermaniac <5206120+numbermaniac@users.noreply.github.com>
|
| 998 |
+
Sakirul Alam <binarysakir@gmail.com>
|
| 999 |
+
Mohammed Bilal <r.mohammedbilal@gmail.com>
|
| 1000 |
+
Chris du Plessis <christopherjonduplessis@gmail.com>
|
| 1001 |
+
Coder-RG <rgoel1999@gmail.com>
|
| 1002 |
+
Ansh Mishra <anshmishra471@gmail.com>
|
| 1003 |
+
Alex Malins <github@alexmalins.com>
|
| 1004 |
+
Lorenzo Contento <lorenzo.contento@gmail.com>
|
| 1005 |
+
Naveen Sai <naveensaisreenivas@gmail.com>
|
| 1006 |
+
Shital Mule <shitalmule04@gmail.com>
|
| 1007 |
+
Amanda Dsouza <meezamanda@yahoo.com>
|
| 1008 |
+
Nijso Beishuizen <nijso@koolmees.numerically-related.com>
|
| 1009 |
+
Harry Zheng <harry@harryzheng.com>
|
| 1010 |
+
Felix Yan <felixonmars@archlinux.org>
|
| 1011 |
+
Constantin Mateescu <costica1234@me.com>
|
| 1012 |
+
Eva Tiwari <eva.tiwari@gmail.com>
|
| 1013 |
+
Aditya Kumar Sinha <adityakumar113141@gmail.com>
|
| 1014 |
+
Soumi Bardhan <51290447+Soumi7@users.noreply.github.com>
|
| 1015 |
+
Kaustubh Chaudhari <ckaustubhm06@gmail.com>
|
| 1016 |
+
Kristian Brünn <hello@kristianbrunn.com>
|
| 1017 |
+
Neel Gorasiya <mgorasiya1974@gmail.com>
|
| 1018 |
+
Akshat Sood <68052998+akshatsood2249@users.noreply.github.com>
|
| 1019 |
+
Jose M. Gomez <chemoki@gmail.com>
|
| 1020 |
+
Stefan Petrea <stefan@garage-coding.com>
|
| 1021 |
+
Praveen Sahu <povinsahu@gmail.com>
|
| 1022 |
+
Mark Bell <mark00bell@googlemail.com>
|
| 1023 |
+
AlexCQY <alex_chua@u.nus.edu>
|
| 1024 |
+
Fabian Froehlich <fabian@schaluck.com>
|
| 1025 |
+
Nikhil Gopalam <gopalamn@umich.edu>
|
| 1026 |
+
Kartik Sethi <kartiks31416@gmail.com>
|
| 1027 |
+
Muhammed Abdul Quadir Owais <quadirowais200@gmail.com>
|
| 1028 |
+
Harshit Yadav <harshityadav2k@gmail.com>
|
| 1029 |
+
Sidharth Mundhra <sidharthmundhra16@gmail.com>
|
| 1030 |
+
Suryam Arnav Kalra <suryamkalra35@gmail.com>
|
| 1031 |
+
Prince Gupta <codemastercpp@gmail.com>
|
| 1032 |
+
Kunal Singh <ksingh19136@gmail.com>
|
| 1033 |
+
Mayank Raj <mayank_1901cs35@iitp.ac.in>
|
| 1034 |
+
Achal Jain <2achaljain@gmail.com>
|
| 1035 |
+
Mario Maio <mario.maio@aruba.it>
|
| 1036 |
+
Aaron Stiff <69512633+AaronStiff@users.noreply.github.com>
|
| 1037 |
+
Wyatt Peak <wyattpeak@gmail.com>
|
| 1038 |
+
Bhaskar Joshi <bhaskar.joshi@research.iiit.ac.in>
|
| 1039 |
+
Aditya Jindal <jaditya8889@gmail.com>
|
| 1040 |
+
Vaibhav Bhat <vaibhav.bhat2097@gmail.com>
|
| 1041 |
+
Priyansh Rathi <techiepriyansh@gmail.com>
|
| 1042 |
+
Saket Kumar Singh <saketkumar1202@gmail.com>
|
| 1043 |
+
Yukai Chou <muzimuzhi@gmail.com>
|
| 1044 |
+
Qijia Liu <liumeo@pku.edu.cn>
|
| 1045 |
+
Paul Mandel <paulmandel@google.com>
|
| 1046 |
+
Nisarg Chaudhari <54911392+Nisarg-Chaudhari@users.noreply.github.com>
|
| 1047 |
+
Dominik Stańczak <stanczakdominik@gmail.com>
|
| 1048 |
+
Rodrigo Luger <rodluger@gmail.com>
|
| 1049 |
+
Marco Antônio Habitzreuter <mahabitzreuter@gmail.com>
|
| 1050 |
+
Ayush Bisht <bisht.ayush2001@gmail.com>
|
| 1051 |
+
Akshansh Bhatt <akshansh@tuta.io>
|
| 1052 |
+
Brandon T. Willard <brandonwillard@users.noreply.github.com>
|
| 1053 |
+
Thomas Aarholt <thomasaarholt@gmail.com>
|
| 1054 |
+
Hiren Chalodiya <hirenchalodiya99@gmail.com>
|
| 1055 |
+
Roland Dixon <rols121@gmail.com>
|
| 1056 |
+
dimasvq <dimas.vq.2020@bristol.ac.uk>
|
| 1057 |
+
Sagar231 <sagarfeb298@gmail.com>
|
| 1058 |
+
Michael Chu <michael02chu@gmail.com>
|
| 1059 |
+
Abby Ng <abigailjng@gmail.com>
|
| 1060 |
+
Angad Sandhu <55819847+angadsinghsandhu@users.noreply.github.com>
|
| 1061 |
+
Alexander Cockburn <alexander_cockburn12@hotmail.com>
|
| 1062 |
+
Yaser AlOsh <yaseralosh@outlook.com>
|
| 1063 |
+
Davide Sandonà <sandona.davide@gmail.com>
|
| 1064 |
+
Jonathan Gutow <gutow@uwosh.edu>
|
| 1065 |
+
Nihir Agarwal <f20180701@pilani.bits-pilani.ac.in>
|
| 1066 |
+
Lee Johnston <lee.johnston.100@gmail.com>
|
| 1067 |
+
Zach Carmichael <20629897+craymichael@users.noreply.github.com>
|
| 1068 |
+
Vijairam Ganesh Moorthy <vijairamg@gmail.com>
|
| 1069 |
+
Hanspeter Schmid <hanspeter.schmid@fhnw.ch>
|
| 1070 |
+
Ben Oostendorp <oostben@umich.edu>
|
| 1071 |
+
Nikita <nikita.student.cse19@itbhu.ac.in>
|
| 1072 |
+
Aman <amanmourya295@gmail.com>
|
| 1073 |
+
Shashank KS <shashankks0987@gmail.com>
|
| 1074 |
+
Aman Sharma <amansharma110603@gmail.com>
|
| 1075 |
+
Anup Parikh <parikhanupk@gmail.com>
|
| 1076 |
+
Lucy Mountain <lucymountain1@icloud.com>
|
| 1077 |
+
Miguel Torres Costa <miguelptcosta1995@gmail.com>
|
| 1078 |
+
Rikard Nordgren <rikard.nordgren@farmaci.uu.se>
|
| 1079 |
+
Arun sanganal <74652697+ArunSanganal@users.noreply.github.com>
|
| 1080 |
+
Kamlesh Joshi <72374645+kamleshjoshi8102@users.noreply.github.com>
|
| 1081 |
+
Joseph Rance <56409230+Joseph-Rance@users.noreply.github.com>
|
| 1082 |
+
Huangduirong <huangduirong@huawei.com>
|
| 1083 |
+
Nils Schulte <47043622+Schnilz@users.noreply.github.com>
|
| 1084 |
+
Matt Bogosian <matt@bogosian.net>
|
| 1085 |
+
Elisha Hollander <just4now666666@gmail.com>
|
| 1086 |
+
Aditya Ravuri <infprobscix@gmail.com>
|
| 1087 |
+
Mamidi Ratna Praneeth <praneethratna@gmail.com>
|
| 1088 |
+
Jeffrey Ryan <jeffaryan7@gmail.com>
|
| 1089 |
+
Jonathan Daniel <36337649+jond01@users.noreply.github.com>
|
| 1090 |
+
Robin Richard <raisin@ecomail.fr>
|
| 1091 |
+
Gautam Menghani <gum3ng@protonmail.com>
|
| 1092 |
+
Remco de Boer <29308176+redeboer@users.noreply.github.com>
|
| 1093 |
+
Sebastian East <sebastianeast@ymail.com>
|
| 1094 |
+
Evani Balasubramanyam <balasubramanyam.evani@gmail.com>
|
| 1095 |
+
Rahil Parikh <r.parikh@somaiya.edu>
|
| 1096 |
+
Jason Ross <jasonross1024@gmail.com>
|
| 1097 |
+
Joannah Nanjekye <joannah.nanjekye@ibm.com>
|
| 1098 |
+
Ayush Kumar <ayushk7102@gmail.com>
|
| 1099 |
+
Kshitij <kshitijparwani.mat18@itbhu.ac.in>
|
| 1100 |
+
Daniel Hyams <dhyams@gmail.com>
|
| 1101 |
+
alijosephine <alijosephine@gmail.com>
|
| 1102 |
+
Matthias Köppe <mkoeppe@math.ucdavis.edu>
|
| 1103 |
+
mohajain <mohajain99@gmail.com>
|
| 1104 |
+
Anibal M. Medina-Mardones <ammedmar@gmail.com>
|
| 1105 |
+
Travis Ens <ens.travis@gmail.com>
|
| 1106 |
+
Evgenia Karunus <lakesare@gmail.com>
|
| 1107 |
+
Risiraj Dey <risirajdey@gmail.com>
|
| 1108 |
+
lastcodestanding <rohang71604@gmail.com>
|
| 1109 |
+
Andrey Lekar <andrey_lekar@adoriasoft.com>
|
| 1110 |
+
Abbas Mohammed <42001049+iam-abbas@users.noreply.github.com>
|
| 1111 |
+
Anutosh Bhat <andersonbhat491@gmail.com>
|
| 1112 |
+
Steve Kieffer <sk@skieffer.info>
|
| 1113 |
+
Paul Spiering <paul@spiering.org>
|
| 1114 |
+
Pieter Gijsbers <p.gijsbers@tue.nl>
|
| 1115 |
+
Wang Ran (汪然) <wangr@smail.nju.edu.cn>
|
| 1116 |
+
naelsondouglas <naelson17@gmail.com>
|
| 1117 |
+
Aman Thakur <thakuraman22july@gmail.com>
|
| 1118 |
+
S. Hanko <suzy.hanko@gmail.com>
|
| 1119 |
+
Dennis Sweeney <sweeney.427@osu.edu>
|
| 1120 |
+
Gurpartap Singh <dhaliwal.gurpartap@gmail.com>
|
| 1121 |
+
Hampus Malmberg <hampus.malmberg88@gmail.com>
|
| 1122 |
+
scimax <max.kellermeier@hotmail.de>
|
| 1123 |
+
Nikhil Date <nikhil.s.date@gmail.com>
|
| 1124 |
+
Kuldeep Borkar Jr <kuldeepborkarjr765@gmail.com>
|
| 1125 |
+
AkuBrain <76952313+Franck2111@users.noreply.github.com>
|
| 1126 |
+
Leo Battle <leowbattle@gmail.com>
|
| 1127 |
+
Advait Pote <apote2050@gmail.com>
|
| 1128 |
+
Anurag Bhat <bhat.1@iitj.ac.in>
|
| 1129 |
+
Jeremy Monat <jemonat@calalum.org>
|
| 1130 |
+
Diane Tchuindjo <dtchuindjo@gmail.com>
|
| 1131 |
+
Tom Fryers <61272761+TomFryers@users.noreply.github.com>
|
| 1132 |
+
Zouhair <zouhair.mahboubi@gmail.com>
|
| 1133 |
+
zzj <29055749+zjzh@users.noreply.github.com>
|
| 1134 |
+
shubhayu09 <guptashubhayu601@gmail.com>
|
| 1135 |
+
Siddhant Jain <siddhantashoknagar@gmail.com>
|
| 1136 |
+
Tirthankar Mazumder <63574588+wermos@users.noreply.github.com>
|
| 1137 |
+
Sumit Kumar <mr.sumitkrr@gmail.com>
|
| 1138 |
+
Shivam Sagar <technoshivam12@gmail.com>
|
| 1139 |
+
Gaurav Jain <gjain369@gmail.com>
|
| 1140 |
+
Andrii Oriekhov <andriyorehov@gmail.com>
|
| 1141 |
+
Luis Talavera <luisfertalavera15@gmail.com>
|
| 1142 |
+
Arie Bovenberg <a.c.bovenberg@gmail.com>
|
| 1143 |
+
Carson McManus <carson.mcmanus1@gmail.com>
|
| 1144 |
+
Jack Schmidt <1107865+jackschmidt@users.noreply.github.com>
|
| 1145 |
+
Riley Britten <nrb1324@hotmail.com>
|
| 1146 |
+
Georges Khaznadar <georgesk@debian.org>
|
| 1147 |
+
Donald Wilson <donwilson1029@gmail.com>
|
| 1148 |
+
Timo Stienstra <timostienstra00@gmail.com>
|
| 1149 |
+
dispasha <dispasha@users.noreply.github.com>
|
| 1150 |
+
Saksham Alok <sakshamalok13@gmail.com>
|
| 1151 |
+
Varenyam Bhardwaj <varenyambhardwaj123@gmail.com>
|
| 1152 |
+
oittaa <8972248+oittaa@users.noreply.github.com>
|
| 1153 |
+
Omkaar <79257339+Pysics@users.noreply.github.com>
|
| 1154 |
+
Islem BOUZENIA <fi_bouzenia@esi.dz>
|
| 1155 |
+
extraymond <extraymond@gmail.com>
|
| 1156 |
+
Alexander Behrens <alex.git@gmx.net>
|
| 1157 |
+
user202729 <25191436+user202729@users.noreply.github.com>
|
| 1158 |
+
Pieter Eendebak <pieter.eendebak@gmail.com>
|
| 1159 |
+
Zaz Brown <zazbrown@zazbrown.com>
|
| 1160 |
+
ritikBhandari <ritikbhandari68@gmail.com>
|
| 1161 |
+
viocha <66580331+viocha@users.noreply.github.com>
|
| 1162 |
+
Arthur Ryman <arthur.ryman@gmail.com>
|
| 1163 |
+
Xiang Wu <hsiangwu@fb.com>
|
| 1164 |
+
tttc3 <T.Coxon2@lboro.ac.uk>
|
| 1165 |
+
Seth Poulsen <poulsenseth@yahoo.com>
|
| 1166 |
+
cocolato <haiizhu@outlook.com>
|
| 1167 |
+
Anton Golovanov <agolovanov256@gmail.com>
|
| 1168 |
+
Gareth Ma <grhkm21@gmail.com>
|
| 1169 |
+
Clément M.T. Robert <cr52@protonmail.com>
|
| 1170 |
+
Glenn Horton-Smith <glenn.hortonsmith@gmail.com>
|
| 1171 |
+
Karan <grgkaran03@gmail.com>
|
| 1172 |
+
Stefan Behnle <84378403+behnle@users.noreply.github.com>
|
| 1173 |
+
Shreyash Mishra <72146041+Shreyash-cyber@users.noreply.github.com>
|
| 1174 |
+
Arthur Milchior <arthur@milchior.fr>
|
| 1175 |
+
NotWearingPants <26556598+NotWearingPants@users.noreply.github.com>
|
| 1176 |
+
Ishan Pandhare <ishan9096137017@gmail.com>
|
| 1177 |
+
Carlos García Montoro <TrilceAC@gmail.com>
|
| 1178 |
+
Parcly Taxel <reddeloostw@gmail.com>
|
| 1179 |
+
Saicharan <saicharanhahaha@gmail.com>
|
| 1180 |
+
Kunal Sheth <kunal@kunalsheth.info>
|
| 1181 |
+
Biswadeep Purkayastha <98874428+metabiswadeep@users.noreply.github.com>
|
| 1182 |
+
Jyn Spring 琴春 <me@vx.st>
|
| 1183 |
+
Phil LeMaitre <phil_lemaitre@live.ca>
|
| 1184 |
+
Chris Kerr <chris.kerr@mykolab.ch>
|
| 1185 |
+
José Senart <jose.senart@gmail.com>
|
| 1186 |
+
Uwe L. Korn <uwelk@xhochy.com>
|
| 1187 |
+
ForeverHaibara <69423537+ForeverHaibara@users.noreply.github.com>
|
| 1188 |
+
Yves Tumushimire <yvestumushimire@gmail.com>
|
| 1189 |
+
wookie184 <wookie1840@gmail.com>
|
| 1190 |
+
Costor <pcs2009@web.de>
|
| 1191 |
+
Klaus Rettinghaus <klaus.rettinghaus@enote.com>
|
| 1192 |
+
Sam Brockie <sambrockie@icloud.com>
|
| 1193 |
+
Abhishek Patidar <1e9abhi1e10@gmail.com>
|
| 1194 |
+
Eric Demer <demer@mailbox.org>
|
| 1195 |
+
Pontus von Brömssen <pontus.vonbromssen+github@gmail.com>
|
| 1196 |
+
Victor Immanuel <chrollolucilfer1402@gmail.com>
|
| 1197 |
+
Evandro Bernardes <evbernardes@gmail.com>
|
| 1198 |
+
Michele Ceccacci <michelececcacci1@gmail.com>
|
| 1199 |
+
Ayush Aryan <ayush.aryan71@gmail.com>
|
| 1200 |
+
Kishore Gopalakrishnan <kishore96@gmail.com>
|
| 1201 |
+
Jan-Philipp Hoffmann <sonntagsgesicht@icloud.com>
|
| 1202 |
+
Daiki Takahashi <haru.td@gmail.com>
|
| 1203 |
+
Sayan Mitra <ee18b156@smail.iitm.ac.in>
|
| 1204 |
+
Aman Kumar Shukla <theprofessionalaman@gmail.com>
|
| 1205 |
+
Zoufiné Lauer-Baré <raszoufine@gmail.com>
|
| 1206 |
+
Charles Harris <erdos4d@gmail.com>
|
| 1207 |
+
Tejaswini Sanapathi <sastejaswini2002@gmail.com>
|
| 1208 |
+
Devansh <be19b002@smail.iitm.ac.in>
|
| 1209 |
+
Aaron Gokaslan <aaronGokaslan@gmail.com>
|
| 1210 |
+
Daan Koning (he/him) <daanolivierkoning@gmail.com>
|
| 1211 |
+
Steven Burns <royalstream@hotmail.com>
|
| 1212 |
+
Jay Patankar <patankarjays@gmail.com>
|
| 1213 |
+
Vivek Soni <sonisheela1977@gmail.com>
|
| 1214 |
+
Le Cong Minh Hieu <hieu.lecongminh@gmail.com>
|
| 1215 |
+
Sam Ritchie <sam@mentat.org>
|
| 1216 |
+
Maciej Skórski <maciej.skorski@gmail.com>
|
| 1217 |
+
Tilo Reneau-Cardoso <tiloreneau@gmail.com>
|
| 1218 |
+
Laurence Warne <laurencewarne@gmail.com>
|
| 1219 |
+
Lukas Molleman <Lukas.Molleman@gmail.com>
|
| 1220 |
+
Konstantinos Riganas <kostasriganas24@gmail.com>
|
| 1221 |
+
Grace Su <grace.duansu@gmail.com>
|
| 1222 |
+
Pedro Rosa <pedro_sxbr@usp.br>
|
| 1223 |
+
Abhinav Cillanki <abhinavcillanki@kgpian.iitkgp.ac.in>
|
| 1224 |
+
Baiyuan Qiu <1061688677@qq.com>
|
| 1225 |
+
Liwei Cai <cai.lw123@gmail.com>
|
| 1226 |
+
Daniel Weindl <daniel.weindl@helmholtz-muenchen.de>
|
| 1227 |
+
Isidora Araya <iarayaday@gmail.com>
|
| 1228 |
+
Seb Tiburzio <sebtiburzio@gmail.com>
|
| 1229 |
+
Victory Omole <vtomole2@gmail.com>
|
| 1230 |
+
Abhishek Chaudhary <ac5003@columbia.edu>
|
| 1231 |
+
Alexander Zhura <nice.zhura@list.ru>
|
| 1232 |
+
Shuai Zhou <shuaivzhou@berkeley.edu>
|
| 1233 |
+
Martin Manns <mmanns@gmx.net>
|
| 1234 |
+
John Möller <john.moller@outlook.com>
|
| 1235 |
+
zzc <1378113190@qq.com>
|
| 1236 |
+
Pablo Galindo Salgado <pablogsal@gmail.com>
|
| 1237 |
+
Johannes Kasimir <johannes.kasimir@math.lu.se>
|
| 1238 |
+
Theodore Dias <theodore.dias@hotmail.co.uk>
|
| 1239 |
+
Kaustubh <90597818+kaustubh-765@users.noreply.github.com>
|
| 1240 |
+
Idan Pazi <idan.kp@gmail.com>
|
| 1241 |
+
Bobby Palmer <bobbyp@umich.edu>
|
| 1242 |
+
Saikat Das <saikatdchhe@gmail.com>
|
| 1243 |
+
Suman mondal <smondal.qwerty@gmail.com>
|
| 1244 |
+
Taylan Sahin <info@taylansahin.net>
|
| 1245 |
+
Fabio Luporini <fabio@devitocodes.com>
|
| 1246 |
+
Oriel Malihi <orielmalihi1@gmail.com>
|
| 1247 |
+
Geetika Vadali <geetika.vadali4@gmail.com>
|
| 1248 |
+
Matthias Rettl <matthias.rettl@stud.unileoben.ac.at>
|
| 1249 |
+
Mikhail Remnev <maremnev@gmail.com>
|
| 1250 |
+
philwillnyc <56197213+philwillnyc@users.noreply.github.com>
|
| 1251 |
+
Raphael Lehner <raphael.lehner@gmail.com>
|
| 1252 |
+
Harry Mountain <harrymountain1@icloud.com>
|
| 1253 |
+
Bhavik Sachdev <b.sachdev1904@gmail.com>
|
| 1254 |
+
袁野 (Yuan Ye) <yuanyelele@tutanota.com>
|
| 1255 |
+
fazledyn-or <ataf@openrefactory.com>
|
| 1256 |
+
mohammedouahman <simofun85@gmail.com>
|
| 1257 |
+
K. Kraus <laqueray@googlemail.com>
|
| 1258 |
+
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
|
| 1259 |
+
platypus <platypus.computerchip@gmail.com>
|
| 1260 |
+
codecruisader <nnisarg55@gmail.com>
|
| 1261 |
+
James Whitehead <whiteheadj@gmail.com>
|
| 1262 |
+
atharvParlikar <atharvparlikar@gmail.com>
|
| 1263 |
+
Ivan Petukhov <satels@gmail.com>
|
| 1264 |
+
Augusto Borges <borges.augustoar@gmail.com>
|
| 1265 |
+
Han Wei Ang <ang.h.w@u.nus.edu>
|
| 1266 |
+
Congxu Yang <u7189828@anu.edu.au>
|
| 1267 |
+
Saicharan <62512681+saicharan2804@users.noreply.github.com>
|
| 1268 |
+
Arnab Nandi <arnabnandi2002@gmail.com>
|
| 1269 |
+
Harrison Oates <48871176+HarrisonOates@users.noreply.github.com>
|
| 1270 |
+
Corey Cerovsek <corey@cerovsek.com>
|
| 1271 |
+
Harsh Kasat <hkasat@waymore.io>
|
| 1272 |
+
omahs <73983677+omahs@users.noreply.github.com>
|
| 1273 |
+
Pascal Gitz <pascal.gitz@hotmail.ch>
|
| 1274 |
+
Ravindu-Hirimuthugoda <ravindu.18@cse.mrt.ac.lk>
|
| 1275 |
+
Sophia Pustova <tripplezzed@gmail.com>
|
| 1276 |
+
George Pittock <gpittock4@gmail.com>
|
| 1277 |
+
Warren Jacinto <warrenjacinto@gmail.com>
|
| 1278 |
+
Sachin Singh <sachinishu02@gmail.com>
|
| 1279 |
+
Zedmat <104870914+harshkasat@users.noreply.github.com>
|
| 1280 |
+
Soumendra Ganguly <soumendraganguly@gmail.com>
|
| 1281 |
+
Samith Karunathilake <55777141+samithkavishke@users.noreply.github.com>
|
| 1282 |
+
Viraj Vekaria <virajv5593@gmail.com>
|
| 1283 |
+
Shishir Kushwaha <kushwahashishir1112@gmail.com>
|
| 1284 |
+
Ankit Kumar Singh <ankitdiswar10@gmail.com>
|
| 1285 |
+
Abhishek Kumar <abhishek.nitdelhi@gmail.com>
|
| 1286 |
+
Mohak Malviya <mohakmalviya2000@gmail.com>
|
| 1287 |
+
Matthias Liesenfeld <116307294+maliesen@users.noreply.github.com>
|
| 1288 |
+
dodo <palumbododo@gmail.com>
|
| 1289 |
+
Mohamed Rezk <mohrizq895@gmail.com>
|
| 1290 |
+
Tommaso Vaccari <05-gesto-follemente@icloud.com>
|
| 1291 |
+
Alexis Schotte <alexis.schotte@gmail.com>
|
| 1292 |
+
Lauren Yim <31467609+cherryblossom000@users.noreply.github.com>
|
| 1293 |
+
Prey Patel <patel.prey@iitgn.ac.in>
|
| 1294 |
+
Riccardo Di Girolamo <riccardodigirolamo01@gmail.com>
|
| 1295 |
+
Abhishek kumar <kumar325571@gmail.com>
|
| 1296 |
+
Sam Lubelsky <sammy56lt@gmail.com>
|
| 1297 |
+
Henrique Soares <henrique.c.soares@tecnico.ulisboa.pt>
|
| 1298 |
+
Vladimir Sereda <voffch@gmail.com>
|
| 1299 |
+
Hwayeon Kang <hwayeonniii@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 |
+
Nick Harder <nharder@umich.edu>
|
| 1305 |
+
Ethan DeGuire <ethandeguire@gmail.com>
|
| 1306 |
+
Lorenz Winkler <lorenz.winkler@tuwien.ac.at>
|
| 1307 |
+
Richard Rodenbusch <rrodenbusch@gmail.com>
|
| 1308 |
+
Zhenxu Zhu <xzdlj@outlook.com>
|
| 1309 |
+
Mark van Gelder <m.j.vangelder@student.tudelft.nl>
|
| 1310 |
+
Mark van Gelder <mvgmvgmvg@live.com>
|
| 1311 |
+
Ishan Pandhare <91841626+Ishanned@users.noreply.github.com>
|
| 1312 |
+
James A. Preiss <jamesalanpreiss@gmail.com>
|
| 1313 |
+
Emile Fourcini <emile.fourcin1@gmail.com>
|
| 1314 |
+
Alberto Jiménez Ruiz <Alberto.Jimenez@uclm.es>
|
| 1315 |
+
João Bravo <joaocgbravo@tecnico.ulisboa.pt>
|
| 1316 |
+
Dean Price <dean1357price1357@gmail.com>
|
| 1317 |
+
Edward Z. Yang <ezyang@mit.edu>
|
| 1318 |
+
James Titus <titusjames299@gmail.com>
|
| 1319 |
+
Zhuoyuan Li <zy.li@stu.pku.edu.cn>
|
| 1320 |
+
Hugo Kerstens <hugo@kerstens.me>
|
| 1321 |
+
Jan Jancar <johny@neuromancer.sk>
|
| 1322 |
+
Andrew Mosson <amosson@yahoo.com>
|
| 1323 |
+
Marek Madejski <marekmadejski@yandex.com>
|
| 1324 |
+
Gonzalo Tornaría <tornaria@cmat.edu.uy>
|
| 1325 |
+
Peter Stahlecker <peter.stahlecker@gmail.com>
|
| 1326 |
+
Jean-François B <2589111+jfbu@users.noreply.github.com>
|
| 1327 |
+
Zexuan Zhou (Bruce) <zzx498636727@gmail.com>
|
| 1328 |
+
George Frolov <gosha@fro.lv>
|
| 1329 |
+
Corbet Elkins <corbet286@gmail.com>
|
| 1330 |
+
Håkon Kvernmoen <haakon.kvernmoen@gmail.com>
|
| 1331 |
+
Muhammad Maaz <mmaaz6004@gmail.com>
|
| 1332 |
+
Shishir Kushwaha <138311586+shishir-11@users.noreply.github.com>
|
| 1333 |
+
Matt Wang <mattwang44@gmail.com>
|
| 1334 |
+
bharatAmeria <21001019007@jcboseust.ac.in>
|
| 1335 |
+
Amir Ebrahimi <github@aebrahimi.com>
|
| 1336 |
+
Steven Esquea <steven.esquea@irreverente.net>
|
| 1337 |
+
Rishabh Kamboj <111004091+VectorNd@users.noreply.github.com>
|
| 1338 |
+
Aasim Ali <aasim250205@gmail.com>
|
| 1339 |
+
Ivan A. Melnikov <iv@altlinux.org>
|
| 1340 |
+
Borek Saheli <boreksaheli@gmail.com>
|
| 1341 |
+
Guido Roncarolo <guido.roncarolo@gmail.com>
|
| 1342 |
+
Quek Zi Yao <ziyaoqzy2001@gmail.com>
|
| 1343 |
+
Roelof Rietbroek <r.rietbroek@utwente.nl>
|
| 1344 |
+
MostafaGalal1 <mostafag649.mg@gmail.com>
|
| 1345 |
+
Au Huishan <huishan_au@outlook.com>
|
| 1346 |
+
Kris Katterjohn <katterjohn@gmail.com>
|
| 1347 |
+
Shiyao Guo <mivikq@gmail.com>
|
| 1348 |
+
Rushabh Mehta <mehtarushabh2005@gmail.com>
|
| 1349 |
+
Temiloluwa Yusuf ytemiloluwa@gmail.com ytemiloluwa <ytemiloluwa@gmail.com>
|
| 1350 |
+
Davi Laerte <davilae011@gmail.com>
|
| 1351 |
+
Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
|
| 1352 |
+
Harshit Gupta <harshithigh2001@gmail.com>
|
| 1353 |
+
Praveen Perumal <ppraveen98841@gmail.com>
|
| 1354 |
+
Kevin McWhirter <klmcw@yahoo.com>
|
| 1355 |
+
Prayag V <v.prayag2005@gmail.com>
|
| 1356 |
+
Lucas Kletzander <lucas.kletzander@gmail.com>
|
| 1357 |
+
Pratyksh Gupta <pratykshgupta9999@gmail.com>
|
| 1358 |
+
Leonardo Mangani <leomangani4@gmail.com>
|
| 1359 |
+
Karan Anand <anandkarancompsci@gmail.com>
|
| 1360 |
+
Gagan Mishra <simonsimple305@gmail.com>
|
| 1361 |
+
Krishnav Bajoria <bajoriakrishnav@gmail.com>
|
| 1362 |
+
Matt Ord <matthew.ord1@gmail.com>
|
| 1363 |
+
Jatin Bhardwaj <bhardwajjatin093@gmail.com>
|
| 1364 |
+
Prashant Tandon <tandonprashant101@gmail.com>
|
| 1365 |
+
Paramjit Singh <paramjit1071@gmail.com>
|
| 1366 |
+
João Rodrigues <abcjoao@hotmail.com>
|
| 1367 |
+
Alejandro García Prada <114813960+AlexGarciaPrada@users.noreply.github.com>
|
| 1368 |
+
Matthew Treinish <mtreinish@kortar.org>
|
| 1369 |
+
Clayton Rabideau <claytonrabideau@gmail.com>
|
| 1370 |
+
Victoria Koval <bictoriakoval16@gmail.com>
|
| 1371 |
+
Voaides Negustor Robert <134785947+voaidesr@users.noreply.github.com>
|
| 1372 |
+
Ovsk Mendov <bbb23exposed@gmail.com>
|
| 1373 |
+
David Brooks <dave@bcs.co.nz>
|
| 1374 |
+
Nicholas Laustrup <124007393+nicklaustrup@users.noreply.github.com>
|
| 1375 |
+
Harikrishna Srinivasan <harikrishnasri3@gmail.com>
|
| 1376 |
+
Mathis Cros <mathis.cros@telecom-paris.fr>
|
| 1377 |
+
Arnav Mummineni <45217840+RCoder01@users.noreply.github.com>
|
| 1378 |
+
Thangaraju Sibiraj <85477603+t-sibiraj@users.noreply.github.com>
|
| 1379 |
+
KJaybhaye <krushnajaybhaye01@gmail.com>
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/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.
|
hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
isympy
|
| 2 |
+
sympy
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/sample_scipy.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from functools import singledispatch
|
| 2 |
+
|
| 3 |
+
from sympy.core.symbol import Dummy
|
| 4 |
+
from sympy.functions.elementary.exponential import exp
|
| 5 |
+
from sympy.utilities.lambdify import lambdify
|
| 6 |
+
from sympy.external import import_module
|
| 7 |
+
from sympy.stats import DiscreteDistributionHandmade
|
| 8 |
+
from sympy.stats.crv import SingleContinuousDistribution
|
| 9 |
+
from sympy.stats.crv_types import ChiSquaredDistribution, ExponentialDistribution, GammaDistribution, \
|
| 10 |
+
LogNormalDistribution, NormalDistribution, ParetoDistribution, UniformDistribution, BetaDistribution, \
|
| 11 |
+
StudentTDistribution, CauchyDistribution
|
| 12 |
+
from sympy.stats.drv_types import GeometricDistribution, LogarithmicDistribution, NegativeBinomialDistribution, \
|
| 13 |
+
PoissonDistribution, SkellamDistribution, YuleSimonDistribution, ZetaDistribution
|
| 14 |
+
from sympy.stats.frv import SingleFiniteDistribution
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
scipy = import_module("scipy", import_kwargs={'fromlist':['stats']})
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@singledispatch
|
| 21 |
+
def do_sample_scipy(dist, size, seed):
|
| 22 |
+
return None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# CRV
|
| 26 |
+
|
| 27 |
+
@do_sample_scipy.register(SingleContinuousDistribution)
|
| 28 |
+
def _(dist: SingleContinuousDistribution, size, seed):
|
| 29 |
+
# if we don't need to make a handmade pdf, we won't
|
| 30 |
+
import scipy.stats
|
| 31 |
+
|
| 32 |
+
z = Dummy('z')
|
| 33 |
+
handmade_pdf = lambdify(z, dist.pdf(z), ['numpy', 'scipy'])
|
| 34 |
+
|
| 35 |
+
class scipy_pdf(scipy.stats.rv_continuous):
|
| 36 |
+
def _pdf(dist, x):
|
| 37 |
+
return handmade_pdf(x)
|
| 38 |
+
|
| 39 |
+
scipy_rv = scipy_pdf(a=float(dist.set._inf),
|
| 40 |
+
b=float(dist.set._sup), name='scipy_pdf')
|
| 41 |
+
return scipy_rv.rvs(size=size, random_state=seed)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
@do_sample_scipy.register(ChiSquaredDistribution)
|
| 45 |
+
def _(dist: ChiSquaredDistribution, size, seed):
|
| 46 |
+
# same parametrisation
|
| 47 |
+
return scipy.stats.chi2.rvs(df=float(dist.k), size=size, random_state=seed)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
@do_sample_scipy.register(ExponentialDistribution)
|
| 51 |
+
def _(dist: ExponentialDistribution, size, seed):
|
| 52 |
+
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.expon.html#scipy.stats.expon
|
| 53 |
+
return scipy.stats.expon.rvs(scale=1 / float(dist.rate), size=size, random_state=seed)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@do_sample_scipy.register(GammaDistribution)
|
| 57 |
+
def _(dist: GammaDistribution, size, seed):
|
| 58 |
+
# https://stackoverflow.com/questions/42150965/how-to-plot-gamma-distribution-with-alpha-and-beta-parameters-in-python
|
| 59 |
+
return scipy.stats.gamma.rvs(a=float(dist.k), scale=float(dist.theta), size=size, random_state=seed)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
@do_sample_scipy.register(LogNormalDistribution)
|
| 63 |
+
def _(dist: LogNormalDistribution, size, seed):
|
| 64 |
+
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.lognorm.html
|
| 65 |
+
return scipy.stats.lognorm.rvs(scale=float(exp(dist.mean)), s=float(dist.std), size=size, random_state=seed)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
@do_sample_scipy.register(NormalDistribution)
|
| 69 |
+
def _(dist: NormalDistribution, size, seed):
|
| 70 |
+
return scipy.stats.norm.rvs(loc=float(dist.mean), scale=float(dist.std), size=size, random_state=seed)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
@do_sample_scipy.register(ParetoDistribution)
|
| 74 |
+
def _(dist: ParetoDistribution, size, seed):
|
| 75 |
+
# https://stackoverflow.com/questions/42260519/defining-pareto-distribution-in-python-scipy
|
| 76 |
+
return scipy.stats.pareto.rvs(b=float(dist.alpha), scale=float(dist.xm), size=size, random_state=seed)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
@do_sample_scipy.register(StudentTDistribution)
|
| 80 |
+
def _(dist: StudentTDistribution, size, seed):
|
| 81 |
+
return scipy.stats.t.rvs(df=float(dist.nu), size=size, random_state=seed)
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
@do_sample_scipy.register(UniformDistribution)
|
| 85 |
+
def _(dist: UniformDistribution, size, seed):
|
| 86 |
+
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.uniform.html
|
| 87 |
+
return scipy.stats.uniform.rvs(loc=float(dist.left), scale=float(dist.right - dist.left), size=size, random_state=seed)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
@do_sample_scipy.register(BetaDistribution)
|
| 91 |
+
def _(dist: BetaDistribution, size, seed):
|
| 92 |
+
# same parametrisation
|
| 93 |
+
return scipy.stats.beta.rvs(a=float(dist.alpha), b=float(dist.beta), size=size, random_state=seed)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
@do_sample_scipy.register(CauchyDistribution)
|
| 97 |
+
def _(dist: CauchyDistribution, size, seed):
|
| 98 |
+
return scipy.stats.cauchy.rvs(loc=float(dist.x0), scale=float(dist.gamma), size=size, random_state=seed)
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
# DRV:
|
| 102 |
+
|
| 103 |
+
@do_sample_scipy.register(DiscreteDistributionHandmade)
|
| 104 |
+
def _(dist: DiscreteDistributionHandmade, size, seed):
|
| 105 |
+
from scipy.stats import rv_discrete
|
| 106 |
+
|
| 107 |
+
z = Dummy('z')
|
| 108 |
+
handmade_pmf = lambdify(z, dist.pdf(z), ['numpy', 'scipy'])
|
| 109 |
+
|
| 110 |
+
class scipy_pmf(rv_discrete):
|
| 111 |
+
def _pmf(dist, x):
|
| 112 |
+
return handmade_pmf(x)
|
| 113 |
+
|
| 114 |
+
scipy_rv = scipy_pmf(a=float(dist.set._inf), b=float(dist.set._sup),
|
| 115 |
+
name='scipy_pmf')
|
| 116 |
+
return scipy_rv.rvs(size=size, random_state=seed)
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
@do_sample_scipy.register(GeometricDistribution)
|
| 120 |
+
def _(dist: GeometricDistribution, size, seed):
|
| 121 |
+
return scipy.stats.geom.rvs(p=float(dist.p), size=size, random_state=seed)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
@do_sample_scipy.register(LogarithmicDistribution)
|
| 125 |
+
def _(dist: LogarithmicDistribution, size, seed):
|
| 126 |
+
return scipy.stats.logser.rvs(p=float(dist.p), size=size, random_state=seed)
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@do_sample_scipy.register(NegativeBinomialDistribution)
|
| 130 |
+
def _(dist: NegativeBinomialDistribution, size, seed):
|
| 131 |
+
return scipy.stats.nbinom.rvs(n=float(dist.r), p=float(dist.p), size=size, random_state=seed)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
@do_sample_scipy.register(PoissonDistribution)
|
| 135 |
+
def _(dist: PoissonDistribution, size, seed):
|
| 136 |
+
return scipy.stats.poisson.rvs(mu=float(dist.lamda), size=size, random_state=seed)
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
@do_sample_scipy.register(SkellamDistribution)
|
| 140 |
+
def _(dist: SkellamDistribution, size, seed):
|
| 141 |
+
return scipy.stats.skellam.rvs(mu1=float(dist.mu1), mu2=float(dist.mu2), size=size, random_state=seed)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
@do_sample_scipy.register(YuleSimonDistribution)
|
| 145 |
+
def _(dist: YuleSimonDistribution, size, seed):
|
| 146 |
+
return scipy.stats.yulesimon.rvs(alpha=float(dist.rho), size=size, random_state=seed)
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
@do_sample_scipy.register(ZetaDistribution)
|
| 150 |
+
def _(dist: ZetaDistribution, size, seed):
|
| 151 |
+
return scipy.stats.zipf.rvs(a=float(dist.s), size=size, random_state=seed)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
# FRV:
|
| 155 |
+
|
| 156 |
+
@do_sample_scipy.register(SingleFiniteDistribution)
|
| 157 |
+
def _(dist: SingleFiniteDistribution, size, seed):
|
| 158 |
+
# scipy can handle with custom distributions
|
| 159 |
+
|
| 160 |
+
from scipy.stats import rv_discrete
|
| 161 |
+
density_ = dist.dict
|
| 162 |
+
x, y = [], []
|
| 163 |
+
for k, v in density_.items():
|
| 164 |
+
x.append(int(k))
|
| 165 |
+
y.append(float(v))
|
| 166 |
+
scipy_rv = rv_discrete(name='scipy_rv', values=(x, y))
|
| 167 |
+
return scipy_rv.rvs(size=size, random_state=seed)
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__init__.py
ADDED
|
File without changes
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (193 Bytes). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_continuous_rv.cpython-312.pyc
ADDED
|
Binary file (9.86 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_discrete_rv.cpython-312.pyc
ADDED
|
Binary file (5.61 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_finite_rv.cpython-312.pyc
ADDED
|
Binary file (5.34 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_continuous_rv.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.numbers import oo
|
| 2 |
+
from sympy.core.symbol import Symbol
|
| 3 |
+
from sympy.functions.elementary.exponential import exp
|
| 4 |
+
from sympy.sets.sets import Interval
|
| 5 |
+
from sympy.external import import_module
|
| 6 |
+
from sympy.stats import Beta, Chi, Normal, Gamma, Exponential, LogNormal, Pareto, ChiSquared, Uniform, sample, \
|
| 7 |
+
BetaPrime, Cauchy, GammaInverse, GaussianInverse, StudentT, Weibull, density, ContinuousRV, FDistribution, \
|
| 8 |
+
Gumbel, Laplace, Logistic, Rayleigh, Triangular
|
| 9 |
+
from sympy.testing.pytest import skip, raises
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def test_sample_numpy():
|
| 13 |
+
distribs_numpy = [
|
| 14 |
+
Beta("B", 1, 1),
|
| 15 |
+
Normal("N", 0, 1),
|
| 16 |
+
Gamma("G", 2, 7),
|
| 17 |
+
Exponential("E", 2),
|
| 18 |
+
LogNormal("LN", 0, 1),
|
| 19 |
+
Pareto("P", 1, 1),
|
| 20 |
+
ChiSquared("CS", 2),
|
| 21 |
+
Uniform("U", 0, 1),
|
| 22 |
+
FDistribution("FD", 1, 2),
|
| 23 |
+
Gumbel("GB", 1, 2),
|
| 24 |
+
Laplace("L", 1, 2),
|
| 25 |
+
Logistic("LO", 1, 2),
|
| 26 |
+
Rayleigh("R", 1),
|
| 27 |
+
Triangular("T", 1, 2, 2),
|
| 28 |
+
]
|
| 29 |
+
size = 3
|
| 30 |
+
numpy = import_module('numpy')
|
| 31 |
+
if not numpy:
|
| 32 |
+
skip('Numpy is not installed. Abort tests for _sample_numpy.')
|
| 33 |
+
else:
|
| 34 |
+
for X in distribs_numpy:
|
| 35 |
+
samps = sample(X, size=size, library='numpy')
|
| 36 |
+
for sam in samps:
|
| 37 |
+
assert sam in X.pspace.domain.set
|
| 38 |
+
raises(NotImplementedError,
|
| 39 |
+
lambda: sample(Chi("C", 1), library='numpy'))
|
| 40 |
+
raises(NotImplementedError,
|
| 41 |
+
lambda: Chi("C", 1).pspace.distribution.sample(library='tensorflow'))
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def test_sample_scipy():
|
| 45 |
+
distribs_scipy = [
|
| 46 |
+
Beta("B", 1, 1),
|
| 47 |
+
BetaPrime("BP", 1, 1),
|
| 48 |
+
Cauchy("C", 1, 1),
|
| 49 |
+
Chi("C", 1),
|
| 50 |
+
Normal("N", 0, 1),
|
| 51 |
+
Gamma("G", 2, 7),
|
| 52 |
+
GammaInverse("GI", 1, 1),
|
| 53 |
+
GaussianInverse("GUI", 1, 1),
|
| 54 |
+
Exponential("E", 2),
|
| 55 |
+
LogNormal("LN", 0, 1),
|
| 56 |
+
Pareto("P", 1, 1),
|
| 57 |
+
StudentT("S", 2),
|
| 58 |
+
ChiSquared("CS", 2),
|
| 59 |
+
Uniform("U", 0, 1)
|
| 60 |
+
]
|
| 61 |
+
size = 3
|
| 62 |
+
scipy = import_module('scipy')
|
| 63 |
+
if not scipy:
|
| 64 |
+
skip('Scipy is not installed. Abort tests for _sample_scipy.')
|
| 65 |
+
else:
|
| 66 |
+
for X in distribs_scipy:
|
| 67 |
+
samps = sample(X, size=size, library='scipy')
|
| 68 |
+
samps2 = sample(X, size=(2, 2), library='scipy')
|
| 69 |
+
for sam in samps:
|
| 70 |
+
assert sam in X.pspace.domain.set
|
| 71 |
+
for i in range(2):
|
| 72 |
+
for j in range(2):
|
| 73 |
+
assert samps2[i][j] in X.pspace.domain.set
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_sample_pymc():
|
| 77 |
+
distribs_pymc = [
|
| 78 |
+
Beta("B", 1, 1),
|
| 79 |
+
Cauchy("C", 1, 1),
|
| 80 |
+
Normal("N", 0, 1),
|
| 81 |
+
Gamma("G", 2, 7),
|
| 82 |
+
GaussianInverse("GI", 1, 1),
|
| 83 |
+
Exponential("E", 2),
|
| 84 |
+
LogNormal("LN", 0, 1),
|
| 85 |
+
Pareto("P", 1, 1),
|
| 86 |
+
ChiSquared("CS", 2),
|
| 87 |
+
Uniform("U", 0, 1)
|
| 88 |
+
]
|
| 89 |
+
size = 3
|
| 90 |
+
pymc = import_module('pymc')
|
| 91 |
+
if not pymc:
|
| 92 |
+
skip('PyMC is not installed. Abort tests for _sample_pymc.')
|
| 93 |
+
else:
|
| 94 |
+
for X in distribs_pymc:
|
| 95 |
+
samps = sample(X, size=size, library='pymc')
|
| 96 |
+
for sam in samps:
|
| 97 |
+
assert sam in X.pspace.domain.set
|
| 98 |
+
raises(NotImplementedError,
|
| 99 |
+
lambda: sample(Chi("C", 1), library='pymc'))
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def test_sampling_gamma_inverse():
|
| 103 |
+
scipy = import_module('scipy')
|
| 104 |
+
if not scipy:
|
| 105 |
+
skip('Scipy not installed. Abort tests for sampling of gamma inverse.')
|
| 106 |
+
X = GammaInverse("x", 1, 1)
|
| 107 |
+
assert sample(X) in X.pspace.domain.set
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def test_lognormal_sampling():
|
| 111 |
+
# Right now, only density function and sampling works
|
| 112 |
+
scipy = import_module('scipy')
|
| 113 |
+
if not scipy:
|
| 114 |
+
skip('Scipy is not installed. Abort tests')
|
| 115 |
+
for i in range(3):
|
| 116 |
+
X = LogNormal('x', i, 1)
|
| 117 |
+
assert sample(X) in X.pspace.domain.set
|
| 118 |
+
|
| 119 |
+
size = 5
|
| 120 |
+
samps = sample(X, size=size)
|
| 121 |
+
for samp in samps:
|
| 122 |
+
assert samp in X.pspace.domain.set
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def test_sampling_gaussian_inverse():
|
| 126 |
+
scipy = import_module('scipy')
|
| 127 |
+
if not scipy:
|
| 128 |
+
skip('Scipy not installed. Abort tests for sampling of Gaussian inverse.')
|
| 129 |
+
X = GaussianInverse("x", 1, 1)
|
| 130 |
+
assert sample(X, library='scipy') in X.pspace.domain.set
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def test_prefab_sampling():
|
| 134 |
+
scipy = import_module('scipy')
|
| 135 |
+
if not scipy:
|
| 136 |
+
skip('Scipy is not installed. Abort tests')
|
| 137 |
+
N = Normal('X', 0, 1)
|
| 138 |
+
L = LogNormal('L', 0, 1)
|
| 139 |
+
E = Exponential('Ex', 1)
|
| 140 |
+
P = Pareto('P', 1, 3)
|
| 141 |
+
W = Weibull('W', 1, 1)
|
| 142 |
+
U = Uniform('U', 0, 1)
|
| 143 |
+
B = Beta('B', 2, 5)
|
| 144 |
+
G = Gamma('G', 1, 3)
|
| 145 |
+
|
| 146 |
+
variables = [N, L, E, P, W, U, B, G]
|
| 147 |
+
niter = 10
|
| 148 |
+
size = 5
|
| 149 |
+
for var in variables:
|
| 150 |
+
for _ in range(niter):
|
| 151 |
+
assert sample(var) in var.pspace.domain.set
|
| 152 |
+
samps = sample(var, size=size)
|
| 153 |
+
for samp in samps:
|
| 154 |
+
assert samp in var.pspace.domain.set
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def test_sample_continuous():
|
| 158 |
+
z = Symbol('z')
|
| 159 |
+
Z = ContinuousRV(z, exp(-z), set=Interval(0, oo))
|
| 160 |
+
assert density(Z)(-1) == 0
|
| 161 |
+
|
| 162 |
+
scipy = import_module('scipy')
|
| 163 |
+
if not scipy:
|
| 164 |
+
skip('Scipy is not installed. Abort tests')
|
| 165 |
+
assert sample(Z) in Z.pspace.domain.set
|
| 166 |
+
sym, val = list(Z.pspace.sample().items())[0]
|
| 167 |
+
assert sym == Z and val in Interval(0, oo)
|
| 168 |
+
|
| 169 |
+
libraries = ['scipy', 'numpy', 'pymc']
|
| 170 |
+
for lib in libraries:
|
| 171 |
+
try:
|
| 172 |
+
imported_lib = import_module(lib)
|
| 173 |
+
if imported_lib:
|
| 174 |
+
s0, s1, s2 = [], [], []
|
| 175 |
+
s0 = sample(Z, size=10, library=lib, seed=0)
|
| 176 |
+
s1 = sample(Z, size=10, library=lib, seed=0)
|
| 177 |
+
s2 = sample(Z, size=10, library=lib, seed=1)
|
| 178 |
+
assert all(s0 == s1)
|
| 179 |
+
assert all(s1 != s2)
|
| 180 |
+
except NotImplementedError:
|
| 181 |
+
continue
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_discrete_rv.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.singleton import S
|
| 2 |
+
from sympy.core.symbol import Symbol
|
| 3 |
+
from sympy.external import import_module
|
| 4 |
+
from sympy.stats import (
|
| 5 |
+
Geometric,
|
| 6 |
+
Poisson,
|
| 7 |
+
Zeta,
|
| 8 |
+
sample,
|
| 9 |
+
Skellam,
|
| 10 |
+
Logarithmic,
|
| 11 |
+
NegativeBinomial,
|
| 12 |
+
YuleSimon,
|
| 13 |
+
DiscreteRV,
|
| 14 |
+
)
|
| 15 |
+
from sympy.testing.pytest import skip, raises, slow
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def test_sample_numpy():
|
| 19 |
+
distribs_numpy = [
|
| 20 |
+
Geometric('G', 0.5),
|
| 21 |
+
Poisson('P', 1),
|
| 22 |
+
Zeta('Z', 2)
|
| 23 |
+
]
|
| 24 |
+
size = 3
|
| 25 |
+
numpy = import_module('numpy')
|
| 26 |
+
if not numpy:
|
| 27 |
+
skip('Numpy is not installed. Abort tests for _sample_numpy.')
|
| 28 |
+
else:
|
| 29 |
+
for X in distribs_numpy:
|
| 30 |
+
samps = sample(X, size=size, library='numpy')
|
| 31 |
+
for sam in samps:
|
| 32 |
+
assert sam in X.pspace.domain.set
|
| 33 |
+
raises(NotImplementedError,
|
| 34 |
+
lambda: sample(Skellam('S', 1, 1), library='numpy'))
|
| 35 |
+
raises(NotImplementedError,
|
| 36 |
+
lambda: Skellam('S', 1, 1).pspace.distribution.sample(library='tensorflow'))
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_sample_scipy():
|
| 40 |
+
p = S(2)/3
|
| 41 |
+
x = Symbol('x', integer=True, positive=True)
|
| 42 |
+
pdf = p*(1 - p)**(x - 1) # pdf of Geometric Distribution
|
| 43 |
+
distribs_scipy = [
|
| 44 |
+
DiscreteRV(x, pdf, set=S.Naturals),
|
| 45 |
+
Geometric('G', 0.5),
|
| 46 |
+
Logarithmic('L', 0.5),
|
| 47 |
+
NegativeBinomial('N', 5, 0.4),
|
| 48 |
+
Poisson('P', 1),
|
| 49 |
+
Skellam('S', 1, 1),
|
| 50 |
+
YuleSimon('Y', 1),
|
| 51 |
+
Zeta('Z', 2)
|
| 52 |
+
]
|
| 53 |
+
size = 3
|
| 54 |
+
scipy = import_module('scipy')
|
| 55 |
+
if not scipy:
|
| 56 |
+
skip('Scipy is not installed. Abort tests for _sample_scipy.')
|
| 57 |
+
else:
|
| 58 |
+
for X in distribs_scipy:
|
| 59 |
+
samps = sample(X, size=size, library='scipy')
|
| 60 |
+
samps2 = sample(X, size=(2, 2), library='scipy')
|
| 61 |
+
for sam in samps:
|
| 62 |
+
assert sam in X.pspace.domain.set
|
| 63 |
+
for i in range(2):
|
| 64 |
+
for j in range(2):
|
| 65 |
+
assert samps2[i][j] in X.pspace.domain.set
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def test_sample_pymc():
|
| 69 |
+
distribs_pymc = [
|
| 70 |
+
Geometric('G', 0.5),
|
| 71 |
+
Poisson('P', 1),
|
| 72 |
+
NegativeBinomial('N', 5, 0.4)
|
| 73 |
+
]
|
| 74 |
+
size = 3
|
| 75 |
+
pymc = import_module('pymc')
|
| 76 |
+
if not pymc:
|
| 77 |
+
skip('PyMC is not installed. Abort tests for _sample_pymc.')
|
| 78 |
+
else:
|
| 79 |
+
for X in distribs_pymc:
|
| 80 |
+
samps = sample(X, size=size, library='pymc')
|
| 81 |
+
for sam in samps:
|
| 82 |
+
assert sam in X.pspace.domain.set
|
| 83 |
+
raises(NotImplementedError,
|
| 84 |
+
lambda: sample(Skellam('S', 1, 1), library='pymc'))
|
| 85 |
+
|
| 86 |
+
@slow
|
| 87 |
+
def test_sample_discrete():
|
| 88 |
+
X = Geometric('X', S.Half)
|
| 89 |
+
scipy = import_module('scipy')
|
| 90 |
+
if not scipy:
|
| 91 |
+
skip('Scipy not installed. Abort tests')
|
| 92 |
+
assert sample(X) in X.pspace.domain.set
|
| 93 |
+
samps = sample(X, size=2) # This takes long time if ran without scipy
|
| 94 |
+
for samp in samps:
|
| 95 |
+
assert samp in X.pspace.domain.set
|
| 96 |
+
|
| 97 |
+
libraries = ['scipy', 'numpy', 'pymc']
|
| 98 |
+
for lib in libraries:
|
| 99 |
+
try:
|
| 100 |
+
imported_lib = import_module(lib)
|
| 101 |
+
if imported_lib:
|
| 102 |
+
s0, s1, s2 = [], [], []
|
| 103 |
+
s0 = sample(X, size=10, library=lib, seed=0)
|
| 104 |
+
s1 = sample(X, size=10, library=lib, seed=0)
|
| 105 |
+
s2 = sample(X, size=10, library=lib, seed=1)
|
| 106 |
+
assert all(s0 == s1)
|
| 107 |
+
assert not all(s1 == s2)
|
| 108 |
+
except NotImplementedError:
|
| 109 |
+
continue
|
hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_finite_rv.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.numbers import Rational
|
| 2 |
+
from sympy.core.singleton import S
|
| 3 |
+
from sympy.external import import_module
|
| 4 |
+
from sympy.stats import Binomial, sample, Die, FiniteRV, DiscreteUniform, Bernoulli, BetaBinomial, Hypergeometric, \
|
| 5 |
+
Rademacher
|
| 6 |
+
from sympy.testing.pytest import skip, raises
|
| 7 |
+
|
| 8 |
+
def test_given_sample():
|
| 9 |
+
X = Die('X', 6)
|
| 10 |
+
scipy = import_module('scipy')
|
| 11 |
+
if not scipy:
|
| 12 |
+
skip('Scipy is not installed. Abort tests')
|
| 13 |
+
assert sample(X, X > 5) == 6
|
| 14 |
+
|
| 15 |
+
def test_sample_numpy():
|
| 16 |
+
distribs_numpy = [
|
| 17 |
+
Binomial("B", 5, 0.4),
|
| 18 |
+
Hypergeometric("H", 2, 1, 1)
|
| 19 |
+
]
|
| 20 |
+
size = 3
|
| 21 |
+
numpy = import_module('numpy')
|
| 22 |
+
if not numpy:
|
| 23 |
+
skip('Numpy is not installed. Abort tests for _sample_numpy.')
|
| 24 |
+
else:
|
| 25 |
+
for X in distribs_numpy:
|
| 26 |
+
samps = sample(X, size=size, library='numpy')
|
| 27 |
+
for sam in samps:
|
| 28 |
+
assert sam in X.pspace.domain.set
|
| 29 |
+
raises(NotImplementedError,
|
| 30 |
+
lambda: sample(Die("D"), library='numpy'))
|
| 31 |
+
raises(NotImplementedError,
|
| 32 |
+
lambda: Die("D").pspace.sample(library='tensorflow'))
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def test_sample_scipy():
|
| 36 |
+
distribs_scipy = [
|
| 37 |
+
FiniteRV('F', {1: S.Half, 2: Rational(1, 4), 3: Rational(1, 4)}),
|
| 38 |
+
DiscreteUniform("Y", list(range(5))),
|
| 39 |
+
Die("D"),
|
| 40 |
+
Bernoulli("Be", 0.3),
|
| 41 |
+
Binomial("Bi", 5, 0.4),
|
| 42 |
+
BetaBinomial("Bb", 2, 1, 1),
|
| 43 |
+
Hypergeometric("H", 1, 1, 1),
|
| 44 |
+
Rademacher("R")
|
| 45 |
+
]
|
| 46 |
+
|
| 47 |
+
size = 3
|
| 48 |
+
scipy = import_module('scipy')
|
| 49 |
+
if not scipy:
|
| 50 |
+
skip('Scipy not installed. Abort tests for _sample_scipy.')
|
| 51 |
+
else:
|
| 52 |
+
for X in distribs_scipy:
|
| 53 |
+
samps = sample(X, size=size)
|
| 54 |
+
samps2 = sample(X, size=(2, 2))
|
| 55 |
+
for sam in samps:
|
| 56 |
+
assert sam in X.pspace.domain.set
|
| 57 |
+
for i in range(2):
|
| 58 |
+
for j in range(2):
|
| 59 |
+
assert samps2[i][j] in X.pspace.domain.set
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def test_sample_pymc():
|
| 63 |
+
distribs_pymc = [
|
| 64 |
+
Bernoulli('B', 0.2),
|
| 65 |
+
Binomial('N', 5, 0.4)
|
| 66 |
+
]
|
| 67 |
+
size = 3
|
| 68 |
+
pymc = import_module('pymc')
|
| 69 |
+
if not pymc:
|
| 70 |
+
skip('PyMC is not installed. Abort tests for _sample_pymc.')
|
| 71 |
+
else:
|
| 72 |
+
for X in distribs_pymc:
|
| 73 |
+
samps = sample(X, size=size, library='pymc')
|
| 74 |
+
for sam in samps:
|
| 75 |
+
assert sam in X.pspace.domain.set
|
| 76 |
+
raises(NotImplementedError,
|
| 77 |
+
lambda: (sample(Die("D"), library='pymc')))
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_sample_seed():
|
| 81 |
+
F = FiniteRV('F', {1: S.Half, 2: Rational(1, 4), 3: Rational(1, 4)})
|
| 82 |
+
size = 10
|
| 83 |
+
libraries = ['scipy', 'numpy', 'pymc']
|
| 84 |
+
for lib in libraries:
|
| 85 |
+
try:
|
| 86 |
+
imported_lib = import_module(lib)
|
| 87 |
+
if imported_lib:
|
| 88 |
+
s0 = sample(F, size=size, library=lib, seed=0)
|
| 89 |
+
s1 = sample(F, size=size, library=lib, seed=0)
|
| 90 |
+
s2 = sample(F, size=size, library=lib, seed=1)
|
| 91 |
+
assert all(s0 == s1)
|
| 92 |
+
assert not all(s1 == s2)
|
| 93 |
+
except NotImplementedError:
|
| 94 |
+
continue
|
hug/lib/python3.12/site-packages/sympy/stats/stochastic_process.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.basic import Basic
|
| 2 |
+
from sympy.stats.joint_rv import ProductPSpace
|
| 3 |
+
from sympy.stats.rv import ProductDomain, _symbol_converter, Distribution
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class StochasticPSpace(ProductPSpace):
|
| 7 |
+
"""
|
| 8 |
+
Represents probability space of stochastic processes
|
| 9 |
+
and their random variables. Contains mechanics to do
|
| 10 |
+
computations for queries of stochastic processes.
|
| 11 |
+
|
| 12 |
+
Explanation
|
| 13 |
+
===========
|
| 14 |
+
|
| 15 |
+
Initialized by symbol, the specific process and
|
| 16 |
+
distribution(optional) if the random indexed symbols
|
| 17 |
+
of the process follows any specific distribution, like,
|
| 18 |
+
in Bernoulli Process, each random indexed symbol follows
|
| 19 |
+
Bernoulli distribution. For processes with memory, this
|
| 20 |
+
parameter should not be passed.
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
def __new__(cls, sym, process, distribution=None):
|
| 24 |
+
sym = _symbol_converter(sym)
|
| 25 |
+
from sympy.stats.stochastic_process_types import StochasticProcess
|
| 26 |
+
if not isinstance(process, StochasticProcess):
|
| 27 |
+
raise TypeError("`process` must be an instance of StochasticProcess.")
|
| 28 |
+
if distribution is None:
|
| 29 |
+
distribution = Distribution()
|
| 30 |
+
return Basic.__new__(cls, sym, process, distribution)
|
| 31 |
+
|
| 32 |
+
@property
|
| 33 |
+
def process(self):
|
| 34 |
+
"""
|
| 35 |
+
The associated stochastic process.
|
| 36 |
+
"""
|
| 37 |
+
return self.args[1]
|
| 38 |
+
|
| 39 |
+
@property
|
| 40 |
+
def domain(self):
|
| 41 |
+
return ProductDomain(self.process.index_set,
|
| 42 |
+
self.process.state_space)
|
| 43 |
+
|
| 44 |
+
@property
|
| 45 |
+
def symbol(self):
|
| 46 |
+
return self.args[0]
|
| 47 |
+
|
| 48 |
+
@property
|
| 49 |
+
def distribution(self):
|
| 50 |
+
return self.args[2]
|
| 51 |
+
|
| 52 |
+
def probability(self, condition, given_condition=None, evaluate=True, **kwargs):
|
| 53 |
+
"""
|
| 54 |
+
Transfers the task of handling queries to the specific stochastic
|
| 55 |
+
process because every process has their own logic of handling such
|
| 56 |
+
queries.
|
| 57 |
+
"""
|
| 58 |
+
return self.process.probability(condition, given_condition, evaluate, **kwargs)
|
| 59 |
+
|
| 60 |
+
def compute_expectation(self, expr, condition=None, evaluate=True, **kwargs):
|
| 61 |
+
"""
|
| 62 |
+
Transfers the task of handling queries to the specific stochastic
|
| 63 |
+
process because every process has their own logic of handling such
|
| 64 |
+
queries.
|
| 65 |
+
"""
|
| 66 |
+
return self.process.expectation(expr, condition, evaluate, **kwargs)
|
hug/lib/python3.12/site-packages/sympy/stats/stochastic_process_types.py
ADDED
|
@@ -0,0 +1,2383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
import random
|
| 3 |
+
import itertools
|
| 4 |
+
from typing import Sequence as tSequence
|
| 5 |
+
from sympy.concrete.summations import Sum
|
| 6 |
+
from sympy.core.add import Add
|
| 7 |
+
from sympy.core.basic import Basic
|
| 8 |
+
from sympy.core.cache import cacheit
|
| 9 |
+
from sympy.core.containers import Tuple
|
| 10 |
+
from sympy.core.expr import Expr
|
| 11 |
+
from sympy.core.function import (Function, Lambda)
|
| 12 |
+
from sympy.core.mul import Mul
|
| 13 |
+
from sympy.core.intfunc import igcd
|
| 14 |
+
from sympy.core.numbers import (Integer, Rational, oo, pi)
|
| 15 |
+
from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne)
|
| 16 |
+
from sympy.core.singleton import S
|
| 17 |
+
from sympy.core.symbol import (Dummy, Symbol)
|
| 18 |
+
from sympy.functions.combinatorial.factorials import factorial
|
| 19 |
+
from sympy.functions.elementary.exponential import exp
|
| 20 |
+
from sympy.functions.elementary.integers import ceiling
|
| 21 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 22 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 23 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 24 |
+
from sympy.logic.boolalg import (And, Not, Or)
|
| 25 |
+
from sympy.matrices.exceptions import NonSquareMatrixError
|
| 26 |
+
from sympy.matrices.dense import (Matrix, eye, ones, zeros)
|
| 27 |
+
from sympy.matrices.expressions.blockmatrix import BlockMatrix
|
| 28 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 29 |
+
from sympy.matrices.expressions.special import Identity
|
| 30 |
+
from sympy.matrices.immutable import ImmutableMatrix
|
| 31 |
+
from sympy.sets.conditionset import ConditionSet
|
| 32 |
+
from sympy.sets.contains import Contains
|
| 33 |
+
from sympy.sets.fancysets import Range
|
| 34 |
+
from sympy.sets.sets import (FiniteSet, Intersection, Interval, Set, Union)
|
| 35 |
+
from sympy.solvers.solveset import linsolve
|
| 36 |
+
from sympy.tensor.indexed import (Indexed, IndexedBase)
|
| 37 |
+
from sympy.core.relational import Relational
|
| 38 |
+
from sympy.logic.boolalg import Boolean
|
| 39 |
+
from sympy.utilities.exceptions import sympy_deprecation_warning
|
| 40 |
+
from sympy.utilities.iterables import strongly_connected_components
|
| 41 |
+
from sympy.stats.joint_rv import JointDistribution
|
| 42 |
+
from sympy.stats.joint_rv_types import JointDistributionHandmade
|
| 43 |
+
from sympy.stats.rv import (RandomIndexedSymbol, random_symbols, RandomSymbol,
|
| 44 |
+
_symbol_converter, _value_check, pspace, given,
|
| 45 |
+
dependent, is_random, sample_iter, Distribution,
|
| 46 |
+
Density)
|
| 47 |
+
from sympy.stats.stochastic_process import StochasticPSpace
|
| 48 |
+
from sympy.stats.symbolic_probability import Probability, Expectation
|
| 49 |
+
from sympy.stats.frv_types import Bernoulli, BernoulliDistribution, FiniteRV
|
| 50 |
+
from sympy.stats.drv_types import Poisson, PoissonDistribution
|
| 51 |
+
from sympy.stats.crv_types import Normal, NormalDistribution, Gamma, GammaDistribution
|
| 52 |
+
from sympy.core.sympify import _sympify, sympify
|
| 53 |
+
|
| 54 |
+
EmptySet = S.EmptySet
|
| 55 |
+
|
| 56 |
+
__all__ = [
|
| 57 |
+
'StochasticProcess',
|
| 58 |
+
'DiscreteTimeStochasticProcess',
|
| 59 |
+
'DiscreteMarkovChain',
|
| 60 |
+
'TransitionMatrixOf',
|
| 61 |
+
'StochasticStateSpaceOf',
|
| 62 |
+
'GeneratorMatrixOf',
|
| 63 |
+
'ContinuousMarkovChain',
|
| 64 |
+
'BernoulliProcess',
|
| 65 |
+
'PoissonProcess',
|
| 66 |
+
'WienerProcess',
|
| 67 |
+
'GammaProcess'
|
| 68 |
+
]
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
@is_random.register(Indexed)
|
| 72 |
+
def _(x):
|
| 73 |
+
return is_random(x.base)
|
| 74 |
+
|
| 75 |
+
@is_random.register(RandomIndexedSymbol) # type: ignore
|
| 76 |
+
def _(x):
|
| 77 |
+
return True
|
| 78 |
+
|
| 79 |
+
def _set_converter(itr):
|
| 80 |
+
"""
|
| 81 |
+
Helper function for converting list/tuple/set to Set.
|
| 82 |
+
If parameter is not an instance of list/tuple/set then
|
| 83 |
+
no operation is performed.
|
| 84 |
+
|
| 85 |
+
Returns
|
| 86 |
+
=======
|
| 87 |
+
|
| 88 |
+
Set
|
| 89 |
+
The argument converted to Set.
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
Raises
|
| 93 |
+
======
|
| 94 |
+
|
| 95 |
+
TypeError
|
| 96 |
+
If the argument is not an instance of list/tuple/set.
|
| 97 |
+
"""
|
| 98 |
+
if isinstance(itr, (list, tuple, set)):
|
| 99 |
+
itr = FiniteSet(*itr)
|
| 100 |
+
if not isinstance(itr, Set):
|
| 101 |
+
raise TypeError("%s is not an instance of list/tuple/set."%(itr))
|
| 102 |
+
return itr
|
| 103 |
+
|
| 104 |
+
def _state_converter(itr: tSequence) -> Tuple | Range:
|
| 105 |
+
"""
|
| 106 |
+
Helper function for converting list/tuple/set/Range/Tuple/FiniteSet
|
| 107 |
+
to tuple/Range.
|
| 108 |
+
"""
|
| 109 |
+
itr_ret: Tuple | Range
|
| 110 |
+
|
| 111 |
+
if isinstance(itr, (Tuple, set, FiniteSet)):
|
| 112 |
+
itr_ret = Tuple(*(sympify(i) if isinstance(i, str) else i for i in itr))
|
| 113 |
+
|
| 114 |
+
elif isinstance(itr, (list, tuple)):
|
| 115 |
+
# check if states are unique
|
| 116 |
+
if len(set(itr)) != len(itr):
|
| 117 |
+
raise ValueError('The state space must have unique elements.')
|
| 118 |
+
itr_ret = Tuple(*(sympify(i) if isinstance(i, str) else i for i in itr))
|
| 119 |
+
|
| 120 |
+
elif isinstance(itr, Range):
|
| 121 |
+
# the only ordered set in SymPy I know of
|
| 122 |
+
# try to convert to tuple
|
| 123 |
+
try:
|
| 124 |
+
itr_ret = Tuple(*(sympify(i) if isinstance(i, str) else i for i in itr))
|
| 125 |
+
except (TypeError, ValueError):
|
| 126 |
+
itr_ret = itr
|
| 127 |
+
|
| 128 |
+
else:
|
| 129 |
+
raise TypeError("%s is not an instance of list/tuple/set/Range/Tuple/FiniteSet." % (itr))
|
| 130 |
+
return itr_ret
|
| 131 |
+
|
| 132 |
+
def _sym_sympify(arg):
|
| 133 |
+
"""
|
| 134 |
+
Converts an arbitrary expression to a type that can be used inside SymPy.
|
| 135 |
+
As generally strings are unwise to use in the expressions,
|
| 136 |
+
it returns the Symbol of argument if the string type argument is passed.
|
| 137 |
+
|
| 138 |
+
Parameters
|
| 139 |
+
=========
|
| 140 |
+
|
| 141 |
+
arg: The parameter to be converted to be used in SymPy.
|
| 142 |
+
|
| 143 |
+
Returns
|
| 144 |
+
=======
|
| 145 |
+
|
| 146 |
+
The converted parameter.
|
| 147 |
+
|
| 148 |
+
"""
|
| 149 |
+
if isinstance(arg, str):
|
| 150 |
+
return Symbol(arg)
|
| 151 |
+
else:
|
| 152 |
+
return _sympify(arg)
|
| 153 |
+
|
| 154 |
+
def _matrix_checks(matrix):
|
| 155 |
+
if not isinstance(matrix, (Matrix, MatrixSymbol, ImmutableMatrix)):
|
| 156 |
+
raise TypeError("Transition probabilities either should "
|
| 157 |
+
"be a Matrix or a MatrixSymbol.")
|
| 158 |
+
if matrix.shape[0] != matrix.shape[1]:
|
| 159 |
+
raise NonSquareMatrixError("%s is not a square matrix"%(matrix))
|
| 160 |
+
if isinstance(matrix, Matrix):
|
| 161 |
+
matrix = ImmutableMatrix(matrix.tolist())
|
| 162 |
+
return matrix
|
| 163 |
+
|
| 164 |
+
class StochasticProcess(Basic):
|
| 165 |
+
"""
|
| 166 |
+
Base class for all the stochastic processes whether
|
| 167 |
+
discrete or continuous.
|
| 168 |
+
|
| 169 |
+
Parameters
|
| 170 |
+
==========
|
| 171 |
+
|
| 172 |
+
sym: Symbol or str
|
| 173 |
+
state_space: Set
|
| 174 |
+
The state space of the stochastic process, by default S.Reals.
|
| 175 |
+
For discrete sets it is zero indexed.
|
| 176 |
+
|
| 177 |
+
See Also
|
| 178 |
+
========
|
| 179 |
+
|
| 180 |
+
DiscreteTimeStochasticProcess
|
| 181 |
+
"""
|
| 182 |
+
|
| 183 |
+
index_set = S.Reals
|
| 184 |
+
|
| 185 |
+
def __new__(cls, sym, state_space=S.Reals, **kwargs):
|
| 186 |
+
sym = _symbol_converter(sym)
|
| 187 |
+
state_space = _set_converter(state_space)
|
| 188 |
+
return Basic.__new__(cls, sym, state_space)
|
| 189 |
+
|
| 190 |
+
@property
|
| 191 |
+
def symbol(self):
|
| 192 |
+
return self.args[0]
|
| 193 |
+
|
| 194 |
+
@property
|
| 195 |
+
def state_space(self) -> FiniteSet | Range:
|
| 196 |
+
if not isinstance(self.args[1], (FiniteSet, Range)):
|
| 197 |
+
assert isinstance(self.args[1], Tuple)
|
| 198 |
+
return FiniteSet(*self.args[1])
|
| 199 |
+
return self.args[1]
|
| 200 |
+
|
| 201 |
+
def _deprecation_warn_distribution(self):
|
| 202 |
+
sympy_deprecation_warning(
|
| 203 |
+
"""
|
| 204 |
+
Calling the distribution method with a RandomIndexedSymbol
|
| 205 |
+
argument, like X.distribution(X(t)) is deprecated. Instead, call
|
| 206 |
+
distribution() with the given timestamp, like
|
| 207 |
+
|
| 208 |
+
X.distribution(t)
|
| 209 |
+
""",
|
| 210 |
+
deprecated_since_version="1.7.1",
|
| 211 |
+
active_deprecations_target="deprecated-distribution-randomindexedsymbol",
|
| 212 |
+
stacklevel=4,
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
def distribution(self, key=None):
|
| 216 |
+
if key is None:
|
| 217 |
+
self._deprecation_warn_distribution()
|
| 218 |
+
return Distribution()
|
| 219 |
+
|
| 220 |
+
def density(self, x):
|
| 221 |
+
return Density()
|
| 222 |
+
|
| 223 |
+
def __call__(self, time):
|
| 224 |
+
"""
|
| 225 |
+
Overridden in ContinuousTimeStochasticProcess.
|
| 226 |
+
"""
|
| 227 |
+
raise NotImplementedError("Use [] for indexing discrete time stochastic process.")
|
| 228 |
+
|
| 229 |
+
def __getitem__(self, time):
|
| 230 |
+
"""
|
| 231 |
+
Overridden in DiscreteTimeStochasticProcess.
|
| 232 |
+
"""
|
| 233 |
+
raise NotImplementedError("Use () for indexing continuous time stochastic process.")
|
| 234 |
+
|
| 235 |
+
def probability(self, condition):
|
| 236 |
+
raise NotImplementedError()
|
| 237 |
+
|
| 238 |
+
def joint_distribution(self, *args):
|
| 239 |
+
"""
|
| 240 |
+
Computes the joint distribution of the random indexed variables.
|
| 241 |
+
|
| 242 |
+
Parameters
|
| 243 |
+
==========
|
| 244 |
+
|
| 245 |
+
args: iterable
|
| 246 |
+
The finite list of random indexed variables/the key of a stochastic
|
| 247 |
+
process whose joint distribution has to be computed.
|
| 248 |
+
|
| 249 |
+
Returns
|
| 250 |
+
=======
|
| 251 |
+
|
| 252 |
+
JointDistribution
|
| 253 |
+
The joint distribution of the list of random indexed variables.
|
| 254 |
+
An unevaluated object is returned if it is not possible to
|
| 255 |
+
compute the joint distribution.
|
| 256 |
+
|
| 257 |
+
Raises
|
| 258 |
+
======
|
| 259 |
+
|
| 260 |
+
ValueError: When the arguments passed are not of type RandomIndexSymbol
|
| 261 |
+
or Number.
|
| 262 |
+
"""
|
| 263 |
+
args = list(args)
|
| 264 |
+
for i, arg in enumerate(args):
|
| 265 |
+
if S(arg).is_Number:
|
| 266 |
+
if self.index_set.is_subset(S.Integers):
|
| 267 |
+
args[i] = self.__getitem__(arg)
|
| 268 |
+
else:
|
| 269 |
+
args[i] = self.__call__(arg)
|
| 270 |
+
elif not isinstance(arg, RandomIndexedSymbol):
|
| 271 |
+
raise ValueError("Expected a RandomIndexedSymbol or "
|
| 272 |
+
"key not %s"%(type(arg)))
|
| 273 |
+
|
| 274 |
+
if args[0].pspace.distribution == Distribution():
|
| 275 |
+
return JointDistribution(*args)
|
| 276 |
+
density = Lambda(tuple(args),
|
| 277 |
+
expr=Mul.fromiter(arg.pspace.process.density(arg) for arg in args))
|
| 278 |
+
return JointDistributionHandmade(density)
|
| 279 |
+
|
| 280 |
+
def expectation(self, condition, given_condition):
|
| 281 |
+
raise NotImplementedError("Abstract method for expectation queries.")
|
| 282 |
+
|
| 283 |
+
def sample(self):
|
| 284 |
+
raise NotImplementedError("Abstract method for sampling queries.")
|
| 285 |
+
|
| 286 |
+
class DiscreteTimeStochasticProcess(StochasticProcess):
|
| 287 |
+
"""
|
| 288 |
+
Base class for all discrete stochastic processes.
|
| 289 |
+
"""
|
| 290 |
+
def __getitem__(self, time):
|
| 291 |
+
"""
|
| 292 |
+
For indexing discrete time stochastic processes.
|
| 293 |
+
|
| 294 |
+
Returns
|
| 295 |
+
=======
|
| 296 |
+
|
| 297 |
+
RandomIndexedSymbol
|
| 298 |
+
"""
|
| 299 |
+
time = sympify(time)
|
| 300 |
+
if not time.is_symbol and time not in self.index_set:
|
| 301 |
+
raise IndexError("%s is not in the index set of %s"%(time, self.symbol))
|
| 302 |
+
idx_obj = Indexed(self.symbol, time)
|
| 303 |
+
pspace_obj = StochasticPSpace(self.symbol, self, self.distribution(time))
|
| 304 |
+
return RandomIndexedSymbol(idx_obj, pspace_obj)
|
| 305 |
+
|
| 306 |
+
class ContinuousTimeStochasticProcess(StochasticProcess):
|
| 307 |
+
"""
|
| 308 |
+
Base class for all continuous time stochastic process.
|
| 309 |
+
"""
|
| 310 |
+
def __call__(self, time):
|
| 311 |
+
"""
|
| 312 |
+
For indexing continuous time stochastic processes.
|
| 313 |
+
|
| 314 |
+
Returns
|
| 315 |
+
=======
|
| 316 |
+
|
| 317 |
+
RandomIndexedSymbol
|
| 318 |
+
"""
|
| 319 |
+
time = sympify(time)
|
| 320 |
+
if not time.is_symbol and time not in self.index_set:
|
| 321 |
+
raise IndexError("%s is not in the index set of %s"%(time, self.symbol))
|
| 322 |
+
func_obj = Function(self.symbol)(time)
|
| 323 |
+
pspace_obj = StochasticPSpace(self.symbol, self, self.distribution(time))
|
| 324 |
+
return RandomIndexedSymbol(func_obj, pspace_obj)
|
| 325 |
+
|
| 326 |
+
class TransitionMatrixOf(Boolean):
|
| 327 |
+
"""
|
| 328 |
+
Assumes that the matrix is the transition matrix
|
| 329 |
+
of the process.
|
| 330 |
+
"""
|
| 331 |
+
|
| 332 |
+
def __new__(cls, process, matrix):
|
| 333 |
+
if not isinstance(process, DiscreteMarkovChain):
|
| 334 |
+
raise ValueError("Currently only DiscreteMarkovChain "
|
| 335 |
+
"support TransitionMatrixOf.")
|
| 336 |
+
matrix = _matrix_checks(matrix)
|
| 337 |
+
return Basic.__new__(cls, process, matrix)
|
| 338 |
+
|
| 339 |
+
process = property(lambda self: self.args[0])
|
| 340 |
+
matrix = property(lambda self: self.args[1])
|
| 341 |
+
|
| 342 |
+
class GeneratorMatrixOf(TransitionMatrixOf):
|
| 343 |
+
"""
|
| 344 |
+
Assumes that the matrix is the generator matrix
|
| 345 |
+
of the process.
|
| 346 |
+
"""
|
| 347 |
+
|
| 348 |
+
def __new__(cls, process, matrix):
|
| 349 |
+
if not isinstance(process, ContinuousMarkovChain):
|
| 350 |
+
raise ValueError("Currently only ContinuousMarkovChain "
|
| 351 |
+
"support GeneratorMatrixOf.")
|
| 352 |
+
matrix = _matrix_checks(matrix)
|
| 353 |
+
return Basic.__new__(cls, process, matrix)
|
| 354 |
+
|
| 355 |
+
class StochasticStateSpaceOf(Boolean):
|
| 356 |
+
|
| 357 |
+
def __new__(cls, process, state_space):
|
| 358 |
+
if not isinstance(process, (DiscreteMarkovChain, ContinuousMarkovChain)):
|
| 359 |
+
raise ValueError("Currently only DiscreteMarkovChain and ContinuousMarkovChain "
|
| 360 |
+
"support StochasticStateSpaceOf.")
|
| 361 |
+
state_space = _state_converter(state_space)
|
| 362 |
+
if isinstance(state_space, Range):
|
| 363 |
+
ss_size = ceiling((state_space.stop - state_space.start) / state_space.step)
|
| 364 |
+
else:
|
| 365 |
+
ss_size = len(state_space)
|
| 366 |
+
state_index = Range(ss_size)
|
| 367 |
+
return Basic.__new__(cls, process, state_index)
|
| 368 |
+
|
| 369 |
+
process = property(lambda self: self.args[0])
|
| 370 |
+
state_index = property(lambda self: self.args[1])
|
| 371 |
+
|
| 372 |
+
class MarkovProcess(StochasticProcess):
|
| 373 |
+
"""
|
| 374 |
+
Contains methods that handle queries
|
| 375 |
+
common to Markov processes.
|
| 376 |
+
"""
|
| 377 |
+
|
| 378 |
+
@property
|
| 379 |
+
def number_of_states(self) -> Integer | Symbol:
|
| 380 |
+
"""
|
| 381 |
+
The number of states in the Markov Chain.
|
| 382 |
+
"""
|
| 383 |
+
return _sympify(self.args[2].shape[0]) # type: ignore
|
| 384 |
+
|
| 385 |
+
@property
|
| 386 |
+
def _state_index(self):
|
| 387 |
+
"""
|
| 388 |
+
Returns state index as Range.
|
| 389 |
+
"""
|
| 390 |
+
return self.args[1]
|
| 391 |
+
|
| 392 |
+
@classmethod
|
| 393 |
+
def _sanity_checks(cls, state_space, trans_probs):
|
| 394 |
+
# Try to never have None as state_space or trans_probs.
|
| 395 |
+
# This helps a lot if we get it done at the start.
|
| 396 |
+
if (state_space is None) and (trans_probs is None):
|
| 397 |
+
_n = Dummy('n', integer=True, nonnegative=True)
|
| 398 |
+
state_space = _state_converter(Range(_n))
|
| 399 |
+
trans_probs = _matrix_checks(MatrixSymbol('_T', _n, _n))
|
| 400 |
+
|
| 401 |
+
elif state_space is None:
|
| 402 |
+
trans_probs = _matrix_checks(trans_probs)
|
| 403 |
+
state_space = _state_converter(Range(trans_probs.shape[0]))
|
| 404 |
+
|
| 405 |
+
elif trans_probs is None:
|
| 406 |
+
state_space = _state_converter(state_space)
|
| 407 |
+
if isinstance(state_space, Range):
|
| 408 |
+
_n = ceiling((state_space.stop - state_space.start) / state_space.step)
|
| 409 |
+
else:
|
| 410 |
+
_n = len(state_space)
|
| 411 |
+
trans_probs = MatrixSymbol('_T', _n, _n)
|
| 412 |
+
|
| 413 |
+
else:
|
| 414 |
+
state_space = _state_converter(state_space)
|
| 415 |
+
trans_probs = _matrix_checks(trans_probs)
|
| 416 |
+
# Range object doesn't want to give a symbolic size
|
| 417 |
+
# so we do it ourselves.
|
| 418 |
+
if isinstance(state_space, Range):
|
| 419 |
+
ss_size = ceiling((state_space.stop - state_space.start) / state_space.step)
|
| 420 |
+
else:
|
| 421 |
+
ss_size = len(state_space)
|
| 422 |
+
if ss_size != trans_probs.shape[0]:
|
| 423 |
+
raise ValueError('The size of the state space and the number of '
|
| 424 |
+
'rows of the transition matrix must be the same.')
|
| 425 |
+
|
| 426 |
+
return state_space, trans_probs
|
| 427 |
+
|
| 428 |
+
def _extract_information(self, given_condition):
|
| 429 |
+
"""
|
| 430 |
+
Helper function to extract information, like,
|
| 431 |
+
transition matrix/generator matrix, state space, etc.
|
| 432 |
+
"""
|
| 433 |
+
if isinstance(self, DiscreteMarkovChain):
|
| 434 |
+
trans_probs = self.transition_probabilities
|
| 435 |
+
state_index = self._state_index
|
| 436 |
+
elif isinstance(self, ContinuousMarkovChain):
|
| 437 |
+
trans_probs = self.generator_matrix
|
| 438 |
+
state_index = self._state_index
|
| 439 |
+
if isinstance(given_condition, And):
|
| 440 |
+
gcs = given_condition.args
|
| 441 |
+
given_condition = S.true
|
| 442 |
+
for gc in gcs:
|
| 443 |
+
if isinstance(gc, TransitionMatrixOf):
|
| 444 |
+
trans_probs = gc.matrix
|
| 445 |
+
if isinstance(gc, StochasticStateSpaceOf):
|
| 446 |
+
state_index = gc.state_index
|
| 447 |
+
if isinstance(gc, Relational):
|
| 448 |
+
given_condition = given_condition & gc
|
| 449 |
+
if isinstance(given_condition, TransitionMatrixOf):
|
| 450 |
+
trans_probs = given_condition.matrix
|
| 451 |
+
given_condition = S.true
|
| 452 |
+
if isinstance(given_condition, StochasticStateSpaceOf):
|
| 453 |
+
state_index = given_condition.state_index
|
| 454 |
+
given_condition = S.true
|
| 455 |
+
return trans_probs, state_index, given_condition
|
| 456 |
+
|
| 457 |
+
def _check_trans_probs(self, trans_probs, row_sum=1):
|
| 458 |
+
"""
|
| 459 |
+
Helper function for checking the validity of transition
|
| 460 |
+
probabilities.
|
| 461 |
+
"""
|
| 462 |
+
if not isinstance(trans_probs, MatrixSymbol):
|
| 463 |
+
rows = trans_probs.tolist()
|
| 464 |
+
for row in rows:
|
| 465 |
+
if (sum(row) - row_sum) != 0:
|
| 466 |
+
raise ValueError("Values in a row must sum to %s. "
|
| 467 |
+
"If you are using Float or floats then please use Rational."%(row_sum))
|
| 468 |
+
|
| 469 |
+
def _work_out_state_index(self, state_index, given_condition, trans_probs):
|
| 470 |
+
"""
|
| 471 |
+
Helper function to extract state space if there
|
| 472 |
+
is a random symbol in the given condition.
|
| 473 |
+
"""
|
| 474 |
+
# if given condition is None, then there is no need to work out
|
| 475 |
+
# state_space from random variables
|
| 476 |
+
if given_condition != None:
|
| 477 |
+
rand_var = list(given_condition.atoms(RandomSymbol) -
|
| 478 |
+
given_condition.atoms(RandomIndexedSymbol))
|
| 479 |
+
if len(rand_var) == 1:
|
| 480 |
+
state_index = rand_var[0].pspace.set
|
| 481 |
+
|
| 482 |
+
# `not None` is `True`. So the old test fails for symbolic sizes.
|
| 483 |
+
# Need to build the statement differently.
|
| 484 |
+
sym_cond = not self.number_of_states.is_Integer
|
| 485 |
+
cond1 = not sym_cond and len(state_index) != trans_probs.shape[0]
|
| 486 |
+
if cond1:
|
| 487 |
+
raise ValueError("state space is not compatible with the transition probabilities.")
|
| 488 |
+
if not isinstance(trans_probs.shape[0], Symbol):
|
| 489 |
+
state_index = FiniteSet(*range(trans_probs.shape[0]))
|
| 490 |
+
return state_index
|
| 491 |
+
|
| 492 |
+
@cacheit
|
| 493 |
+
def _preprocess(self, given_condition, evaluate):
|
| 494 |
+
"""
|
| 495 |
+
Helper function for pre-processing the information.
|
| 496 |
+
"""
|
| 497 |
+
is_insufficient = False
|
| 498 |
+
|
| 499 |
+
if not evaluate: # avoid pre-processing if the result is not to be evaluated
|
| 500 |
+
return (True, None, None, None)
|
| 501 |
+
|
| 502 |
+
# extracting transition matrix and state space
|
| 503 |
+
trans_probs, state_index, given_condition = self._extract_information(given_condition)
|
| 504 |
+
|
| 505 |
+
# given_condition does not have sufficient information
|
| 506 |
+
# for computations
|
| 507 |
+
if trans_probs is None or \
|
| 508 |
+
given_condition is None:
|
| 509 |
+
is_insufficient = True
|
| 510 |
+
else:
|
| 511 |
+
# checking transition probabilities
|
| 512 |
+
if isinstance(self, DiscreteMarkovChain):
|
| 513 |
+
self._check_trans_probs(trans_probs, row_sum=1)
|
| 514 |
+
elif isinstance(self, ContinuousMarkovChain):
|
| 515 |
+
self._check_trans_probs(trans_probs, row_sum=0)
|
| 516 |
+
|
| 517 |
+
# working out state space
|
| 518 |
+
state_index = self._work_out_state_index(state_index, given_condition, trans_probs)
|
| 519 |
+
|
| 520 |
+
return is_insufficient, trans_probs, state_index, given_condition
|
| 521 |
+
|
| 522 |
+
def replace_with_index(self, condition):
|
| 523 |
+
if isinstance(condition, Relational):
|
| 524 |
+
lhs, rhs = condition.lhs, condition.rhs
|
| 525 |
+
if not isinstance(lhs, RandomIndexedSymbol):
|
| 526 |
+
lhs, rhs = rhs, lhs
|
| 527 |
+
condition = type(condition)(self.index_of.get(lhs, lhs),
|
| 528 |
+
self.index_of.get(rhs, rhs))
|
| 529 |
+
return condition
|
| 530 |
+
|
| 531 |
+
def probability(self, condition, given_condition=None, evaluate=True, **kwargs):
|
| 532 |
+
"""
|
| 533 |
+
Handles probability queries for Markov process.
|
| 534 |
+
|
| 535 |
+
Parameters
|
| 536 |
+
==========
|
| 537 |
+
|
| 538 |
+
condition: Relational
|
| 539 |
+
given_condition: Relational/And
|
| 540 |
+
|
| 541 |
+
Returns
|
| 542 |
+
=======
|
| 543 |
+
Probability
|
| 544 |
+
If the information is not sufficient.
|
| 545 |
+
Expr
|
| 546 |
+
In all other cases.
|
| 547 |
+
|
| 548 |
+
Note
|
| 549 |
+
====
|
| 550 |
+
Any information passed at the time of query overrides
|
| 551 |
+
any information passed at the time of object creation like
|
| 552 |
+
transition probabilities, state space.
|
| 553 |
+
Pass the transition matrix using TransitionMatrixOf,
|
| 554 |
+
generator matrix using GeneratorMatrixOf and state space
|
| 555 |
+
using StochasticStateSpaceOf in given_condition using & or And.
|
| 556 |
+
"""
|
| 557 |
+
check, mat, state_index, new_given_condition = \
|
| 558 |
+
self._preprocess(given_condition, evaluate)
|
| 559 |
+
|
| 560 |
+
rv = list(condition.atoms(RandomIndexedSymbol))
|
| 561 |
+
symbolic = False
|
| 562 |
+
for sym in rv:
|
| 563 |
+
if sym.key.is_symbol:
|
| 564 |
+
symbolic = True
|
| 565 |
+
break
|
| 566 |
+
|
| 567 |
+
if check:
|
| 568 |
+
return Probability(condition, new_given_condition)
|
| 569 |
+
|
| 570 |
+
if isinstance(self, ContinuousMarkovChain):
|
| 571 |
+
trans_probs = self.transition_probabilities(mat)
|
| 572 |
+
elif isinstance(self, DiscreteMarkovChain):
|
| 573 |
+
trans_probs = mat
|
| 574 |
+
condition = self.replace_with_index(condition)
|
| 575 |
+
given_condition = self.replace_with_index(given_condition)
|
| 576 |
+
new_given_condition = self.replace_with_index(new_given_condition)
|
| 577 |
+
|
| 578 |
+
if isinstance(condition, Relational):
|
| 579 |
+
if isinstance(new_given_condition, And):
|
| 580 |
+
gcs = new_given_condition.args
|
| 581 |
+
else:
|
| 582 |
+
gcs = (new_given_condition, )
|
| 583 |
+
min_key_rv = list(new_given_condition.atoms(RandomIndexedSymbol))
|
| 584 |
+
|
| 585 |
+
if len(min_key_rv):
|
| 586 |
+
min_key_rv = min_key_rv[0]
|
| 587 |
+
for r in rv:
|
| 588 |
+
if min_key_rv.key.is_symbol or r.key.is_symbol:
|
| 589 |
+
continue
|
| 590 |
+
if min_key_rv.key > r.key:
|
| 591 |
+
return Probability(condition)
|
| 592 |
+
else:
|
| 593 |
+
min_key_rv = None
|
| 594 |
+
return Probability(condition)
|
| 595 |
+
|
| 596 |
+
if symbolic:
|
| 597 |
+
return self._symbolic_probability(condition, new_given_condition, rv, min_key_rv)
|
| 598 |
+
|
| 599 |
+
if len(rv) > 1:
|
| 600 |
+
rv[0] = condition.lhs
|
| 601 |
+
rv[1] = condition.rhs
|
| 602 |
+
if rv[0].key < rv[1].key:
|
| 603 |
+
rv[0], rv[1] = rv[1], rv[0]
|
| 604 |
+
if isinstance(condition, Gt):
|
| 605 |
+
condition = Lt(condition.lhs, condition.rhs)
|
| 606 |
+
elif isinstance(condition, Lt):
|
| 607 |
+
condition = Gt(condition.lhs, condition.rhs)
|
| 608 |
+
elif isinstance(condition, Ge):
|
| 609 |
+
condition = Le(condition.lhs, condition.rhs)
|
| 610 |
+
elif isinstance(condition, Le):
|
| 611 |
+
condition = Ge(condition.lhs, condition.rhs)
|
| 612 |
+
s = Rational(0, 1)
|
| 613 |
+
n = len(self.state_space)
|
| 614 |
+
|
| 615 |
+
if isinstance(condition, (Eq, Ne)):
|
| 616 |
+
for i in range(0, n):
|
| 617 |
+
s += self.probability(Eq(rv[0], i), Eq(rv[1], i)) * self.probability(Eq(rv[1], i), new_given_condition)
|
| 618 |
+
return s if isinstance(condition, Eq) else 1 - s
|
| 619 |
+
else:
|
| 620 |
+
upper = 0
|
| 621 |
+
greater = False
|
| 622 |
+
if isinstance(condition, (Ge, Lt)):
|
| 623 |
+
upper = 1
|
| 624 |
+
if isinstance(condition, (Ge, Gt)):
|
| 625 |
+
greater = True
|
| 626 |
+
|
| 627 |
+
for i in range(0, n):
|
| 628 |
+
if i <= n//2:
|
| 629 |
+
for j in range(0, i + upper):
|
| 630 |
+
s += self.probability(Eq(rv[0], i), Eq(rv[1], j)) * self.probability(Eq(rv[1], j), new_given_condition)
|
| 631 |
+
else:
|
| 632 |
+
s += self.probability(Eq(rv[0], i), new_given_condition)
|
| 633 |
+
for j in range(i + upper, n):
|
| 634 |
+
s -= self.probability(Eq(rv[0], i), Eq(rv[1], j)) * self.probability(Eq(rv[1], j), new_given_condition)
|
| 635 |
+
return s if greater else 1 - s
|
| 636 |
+
|
| 637 |
+
rv = rv[0]
|
| 638 |
+
states = condition.as_set()
|
| 639 |
+
prob, gstate = {}, None
|
| 640 |
+
for gc in gcs:
|
| 641 |
+
if gc.has(min_key_rv):
|
| 642 |
+
if gc.has(Probability):
|
| 643 |
+
p, gp = (gc.rhs, gc.lhs) if isinstance(gc.lhs, Probability) \
|
| 644 |
+
else (gc.lhs, gc.rhs)
|
| 645 |
+
gr = gp.args[0]
|
| 646 |
+
gset = Intersection(gr.as_set(), state_index)
|
| 647 |
+
gstate = list(gset)[0]
|
| 648 |
+
prob[gset] = p
|
| 649 |
+
else:
|
| 650 |
+
_, gstate = (gc.lhs.key, gc.rhs) if isinstance(gc.lhs, RandomIndexedSymbol) \
|
| 651 |
+
else (gc.rhs.key, gc.lhs)
|
| 652 |
+
|
| 653 |
+
if not all(k in self.index_set for k in (rv.key, min_key_rv.key)):
|
| 654 |
+
raise IndexError("The timestamps of the process are not in it's index set.")
|
| 655 |
+
states = Intersection(states, state_index) if not isinstance(self.number_of_states, Symbol) else states
|
| 656 |
+
for state in Union(states, FiniteSet(gstate)):
|
| 657 |
+
if not state.is_Integer or Ge(state, mat.shape[0]) is True:
|
| 658 |
+
raise IndexError("No information is available for (%s, %s) in "
|
| 659 |
+
"transition probabilities of shape, (%s, %s). "
|
| 660 |
+
"State space is zero indexed."
|
| 661 |
+
%(gstate, state, mat.shape[0], mat.shape[1]))
|
| 662 |
+
if prob:
|
| 663 |
+
gstates = Union(*prob.keys())
|
| 664 |
+
if len(gstates) == 1:
|
| 665 |
+
gstate = list(gstates)[0]
|
| 666 |
+
gprob = list(prob.values())[0]
|
| 667 |
+
prob[gstates] = gprob
|
| 668 |
+
elif len(gstates) == len(state_index) - 1:
|
| 669 |
+
gstate = list(state_index - gstates)[0]
|
| 670 |
+
gprob = S.One - sum(prob.values())
|
| 671 |
+
prob[state_index - gstates] = gprob
|
| 672 |
+
else:
|
| 673 |
+
raise ValueError("Conflicting information.")
|
| 674 |
+
else:
|
| 675 |
+
gprob = S.One
|
| 676 |
+
|
| 677 |
+
if min_key_rv == rv:
|
| 678 |
+
return sum(prob[FiniteSet(state)] for state in states)
|
| 679 |
+
if isinstance(self, ContinuousMarkovChain):
|
| 680 |
+
return gprob * sum(trans_probs(rv.key - min_key_rv.key).__getitem__((gstate, state))
|
| 681 |
+
for state in states)
|
| 682 |
+
if isinstance(self, DiscreteMarkovChain):
|
| 683 |
+
return gprob * sum((trans_probs**(rv.key - min_key_rv.key)).__getitem__((gstate, state))
|
| 684 |
+
for state in states)
|
| 685 |
+
|
| 686 |
+
if isinstance(condition, Not):
|
| 687 |
+
expr = condition.args[0]
|
| 688 |
+
return S.One - self.probability(expr, given_condition, evaluate, **kwargs)
|
| 689 |
+
|
| 690 |
+
if isinstance(condition, And):
|
| 691 |
+
compute_later, state2cond, conds = [], {}, condition.args
|
| 692 |
+
for expr in conds:
|
| 693 |
+
if isinstance(expr, Relational):
|
| 694 |
+
ris = list(expr.atoms(RandomIndexedSymbol))[0]
|
| 695 |
+
if state2cond.get(ris, None) is None:
|
| 696 |
+
state2cond[ris] = S.true
|
| 697 |
+
state2cond[ris] &= expr
|
| 698 |
+
else:
|
| 699 |
+
compute_later.append(expr)
|
| 700 |
+
ris = []
|
| 701 |
+
for ri in state2cond:
|
| 702 |
+
ris.append(ri)
|
| 703 |
+
cset = Intersection(state2cond[ri].as_set(), state_index)
|
| 704 |
+
if len(cset) == 0:
|
| 705 |
+
return S.Zero
|
| 706 |
+
state2cond[ri] = cset.as_relational(ri)
|
| 707 |
+
sorted_ris = sorted(ris, key=lambda ri: ri.key)
|
| 708 |
+
prod = self.probability(state2cond[sorted_ris[0]], given_condition, evaluate, **kwargs)
|
| 709 |
+
for i in range(1, len(sorted_ris)):
|
| 710 |
+
ri, prev_ri = sorted_ris[i], sorted_ris[i-1]
|
| 711 |
+
if not isinstance(state2cond[ri], Eq):
|
| 712 |
+
raise ValueError("The process is in multiple states at %s, unable to determine the probability."%(ri))
|
| 713 |
+
mat_of = TransitionMatrixOf(self, mat) if isinstance(self, DiscreteMarkovChain) else GeneratorMatrixOf(self, mat)
|
| 714 |
+
prod *= self.probability(state2cond[ri], state2cond[prev_ri]
|
| 715 |
+
& mat_of
|
| 716 |
+
& StochasticStateSpaceOf(self, state_index),
|
| 717 |
+
evaluate, **kwargs)
|
| 718 |
+
for expr in compute_later:
|
| 719 |
+
prod *= self.probability(expr, given_condition, evaluate, **kwargs)
|
| 720 |
+
return prod
|
| 721 |
+
|
| 722 |
+
if isinstance(condition, Or):
|
| 723 |
+
return sum(self.probability(expr, given_condition, evaluate, **kwargs)
|
| 724 |
+
for expr in condition.args)
|
| 725 |
+
|
| 726 |
+
raise NotImplementedError("Mechanism for handling (%s, %s) queries hasn't been "
|
| 727 |
+
"implemented yet."%(condition, given_condition))
|
| 728 |
+
|
| 729 |
+
def _symbolic_probability(self, condition, new_given_condition, rv, min_key_rv):
|
| 730 |
+
#Function to calculate probability for queries with symbols
|
| 731 |
+
if isinstance(condition, Relational):
|
| 732 |
+
curr_state = new_given_condition.rhs if isinstance(new_given_condition.lhs, RandomIndexedSymbol) \
|
| 733 |
+
else new_given_condition.lhs
|
| 734 |
+
next_state = condition.rhs if isinstance(condition.lhs, RandomIndexedSymbol) \
|
| 735 |
+
else condition.lhs
|
| 736 |
+
|
| 737 |
+
if isinstance(condition, (Eq, Ne)):
|
| 738 |
+
if isinstance(self, DiscreteMarkovChain):
|
| 739 |
+
P = self.transition_probabilities**(rv[0].key - min_key_rv.key)
|
| 740 |
+
else:
|
| 741 |
+
P = exp(self.generator_matrix*(rv[0].key - min_key_rv.key))
|
| 742 |
+
prob = P[curr_state, next_state] if isinstance(condition, Eq) else 1 - P[curr_state, next_state]
|
| 743 |
+
return Piecewise((prob, rv[0].key > min_key_rv.key), (Probability(condition), True))
|
| 744 |
+
else:
|
| 745 |
+
upper = 1
|
| 746 |
+
greater = False
|
| 747 |
+
if isinstance(condition, (Ge, Lt)):
|
| 748 |
+
upper = 0
|
| 749 |
+
if isinstance(condition, (Ge, Gt)):
|
| 750 |
+
greater = True
|
| 751 |
+
k = Dummy('k')
|
| 752 |
+
condition = Eq(condition.lhs, k) if isinstance(condition.lhs, RandomIndexedSymbol)\
|
| 753 |
+
else Eq(condition.rhs, k)
|
| 754 |
+
total = Sum(self.probability(condition, new_given_condition), (k, next_state + upper, self.state_space._sup))
|
| 755 |
+
return Piecewise((total, rv[0].key > min_key_rv.key), (Probability(condition), True)) if greater\
|
| 756 |
+
else Piecewise((1 - total, rv[0].key > min_key_rv.key), (Probability(condition), True))
|
| 757 |
+
else:
|
| 758 |
+
return Probability(condition, new_given_condition)
|
| 759 |
+
|
| 760 |
+
def expectation(self, expr, condition=None, evaluate=True, **kwargs):
|
| 761 |
+
"""
|
| 762 |
+
Handles expectation queries for markov process.
|
| 763 |
+
|
| 764 |
+
Parameters
|
| 765 |
+
==========
|
| 766 |
+
|
| 767 |
+
expr: RandomIndexedSymbol, Relational, Logic
|
| 768 |
+
Condition for which expectation has to be computed. Must
|
| 769 |
+
contain a RandomIndexedSymbol of the process.
|
| 770 |
+
condition: Relational, Logic
|
| 771 |
+
The given conditions under which computations should be done.
|
| 772 |
+
|
| 773 |
+
Returns
|
| 774 |
+
=======
|
| 775 |
+
|
| 776 |
+
Expectation
|
| 777 |
+
Unevaluated object if computations cannot be done due to
|
| 778 |
+
insufficient information.
|
| 779 |
+
Expr
|
| 780 |
+
In all other cases when the computations are successful.
|
| 781 |
+
|
| 782 |
+
Note
|
| 783 |
+
====
|
| 784 |
+
|
| 785 |
+
Any information passed at the time of query overrides
|
| 786 |
+
any information passed at the time of object creation like
|
| 787 |
+
transition probabilities, state space.
|
| 788 |
+
|
| 789 |
+
Pass the transition matrix using TransitionMatrixOf,
|
| 790 |
+
generator matrix using GeneratorMatrixOf and state space
|
| 791 |
+
using StochasticStateSpaceOf in given_condition using & or And.
|
| 792 |
+
"""
|
| 793 |
+
|
| 794 |
+
check, mat, state_index, condition = \
|
| 795 |
+
self._preprocess(condition, evaluate)
|
| 796 |
+
|
| 797 |
+
if check:
|
| 798 |
+
return Expectation(expr, condition)
|
| 799 |
+
|
| 800 |
+
rvs = random_symbols(expr)
|
| 801 |
+
if isinstance(expr, Expr) and isinstance(condition, Eq) \
|
| 802 |
+
and len(rvs) == 1:
|
| 803 |
+
# handle queries similar to E(f(X[i]), Eq(X[i-m], <some-state>))
|
| 804 |
+
condition=self.replace_with_index(condition)
|
| 805 |
+
state_index=self.replace_with_index(state_index)
|
| 806 |
+
rv = list(rvs)[0]
|
| 807 |
+
lhsg, rhsg = condition.lhs, condition.rhs
|
| 808 |
+
if not isinstance(lhsg, RandomIndexedSymbol):
|
| 809 |
+
lhsg, rhsg = (rhsg, lhsg)
|
| 810 |
+
if rhsg not in state_index:
|
| 811 |
+
raise ValueError("%s state is not in the state space."%(rhsg))
|
| 812 |
+
if rv.key < lhsg.key:
|
| 813 |
+
raise ValueError("Incorrect given condition is given, expectation "
|
| 814 |
+
"time %s < time %s"%(rv.key, rv.key))
|
| 815 |
+
mat_of = TransitionMatrixOf(self, mat) if isinstance(self, DiscreteMarkovChain) else GeneratorMatrixOf(self, mat)
|
| 816 |
+
cond = condition & mat_of & \
|
| 817 |
+
StochasticStateSpaceOf(self, state_index)
|
| 818 |
+
func = lambda s: self.probability(Eq(rv, s), cond) * expr.subs(rv, self._state_index[s])
|
| 819 |
+
return sum(func(s) for s in state_index)
|
| 820 |
+
|
| 821 |
+
raise NotImplementedError("Mechanism for handling (%s, %s) queries hasn't been "
|
| 822 |
+
"implemented yet."%(expr, condition))
|
| 823 |
+
|
| 824 |
+
class DiscreteMarkovChain(DiscreteTimeStochasticProcess, MarkovProcess):
|
| 825 |
+
"""
|
| 826 |
+
Represents a finite discrete time-homogeneous Markov chain.
|
| 827 |
+
|
| 828 |
+
This type of Markov Chain can be uniquely characterised by
|
| 829 |
+
its (ordered) state space and its one-step transition probability
|
| 830 |
+
matrix.
|
| 831 |
+
|
| 832 |
+
Parameters
|
| 833 |
+
==========
|
| 834 |
+
|
| 835 |
+
sym:
|
| 836 |
+
The name given to the Markov Chain
|
| 837 |
+
state_space:
|
| 838 |
+
Optional, by default, Range(n)
|
| 839 |
+
trans_probs:
|
| 840 |
+
Optional, by default, MatrixSymbol('_T', n, n)
|
| 841 |
+
|
| 842 |
+
Examples
|
| 843 |
+
========
|
| 844 |
+
|
| 845 |
+
>>> from sympy.stats import DiscreteMarkovChain, TransitionMatrixOf, P, E
|
| 846 |
+
>>> from sympy import Matrix, MatrixSymbol, Eq, symbols
|
| 847 |
+
>>> T = Matrix([[0.5, 0.2, 0.3],[0.2, 0.5, 0.3],[0.2, 0.3, 0.5]])
|
| 848 |
+
>>> Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 849 |
+
>>> YS = DiscreteMarkovChain("Y")
|
| 850 |
+
|
| 851 |
+
>>> Y.state_space
|
| 852 |
+
{0, 1, 2}
|
| 853 |
+
>>> Y.transition_probabilities
|
| 854 |
+
Matrix([
|
| 855 |
+
[0.5, 0.2, 0.3],
|
| 856 |
+
[0.2, 0.5, 0.3],
|
| 857 |
+
[0.2, 0.3, 0.5]])
|
| 858 |
+
>>> TS = MatrixSymbol('T', 3, 3)
|
| 859 |
+
>>> P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TS))
|
| 860 |
+
T[0, 2]*T[1, 0] + T[1, 1]*T[1, 2] + T[1, 2]*T[2, 2]
|
| 861 |
+
>>> P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2)
|
| 862 |
+
0.36
|
| 863 |
+
|
| 864 |
+
Probabilities will be calculated based on indexes rather
|
| 865 |
+
than state names. For example, with the Sunny-Cloudy-Rainy
|
| 866 |
+
model with string state names:
|
| 867 |
+
|
| 868 |
+
>>> from sympy.core.symbol import Str
|
| 869 |
+
>>> Y = DiscreteMarkovChain("Y", [Str('Sunny'), Str('Cloudy'), Str('Rainy')], T)
|
| 870 |
+
>>> P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2)
|
| 871 |
+
0.36
|
| 872 |
+
|
| 873 |
+
This gives the same answer as the ``[0, 1, 2]`` state space.
|
| 874 |
+
Currently, there is no support for state names within probability
|
| 875 |
+
and expectation statements. Here is a work-around using ``Str``:
|
| 876 |
+
|
| 877 |
+
>>> P(Eq(Str('Rainy'), Y[3]), Eq(Y[1], Str('Cloudy'))).round(2)
|
| 878 |
+
0.36
|
| 879 |
+
|
| 880 |
+
Symbol state names can also be used:
|
| 881 |
+
|
| 882 |
+
>>> sunny, cloudy, rainy = symbols('Sunny, Cloudy, Rainy')
|
| 883 |
+
>>> Y = DiscreteMarkovChain("Y", [sunny, cloudy, rainy], T)
|
| 884 |
+
>>> P(Eq(Y[3], rainy), Eq(Y[1], cloudy)).round(2)
|
| 885 |
+
0.36
|
| 886 |
+
|
| 887 |
+
Expectations will be calculated as follows:
|
| 888 |
+
|
| 889 |
+
>>> E(Y[3], Eq(Y[1], cloudy))
|
| 890 |
+
0.38*Cloudy + 0.36*Rainy + 0.26*Sunny
|
| 891 |
+
|
| 892 |
+
Probability of expressions with multiple RandomIndexedSymbols
|
| 893 |
+
can also be calculated provided there is only 1 RandomIndexedSymbol
|
| 894 |
+
in the given condition. It is always better to use Rational instead
|
| 895 |
+
of floating point numbers for the probabilities in the
|
| 896 |
+
transition matrix to avoid errors.
|
| 897 |
+
|
| 898 |
+
>>> from sympy import Gt, Le, Rational
|
| 899 |
+
>>> T = Matrix([[Rational(5, 10), Rational(3, 10), Rational(2, 10)], [Rational(2, 10), Rational(7, 10), Rational(1, 10)], [Rational(3, 10), Rational(3, 10), Rational(4, 10)]])
|
| 900 |
+
>>> Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 901 |
+
>>> P(Eq(Y[3], Y[1]), Eq(Y[0], 0)).round(3)
|
| 902 |
+
0.409
|
| 903 |
+
>>> P(Gt(Y[3], Y[1]), Eq(Y[0], 0)).round(2)
|
| 904 |
+
0.36
|
| 905 |
+
>>> P(Le(Y[15], Y[10]), Eq(Y[8], 2)).round(7)
|
| 906 |
+
0.6963328
|
| 907 |
+
|
| 908 |
+
Symbolic probability queries are also supported
|
| 909 |
+
|
| 910 |
+
>>> a, b, c, d = symbols('a b c d')
|
| 911 |
+
>>> T = Matrix([[Rational(1, 10), Rational(4, 10), Rational(5, 10)], [Rational(3, 10), Rational(4, 10), Rational(3, 10)], [Rational(7, 10), Rational(2, 10), Rational(1, 10)]])
|
| 912 |
+
>>> Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 913 |
+
>>> query = P(Eq(Y[a], b), Eq(Y[c], d))
|
| 914 |
+
>>> query.subs({a:10, b:2, c:5, d:1}).round(4)
|
| 915 |
+
0.3096
|
| 916 |
+
>>> P(Eq(Y[10], 2), Eq(Y[5], 1)).evalf().round(4)
|
| 917 |
+
0.3096
|
| 918 |
+
>>> query_gt = P(Gt(Y[a], b), Eq(Y[c], d))
|
| 919 |
+
>>> query_gt.subs({a:21, b:0, c:5, d:0}).evalf().round(5)
|
| 920 |
+
0.64705
|
| 921 |
+
>>> P(Gt(Y[21], 0), Eq(Y[5], 0)).round(5)
|
| 922 |
+
0.64705
|
| 923 |
+
|
| 924 |
+
There is limited support for arbitrarily sized states:
|
| 925 |
+
|
| 926 |
+
>>> n = symbols('n', nonnegative=True, integer=True)
|
| 927 |
+
>>> T = MatrixSymbol('T', n, n)
|
| 928 |
+
>>> Y = DiscreteMarkovChain("Y", trans_probs=T)
|
| 929 |
+
>>> Y.state_space
|
| 930 |
+
Range(0, n, 1)
|
| 931 |
+
>>> query = P(Eq(Y[a], b), Eq(Y[c], d))
|
| 932 |
+
>>> query.subs({a:10, b:2, c:5, d:1})
|
| 933 |
+
(T**5)[1, 2]
|
| 934 |
+
|
| 935 |
+
References
|
| 936 |
+
==========
|
| 937 |
+
|
| 938 |
+
.. [1] https://en.wikipedia.org/wiki/Markov_chain#Discrete-time_Markov_chain
|
| 939 |
+
.. [2] https://web.archive.org/web/20201230182007/https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
|
| 940 |
+
"""
|
| 941 |
+
index_set = S.Naturals0
|
| 942 |
+
|
| 943 |
+
def __new__(cls, sym, state_space=None, trans_probs=None):
|
| 944 |
+
sym = _symbol_converter(sym)
|
| 945 |
+
|
| 946 |
+
state_space, trans_probs = MarkovProcess._sanity_checks(state_space, trans_probs)
|
| 947 |
+
|
| 948 |
+
obj = Basic.__new__(cls, sym, state_space, trans_probs) # type: ignore
|
| 949 |
+
indices = {}
|
| 950 |
+
if isinstance(obj.number_of_states, Integer):
|
| 951 |
+
for index, state in enumerate(obj._state_index):
|
| 952 |
+
indices[state] = index
|
| 953 |
+
obj.index_of = indices
|
| 954 |
+
return obj
|
| 955 |
+
|
| 956 |
+
@property
|
| 957 |
+
def transition_probabilities(self):
|
| 958 |
+
"""
|
| 959 |
+
Transition probabilities of discrete Markov chain,
|
| 960 |
+
either an instance of Matrix or MatrixSymbol.
|
| 961 |
+
"""
|
| 962 |
+
return self.args[2]
|
| 963 |
+
|
| 964 |
+
def communication_classes(self) -> list[tuple[list[Basic], Boolean, Integer]]:
|
| 965 |
+
"""
|
| 966 |
+
Returns the list of communication classes that partition
|
| 967 |
+
the states of the markov chain.
|
| 968 |
+
|
| 969 |
+
A communication class is defined to be a set of states
|
| 970 |
+
such that every state in that set is reachable from
|
| 971 |
+
every other state in that set. Due to its properties
|
| 972 |
+
this forms a class in the mathematical sense.
|
| 973 |
+
Communication classes are also known as recurrence
|
| 974 |
+
classes.
|
| 975 |
+
|
| 976 |
+
Returns
|
| 977 |
+
=======
|
| 978 |
+
|
| 979 |
+
classes
|
| 980 |
+
The ``classes`` are a list of tuples. Each
|
| 981 |
+
tuple represents a single communication class
|
| 982 |
+
with its properties. The first element in the
|
| 983 |
+
tuple is the list of states in the class, the
|
| 984 |
+
second element is whether the class is recurrent
|
| 985 |
+
and the third element is the period of the
|
| 986 |
+
communication class.
|
| 987 |
+
|
| 988 |
+
Examples
|
| 989 |
+
========
|
| 990 |
+
|
| 991 |
+
>>> from sympy.stats import DiscreteMarkovChain
|
| 992 |
+
>>> from sympy import Matrix
|
| 993 |
+
>>> T = Matrix([[0, 1, 0],
|
| 994 |
+
... [1, 0, 0],
|
| 995 |
+
... [1, 0, 0]])
|
| 996 |
+
>>> X = DiscreteMarkovChain('X', [1, 2, 3], T)
|
| 997 |
+
>>> classes = X.communication_classes()
|
| 998 |
+
>>> for states, is_recurrent, period in classes:
|
| 999 |
+
... states, is_recurrent, period
|
| 1000 |
+
([1, 2], True, 2)
|
| 1001 |
+
([3], False, 1)
|
| 1002 |
+
|
| 1003 |
+
From this we can see that states ``1`` and ``2``
|
| 1004 |
+
communicate, are recurrent and have a period
|
| 1005 |
+
of 2. We can also see state ``3`` is transient
|
| 1006 |
+
with a period of 1.
|
| 1007 |
+
|
| 1008 |
+
Notes
|
| 1009 |
+
=====
|
| 1010 |
+
|
| 1011 |
+
The algorithm used is of order ``O(n**2)`` where
|
| 1012 |
+
``n`` is the number of states in the markov chain.
|
| 1013 |
+
It uses Tarjan's algorithm to find the classes
|
| 1014 |
+
themselves and then it uses a breadth-first search
|
| 1015 |
+
algorithm to find each class's periodicity.
|
| 1016 |
+
Most of the algorithm's components approach ``O(n)``
|
| 1017 |
+
as the matrix becomes more and more sparse.
|
| 1018 |
+
|
| 1019 |
+
References
|
| 1020 |
+
==========
|
| 1021 |
+
|
| 1022 |
+
.. [1] https://web.archive.org/web/20220207032113/https://www.columbia.edu/~ww2040/4701Sum07/4701-06-Notes-MCII.pdf
|
| 1023 |
+
.. [2] https://cecas.clemson.edu/~shierd/Shier/markov.pdf
|
| 1024 |
+
.. [3] https://www.proquest.com/openview/4adc6a51d8371be5b0e4c7dff287fc70/1?pq-origsite=gscholar&cbl=2026366&diss=y
|
| 1025 |
+
.. [4] https://www.mathworks.com/help/econ/dtmc.classify.html
|
| 1026 |
+
"""
|
| 1027 |
+
n = self.number_of_states
|
| 1028 |
+
T = self.transition_probabilities
|
| 1029 |
+
|
| 1030 |
+
if isinstance(T, MatrixSymbol):
|
| 1031 |
+
raise NotImplementedError("Cannot perform the operation with a symbolic matrix.")
|
| 1032 |
+
|
| 1033 |
+
# begin Tarjan's algorithm
|
| 1034 |
+
V = Range(n)
|
| 1035 |
+
# don't use state names. Rather use state
|
| 1036 |
+
# indexes since we use them for matrix
|
| 1037 |
+
# indexing here and later onward
|
| 1038 |
+
E = [(i, j) for i in V for j in V if T[i, j] != 0]
|
| 1039 |
+
classes = strongly_connected_components((V, E))
|
| 1040 |
+
# end Tarjan's algorithm
|
| 1041 |
+
|
| 1042 |
+
recurrence = []
|
| 1043 |
+
periods = []
|
| 1044 |
+
for class_ in classes:
|
| 1045 |
+
# begin recurrent check (similar to self._check_trans_probs())
|
| 1046 |
+
submatrix = T[class_, class_] # get the submatrix with those states
|
| 1047 |
+
is_recurrent = S.true
|
| 1048 |
+
rows = submatrix.tolist()
|
| 1049 |
+
for row in rows:
|
| 1050 |
+
if (sum(row) - 1) != 0:
|
| 1051 |
+
is_recurrent = S.false
|
| 1052 |
+
break
|
| 1053 |
+
recurrence.append(is_recurrent)
|
| 1054 |
+
# end recurrent check
|
| 1055 |
+
|
| 1056 |
+
# begin breadth-first search
|
| 1057 |
+
non_tree_edge_values: set[int] = set()
|
| 1058 |
+
visited = {class_[0]}
|
| 1059 |
+
newly_visited = {class_[0]}
|
| 1060 |
+
level = {class_[0]: 0}
|
| 1061 |
+
current_level = 0
|
| 1062 |
+
done = False # imitate a do-while loop
|
| 1063 |
+
while not done: # runs at most len(class_) times
|
| 1064 |
+
done = len(visited) == len(class_)
|
| 1065 |
+
current_level += 1
|
| 1066 |
+
|
| 1067 |
+
# this loop and the while loop above run a combined len(class_) number of times.
|
| 1068 |
+
# so this triple nested loop runs through each of the n states once.
|
| 1069 |
+
for i in newly_visited:
|
| 1070 |
+
|
| 1071 |
+
# the loop below runs len(class_) number of times
|
| 1072 |
+
# complexity is around about O(n * avg(len(class_)))
|
| 1073 |
+
newly_visited = {j for j in class_ if T[i, j] != 0}
|
| 1074 |
+
|
| 1075 |
+
new_tree_edges = newly_visited.difference(visited)
|
| 1076 |
+
for j in new_tree_edges:
|
| 1077 |
+
level[j] = current_level
|
| 1078 |
+
|
| 1079 |
+
new_non_tree_edges = newly_visited.intersection(visited)
|
| 1080 |
+
new_non_tree_edge_values = {level[i]-level[j]+1 for j in new_non_tree_edges}
|
| 1081 |
+
|
| 1082 |
+
non_tree_edge_values = non_tree_edge_values.union(new_non_tree_edge_values)
|
| 1083 |
+
visited = visited.union(new_tree_edges)
|
| 1084 |
+
|
| 1085 |
+
# igcd needs at least 2 arguments
|
| 1086 |
+
positive_ntev = {val_e for val_e in non_tree_edge_values if val_e > 0}
|
| 1087 |
+
if len(positive_ntev) == 0:
|
| 1088 |
+
periods.append(len(class_))
|
| 1089 |
+
elif len(positive_ntev) == 1:
|
| 1090 |
+
periods.append(positive_ntev.pop())
|
| 1091 |
+
else:
|
| 1092 |
+
periods.append(igcd(*positive_ntev))
|
| 1093 |
+
# end breadth-first search
|
| 1094 |
+
|
| 1095 |
+
# convert back to the user's state names
|
| 1096 |
+
classes = [[_sympify(self._state_index[i]) for i in class_] for class_ in classes]
|
| 1097 |
+
return list(zip(classes, recurrence, map(Integer,periods)))
|
| 1098 |
+
|
| 1099 |
+
def fundamental_matrix(self):
|
| 1100 |
+
"""
|
| 1101 |
+
Each entry fundamental matrix can be interpreted as
|
| 1102 |
+
the expected number of times the chains is in state j
|
| 1103 |
+
if it started in state i.
|
| 1104 |
+
|
| 1105 |
+
References
|
| 1106 |
+
==========
|
| 1107 |
+
|
| 1108 |
+
.. [1] https://lips.cs.princeton.edu/the-fundamental-matrix-of-a-finite-markov-chain/
|
| 1109 |
+
|
| 1110 |
+
"""
|
| 1111 |
+
_, _, _, Q = self.decompose()
|
| 1112 |
+
|
| 1113 |
+
if Q.shape[0] > 0: # if non-ergodic
|
| 1114 |
+
I = eye(Q.shape[0])
|
| 1115 |
+
if (I - Q).det() == 0:
|
| 1116 |
+
raise ValueError("The fundamental matrix doesn't exist.")
|
| 1117 |
+
return (I - Q).inv().as_immutable()
|
| 1118 |
+
else: # if ergodic
|
| 1119 |
+
P = self.transition_probabilities
|
| 1120 |
+
I = eye(P.shape[0])
|
| 1121 |
+
w = self.fixed_row_vector()
|
| 1122 |
+
W = Matrix([list(w) for i in range(0, P.shape[0])])
|
| 1123 |
+
if (I - P + W).det() == 0:
|
| 1124 |
+
raise ValueError("The fundamental matrix doesn't exist.")
|
| 1125 |
+
return (I - P + W).inv().as_immutable()
|
| 1126 |
+
|
| 1127 |
+
def absorbing_probabilities(self):
|
| 1128 |
+
"""
|
| 1129 |
+
Computes the absorbing probabilities, i.e.
|
| 1130 |
+
the ij-th entry of the matrix denotes the
|
| 1131 |
+
probability of Markov chain being absorbed
|
| 1132 |
+
in state j starting from state i.
|
| 1133 |
+
"""
|
| 1134 |
+
_, _, R, _ = self.decompose()
|
| 1135 |
+
N = self.fundamental_matrix()
|
| 1136 |
+
if R is None or N is None:
|
| 1137 |
+
return None
|
| 1138 |
+
return N*R
|
| 1139 |
+
|
| 1140 |
+
def absorbing_probabilites(self):
|
| 1141 |
+
sympy_deprecation_warning(
|
| 1142 |
+
"""
|
| 1143 |
+
DiscreteMarkovChain.absorbing_probabilites() is deprecated. Use
|
| 1144 |
+
absorbing_probabilities() instead (note the spelling difference).
|
| 1145 |
+
""",
|
| 1146 |
+
deprecated_since_version="1.7",
|
| 1147 |
+
active_deprecations_target="deprecated-absorbing_probabilites",
|
| 1148 |
+
)
|
| 1149 |
+
return self.absorbing_probabilities()
|
| 1150 |
+
|
| 1151 |
+
def is_regular(self):
|
| 1152 |
+
tuples = self.communication_classes()
|
| 1153 |
+
if len(tuples) == 0:
|
| 1154 |
+
return S.false # not defined for a 0x0 matrix
|
| 1155 |
+
classes, _, periods = list(zip(*tuples))
|
| 1156 |
+
return And(len(classes) == 1, periods[0] == 1)
|
| 1157 |
+
|
| 1158 |
+
def is_ergodic(self):
|
| 1159 |
+
tuples = self.communication_classes()
|
| 1160 |
+
if len(tuples) == 0:
|
| 1161 |
+
return S.false # not defined for a 0x0 matrix
|
| 1162 |
+
classes, _, _ = list(zip(*tuples))
|
| 1163 |
+
return S(len(classes) == 1)
|
| 1164 |
+
|
| 1165 |
+
def is_absorbing_state(self, state):
|
| 1166 |
+
trans_probs = self.transition_probabilities
|
| 1167 |
+
if isinstance(trans_probs, ImmutableMatrix) and \
|
| 1168 |
+
state < trans_probs.shape[0]:
|
| 1169 |
+
return S(trans_probs[state, state]) is S.One
|
| 1170 |
+
|
| 1171 |
+
def is_absorbing_chain(self):
|
| 1172 |
+
states, A, B, C = self.decompose()
|
| 1173 |
+
r = A.shape[0]
|
| 1174 |
+
return And(r > 0, A == Identity(r).as_explicit())
|
| 1175 |
+
|
| 1176 |
+
def stationary_distribution(self, condition_set=False) -> ImmutableMatrix | ConditionSet | Lambda:
|
| 1177 |
+
r"""
|
| 1178 |
+
The stationary distribution is any row vector, p, that solves p = pP,
|
| 1179 |
+
is row stochastic and each element in p must be nonnegative.
|
| 1180 |
+
That means in matrix form: :math:`(P-I)^T p^T = 0` and
|
| 1181 |
+
:math:`(1, \dots, 1) p = 1`
|
| 1182 |
+
where ``P`` is the one-step transition matrix.
|
| 1183 |
+
|
| 1184 |
+
All time-homogeneous Markov Chains with a finite state space
|
| 1185 |
+
have at least one stationary distribution. In addition, if
|
| 1186 |
+
a finite time-homogeneous Markov Chain is irreducible, the
|
| 1187 |
+
stationary distribution is unique.
|
| 1188 |
+
|
| 1189 |
+
Parameters
|
| 1190 |
+
==========
|
| 1191 |
+
|
| 1192 |
+
condition_set : bool
|
| 1193 |
+
If the chain has a symbolic size or transition matrix,
|
| 1194 |
+
it will return a ``Lambda`` if ``False`` and return a
|
| 1195 |
+
``ConditionSet`` if ``True``.
|
| 1196 |
+
|
| 1197 |
+
Examples
|
| 1198 |
+
========
|
| 1199 |
+
|
| 1200 |
+
>>> from sympy.stats import DiscreteMarkovChain
|
| 1201 |
+
>>> from sympy import Matrix, S
|
| 1202 |
+
|
| 1203 |
+
An irreducible Markov Chain
|
| 1204 |
+
|
| 1205 |
+
>>> T = Matrix([[S(1)/2, S(1)/2, 0],
|
| 1206 |
+
... [S(4)/5, S(1)/5, 0],
|
| 1207 |
+
... [1, 0, 0]])
|
| 1208 |
+
>>> X = DiscreteMarkovChain('X', trans_probs=T)
|
| 1209 |
+
>>> X.stationary_distribution()
|
| 1210 |
+
Matrix([[8/13, 5/13, 0]])
|
| 1211 |
+
|
| 1212 |
+
A reducible Markov Chain
|
| 1213 |
+
|
| 1214 |
+
>>> T = Matrix([[S(1)/2, S(1)/2, 0],
|
| 1215 |
+
... [S(4)/5, S(1)/5, 0],
|
| 1216 |
+
... [0, 0, 1]])
|
| 1217 |
+
>>> X = DiscreteMarkovChain('X', trans_probs=T)
|
| 1218 |
+
>>> X.stationary_distribution()
|
| 1219 |
+
Matrix([[8/13 - 8*tau0/13, 5/13 - 5*tau0/13, tau0]])
|
| 1220 |
+
|
| 1221 |
+
>>> Y = DiscreteMarkovChain('Y')
|
| 1222 |
+
>>> Y.stationary_distribution()
|
| 1223 |
+
Lambda((wm, _T), Eq(wm*_T, wm))
|
| 1224 |
+
|
| 1225 |
+
>>> Y.stationary_distribution(condition_set=True)
|
| 1226 |
+
ConditionSet(wm, Eq(wm*_T, wm))
|
| 1227 |
+
|
| 1228 |
+
References
|
| 1229 |
+
==========
|
| 1230 |
+
|
| 1231 |
+
.. [1] https://www.probabilitycourse.com/chapter11/11_2_6_stationary_and_limiting_distributions.php
|
| 1232 |
+
.. [2] https://web.archive.org/web/20210508104430/https://galton.uchicago.edu/~yibi/teaching/stat317/2014/Lectures/Lecture4_6up.pdf
|
| 1233 |
+
|
| 1234 |
+
See Also
|
| 1235 |
+
========
|
| 1236 |
+
|
| 1237 |
+
sympy.stats.DiscreteMarkovChain.limiting_distribution
|
| 1238 |
+
"""
|
| 1239 |
+
trans_probs = self.transition_probabilities
|
| 1240 |
+
n = self.number_of_states
|
| 1241 |
+
|
| 1242 |
+
if n == 0:
|
| 1243 |
+
return ImmutableMatrix(Matrix([[]]))
|
| 1244 |
+
|
| 1245 |
+
# symbolic matrix version
|
| 1246 |
+
if isinstance(trans_probs, MatrixSymbol):
|
| 1247 |
+
wm = MatrixSymbol('wm', 1, n)
|
| 1248 |
+
if condition_set:
|
| 1249 |
+
return ConditionSet(wm, Eq(wm * trans_probs, wm))
|
| 1250 |
+
else:
|
| 1251 |
+
return Lambda((wm, trans_probs), Eq(wm * trans_probs, wm))
|
| 1252 |
+
|
| 1253 |
+
# numeric matrix version
|
| 1254 |
+
a = Matrix(trans_probs - Identity(n)).T
|
| 1255 |
+
a[0, 0:n] = ones(1, n) # type: ignore
|
| 1256 |
+
b = zeros(n, 1)
|
| 1257 |
+
b[0, 0] = 1
|
| 1258 |
+
|
| 1259 |
+
soln = list(linsolve((a, b)))[0]
|
| 1260 |
+
return ImmutableMatrix([soln])
|
| 1261 |
+
|
| 1262 |
+
def fixed_row_vector(self):
|
| 1263 |
+
"""
|
| 1264 |
+
A wrapper for ``stationary_distribution()``.
|
| 1265 |
+
"""
|
| 1266 |
+
return self.stationary_distribution()
|
| 1267 |
+
|
| 1268 |
+
@property
|
| 1269 |
+
def limiting_distribution(self):
|
| 1270 |
+
"""
|
| 1271 |
+
The fixed row vector is the limiting
|
| 1272 |
+
distribution of a discrete Markov chain.
|
| 1273 |
+
"""
|
| 1274 |
+
return self.fixed_row_vector()
|
| 1275 |
+
|
| 1276 |
+
def decompose(self) -> tuple[list[Basic], ImmutableMatrix, ImmutableMatrix, ImmutableMatrix]:
|
| 1277 |
+
"""
|
| 1278 |
+
Decomposes the transition matrix into submatrices with
|
| 1279 |
+
special properties.
|
| 1280 |
+
|
| 1281 |
+
The transition matrix can be decomposed into 4 submatrices:
|
| 1282 |
+
- A - the submatrix from recurrent states to recurrent states.
|
| 1283 |
+
- B - the submatrix from transient to recurrent states.
|
| 1284 |
+
- C - the submatrix from transient to transient states.
|
| 1285 |
+
- O - the submatrix of zeros for recurrent to transient states.
|
| 1286 |
+
|
| 1287 |
+
Returns
|
| 1288 |
+
=======
|
| 1289 |
+
|
| 1290 |
+
states, A, B, C
|
| 1291 |
+
``states`` - a list of state names with the first being
|
| 1292 |
+
the recurrent states and the last being
|
| 1293 |
+
the transient states in the order
|
| 1294 |
+
of the row names of A and then the row names of C.
|
| 1295 |
+
``A`` - the submatrix from recurrent states to recurrent states.
|
| 1296 |
+
``B`` - the submatrix from transient to recurrent states.
|
| 1297 |
+
``C`` - the submatrix from transient to transient states.
|
| 1298 |
+
|
| 1299 |
+
Examples
|
| 1300 |
+
========
|
| 1301 |
+
|
| 1302 |
+
>>> from sympy.stats import DiscreteMarkovChain
|
| 1303 |
+
>>> from sympy import Matrix, S
|
| 1304 |
+
|
| 1305 |
+
One can decompose this chain for example:
|
| 1306 |
+
|
| 1307 |
+
>>> T = Matrix([[S(1)/2, S(1)/2, 0, 0, 0],
|
| 1308 |
+
... [S(2)/5, S(1)/5, S(2)/5, 0, 0],
|
| 1309 |
+
... [0, 0, 1, 0, 0],
|
| 1310 |
+
... [0, 0, S(1)/2, S(1)/2, 0],
|
| 1311 |
+
... [S(1)/2, 0, 0, 0, S(1)/2]])
|
| 1312 |
+
>>> X = DiscreteMarkovChain('X', trans_probs=T)
|
| 1313 |
+
>>> states, A, B, C = X.decompose()
|
| 1314 |
+
>>> states
|
| 1315 |
+
[2, 0, 1, 3, 4]
|
| 1316 |
+
|
| 1317 |
+
>>> A # recurrent to recurrent
|
| 1318 |
+
Matrix([[1]])
|
| 1319 |
+
|
| 1320 |
+
>>> B # transient to recurrent
|
| 1321 |
+
Matrix([
|
| 1322 |
+
[ 0],
|
| 1323 |
+
[2/5],
|
| 1324 |
+
[1/2],
|
| 1325 |
+
[ 0]])
|
| 1326 |
+
|
| 1327 |
+
>>> C # transient to transient
|
| 1328 |
+
Matrix([
|
| 1329 |
+
[1/2, 1/2, 0, 0],
|
| 1330 |
+
[2/5, 1/5, 0, 0],
|
| 1331 |
+
[ 0, 0, 1/2, 0],
|
| 1332 |
+
[1/2, 0, 0, 1/2]])
|
| 1333 |
+
|
| 1334 |
+
This means that state 2 is the only absorbing state
|
| 1335 |
+
(since A is a 1x1 matrix). B is a 4x1 matrix since
|
| 1336 |
+
the 4 remaining transient states all merge into recurrent
|
| 1337 |
+
state 2. And C is the 4x4 matrix that shows how the
|
| 1338 |
+
transient states 0, 1, 3, 4 all interact.
|
| 1339 |
+
|
| 1340 |
+
See Also
|
| 1341 |
+
========
|
| 1342 |
+
|
| 1343 |
+
sympy.stats.DiscreteMarkovChain.communication_classes
|
| 1344 |
+
sympy.stats.DiscreteMarkovChain.canonical_form
|
| 1345 |
+
|
| 1346 |
+
References
|
| 1347 |
+
==========
|
| 1348 |
+
|
| 1349 |
+
.. [1] https://en.wikipedia.org/wiki/Absorbing_Markov_chain
|
| 1350 |
+
.. [2] https://people.brandeis.edu/~igusa/Math56aS08/Math56a_S08_notes015.pdf
|
| 1351 |
+
"""
|
| 1352 |
+
trans_probs = self.transition_probabilities
|
| 1353 |
+
|
| 1354 |
+
classes = self.communication_classes()
|
| 1355 |
+
r_states = []
|
| 1356 |
+
t_states = []
|
| 1357 |
+
|
| 1358 |
+
for states, recurrent, period in classes:
|
| 1359 |
+
if recurrent:
|
| 1360 |
+
r_states += states
|
| 1361 |
+
else:
|
| 1362 |
+
t_states += states
|
| 1363 |
+
|
| 1364 |
+
states = r_states + t_states
|
| 1365 |
+
indexes = [self.index_of[state] for state in states] # type: ignore
|
| 1366 |
+
|
| 1367 |
+
A = Matrix(len(r_states), len(r_states),
|
| 1368 |
+
lambda i, j: trans_probs[indexes[i], indexes[j]])
|
| 1369 |
+
|
| 1370 |
+
B = Matrix(len(t_states), len(r_states),
|
| 1371 |
+
lambda i, j: trans_probs[indexes[len(r_states) + i], indexes[j]])
|
| 1372 |
+
|
| 1373 |
+
C = Matrix(len(t_states), len(t_states),
|
| 1374 |
+
lambda i, j: trans_probs[indexes[len(r_states) + i], indexes[len(r_states) + j]])
|
| 1375 |
+
|
| 1376 |
+
return states, A.as_immutable(), B.as_immutable(), C.as_immutable()
|
| 1377 |
+
|
| 1378 |
+
def canonical_form(self) -> tuple[list[Basic], ImmutableMatrix]:
|
| 1379 |
+
"""
|
| 1380 |
+
Reorders the one-step transition matrix
|
| 1381 |
+
so that recurrent states appear first and transient
|
| 1382 |
+
states appear last. Other representations include inserting
|
| 1383 |
+
transient states first and recurrent states last.
|
| 1384 |
+
|
| 1385 |
+
Returns
|
| 1386 |
+
=======
|
| 1387 |
+
|
| 1388 |
+
states, P_new
|
| 1389 |
+
``states`` is the list that describes the order of the
|
| 1390 |
+
new states in the matrix
|
| 1391 |
+
so that the ith element in ``states`` is the state of the
|
| 1392 |
+
ith row of A.
|
| 1393 |
+
``P_new`` is the new transition matrix in canonical form.
|
| 1394 |
+
|
| 1395 |
+
Examples
|
| 1396 |
+
========
|
| 1397 |
+
|
| 1398 |
+
>>> from sympy.stats import DiscreteMarkovChain
|
| 1399 |
+
>>> from sympy import Matrix, S
|
| 1400 |
+
|
| 1401 |
+
You can convert your chain into canonical form:
|
| 1402 |
+
|
| 1403 |
+
>>> T = Matrix([[S(1)/2, S(1)/2, 0, 0, 0],
|
| 1404 |
+
... [S(2)/5, S(1)/5, S(2)/5, 0, 0],
|
| 1405 |
+
... [0, 0, 1, 0, 0],
|
| 1406 |
+
... [0, 0, S(1)/2, S(1)/2, 0],
|
| 1407 |
+
... [S(1)/2, 0, 0, 0, S(1)/2]])
|
| 1408 |
+
>>> X = DiscreteMarkovChain('X', list(range(1, 6)), trans_probs=T)
|
| 1409 |
+
>>> states, new_matrix = X.canonical_form()
|
| 1410 |
+
>>> states
|
| 1411 |
+
[3, 1, 2, 4, 5]
|
| 1412 |
+
|
| 1413 |
+
>>> new_matrix
|
| 1414 |
+
Matrix([
|
| 1415 |
+
[ 1, 0, 0, 0, 0],
|
| 1416 |
+
[ 0, 1/2, 1/2, 0, 0],
|
| 1417 |
+
[2/5, 2/5, 1/5, 0, 0],
|
| 1418 |
+
[1/2, 0, 0, 1/2, 0],
|
| 1419 |
+
[ 0, 1/2, 0, 0, 1/2]])
|
| 1420 |
+
|
| 1421 |
+
The new states are [3, 1, 2, 4, 5] and you can
|
| 1422 |
+
create a new chain with this and its canonical
|
| 1423 |
+
form will remain the same (since it is already
|
| 1424 |
+
in canonical form).
|
| 1425 |
+
|
| 1426 |
+
>>> X = DiscreteMarkovChain('X', states, new_matrix)
|
| 1427 |
+
>>> states, new_matrix = X.canonical_form()
|
| 1428 |
+
>>> states
|
| 1429 |
+
[3, 1, 2, 4, 5]
|
| 1430 |
+
|
| 1431 |
+
>>> new_matrix
|
| 1432 |
+
Matrix([
|
| 1433 |
+
[ 1, 0, 0, 0, 0],
|
| 1434 |
+
[ 0, 1/2, 1/2, 0, 0],
|
| 1435 |
+
[2/5, 2/5, 1/5, 0, 0],
|
| 1436 |
+
[1/2, 0, 0, 1/2, 0],
|
| 1437 |
+
[ 0, 1/2, 0, 0, 1/2]])
|
| 1438 |
+
|
| 1439 |
+
This is not limited to absorbing chains:
|
| 1440 |
+
|
| 1441 |
+
>>> T = Matrix([[0, 5, 5, 0, 0],
|
| 1442 |
+
... [0, 0, 0, 10, 0],
|
| 1443 |
+
... [5, 0, 5, 0, 0],
|
| 1444 |
+
... [0, 10, 0, 0, 0],
|
| 1445 |
+
... [0, 3, 0, 3, 4]])/10
|
| 1446 |
+
>>> X = DiscreteMarkovChain('X', trans_probs=T)
|
| 1447 |
+
>>> states, new_matrix = X.canonical_form()
|
| 1448 |
+
>>> states
|
| 1449 |
+
[1, 3, 0, 2, 4]
|
| 1450 |
+
|
| 1451 |
+
>>> new_matrix
|
| 1452 |
+
Matrix([
|
| 1453 |
+
[ 0, 1, 0, 0, 0],
|
| 1454 |
+
[ 1, 0, 0, 0, 0],
|
| 1455 |
+
[ 1/2, 0, 0, 1/2, 0],
|
| 1456 |
+
[ 0, 0, 1/2, 1/2, 0],
|
| 1457 |
+
[3/10, 3/10, 0, 0, 2/5]])
|
| 1458 |
+
|
| 1459 |
+
See Also
|
| 1460 |
+
========
|
| 1461 |
+
|
| 1462 |
+
sympy.stats.DiscreteMarkovChain.communication_classes
|
| 1463 |
+
sympy.stats.DiscreteMarkovChain.decompose
|
| 1464 |
+
|
| 1465 |
+
References
|
| 1466 |
+
==========
|
| 1467 |
+
|
| 1468 |
+
.. [1] https://onlinelibrary.wiley.com/doi/pdf/10.1002/9780470316887.app1
|
| 1469 |
+
.. [2] http://www.columbia.edu/~ww2040/6711F12/lect1023big.pdf
|
| 1470 |
+
"""
|
| 1471 |
+
states, A, B, C = self.decompose()
|
| 1472 |
+
O = zeros(A.shape[0], C.shape[1])
|
| 1473 |
+
return states, BlockMatrix([[A, O], [B, C]]).as_explicit()
|
| 1474 |
+
|
| 1475 |
+
def sample(self):
|
| 1476 |
+
"""
|
| 1477 |
+
Returns
|
| 1478 |
+
=======
|
| 1479 |
+
|
| 1480 |
+
sample: iterator object
|
| 1481 |
+
iterator object containing the sample
|
| 1482 |
+
|
| 1483 |
+
"""
|
| 1484 |
+
if not isinstance(self.transition_probabilities, (Matrix, ImmutableMatrix)):
|
| 1485 |
+
raise ValueError("Transition Matrix must be provided for sampling")
|
| 1486 |
+
Tlist = self.transition_probabilities.tolist()
|
| 1487 |
+
samps = [random.choice(list(self.state_space))]
|
| 1488 |
+
yield samps[0]
|
| 1489 |
+
time = 1
|
| 1490 |
+
densities = {}
|
| 1491 |
+
for state in self.state_space:
|
| 1492 |
+
states = list(self.state_space)
|
| 1493 |
+
densities[state] = {states[i]: Tlist[state][i]
|
| 1494 |
+
for i in range(len(states))}
|
| 1495 |
+
while time < S.Infinity:
|
| 1496 |
+
samps.append((next(sample_iter(FiniteRV("_", densities[samps[time - 1]])))))
|
| 1497 |
+
yield samps[time]
|
| 1498 |
+
time += 1
|
| 1499 |
+
|
| 1500 |
+
class ContinuousMarkovChain(ContinuousTimeStochasticProcess, MarkovProcess):
|
| 1501 |
+
"""
|
| 1502 |
+
Represents continuous time Markov chain.
|
| 1503 |
+
|
| 1504 |
+
Parameters
|
| 1505 |
+
==========
|
| 1506 |
+
|
| 1507 |
+
sym : Symbol/str
|
| 1508 |
+
state_space : Set
|
| 1509 |
+
Optional, by default, S.Reals
|
| 1510 |
+
gen_mat : Matrix/ImmutableMatrix/MatrixSymbol
|
| 1511 |
+
Optional, by default, None
|
| 1512 |
+
|
| 1513 |
+
Examples
|
| 1514 |
+
========
|
| 1515 |
+
|
| 1516 |
+
>>> from sympy.stats import ContinuousMarkovChain, P
|
| 1517 |
+
>>> from sympy import Matrix, S, Eq, Gt
|
| 1518 |
+
>>> G = Matrix([[-S(1), S(1)], [S(1), -S(1)]])
|
| 1519 |
+
>>> C = ContinuousMarkovChain('C', state_space=[0, 1], gen_mat=G)
|
| 1520 |
+
>>> C.limiting_distribution()
|
| 1521 |
+
Matrix([[1/2, 1/2]])
|
| 1522 |
+
>>> C.state_space
|
| 1523 |
+
{0, 1}
|
| 1524 |
+
>>> C.generator_matrix
|
| 1525 |
+
Matrix([
|
| 1526 |
+
[-1, 1],
|
| 1527 |
+
[ 1, -1]])
|
| 1528 |
+
|
| 1529 |
+
Probability queries are supported
|
| 1530 |
+
|
| 1531 |
+
>>> P(Eq(C(1.96), 0), Eq(C(0.78), 1)).round(5)
|
| 1532 |
+
0.45279
|
| 1533 |
+
>>> P(Gt(C(1.7), 0), Eq(C(0.82), 1)).round(5)
|
| 1534 |
+
0.58602
|
| 1535 |
+
|
| 1536 |
+
Probability of expressions with multiple RandomIndexedSymbols
|
| 1537 |
+
can also be calculated provided there is only 1 RandomIndexedSymbol
|
| 1538 |
+
in the given condition. It is always better to use Rational instead
|
| 1539 |
+
of floating point numbers for the probabilities in the
|
| 1540 |
+
generator matrix to avoid errors.
|
| 1541 |
+
|
| 1542 |
+
>>> from sympy import Gt, Le, Rational
|
| 1543 |
+
>>> G = Matrix([[-S(1), Rational(1, 10), Rational(9, 10)], [Rational(2, 5), -S(1), Rational(3, 5)], [Rational(1, 2), Rational(1, 2), -S(1)]])
|
| 1544 |
+
>>> C = ContinuousMarkovChain('C', state_space=[0, 1, 2], gen_mat=G)
|
| 1545 |
+
>>> P(Eq(C(3.92), C(1.75)), Eq(C(0.46), 0)).round(5)
|
| 1546 |
+
0.37933
|
| 1547 |
+
>>> P(Gt(C(3.92), C(1.75)), Eq(C(0.46), 0)).round(5)
|
| 1548 |
+
0.34211
|
| 1549 |
+
>>> P(Le(C(1.57), C(3.14)), Eq(C(1.22), 1)).round(4)
|
| 1550 |
+
0.7143
|
| 1551 |
+
|
| 1552 |
+
Symbolic probability queries are also supported
|
| 1553 |
+
|
| 1554 |
+
>>> from sympy import symbols
|
| 1555 |
+
>>> a,b,c,d = symbols('a b c d')
|
| 1556 |
+
>>> G = Matrix([[-S(1), Rational(1, 10), Rational(9, 10)], [Rational(2, 5), -S(1), Rational(3, 5)], [Rational(1, 2), Rational(1, 2), -S(1)]])
|
| 1557 |
+
>>> C = ContinuousMarkovChain('C', state_space=[0, 1, 2], gen_mat=G)
|
| 1558 |
+
>>> query = P(Eq(C(a), b), Eq(C(c), d))
|
| 1559 |
+
>>> query.subs({a:3.65, b:2, c:1.78, d:1}).evalf().round(10)
|
| 1560 |
+
0.4002723175
|
| 1561 |
+
>>> P(Eq(C(3.65), 2), Eq(C(1.78), 1)).round(10)
|
| 1562 |
+
0.4002723175
|
| 1563 |
+
>>> query_gt = P(Gt(C(a), b), Eq(C(c), d))
|
| 1564 |
+
>>> query_gt.subs({a:43.2, b:0, c:3.29, d:2}).evalf().round(10)
|
| 1565 |
+
0.6832579186
|
| 1566 |
+
>>> P(Gt(C(43.2), 0), Eq(C(3.29), 2)).round(10)
|
| 1567 |
+
0.6832579186
|
| 1568 |
+
|
| 1569 |
+
References
|
| 1570 |
+
==========
|
| 1571 |
+
|
| 1572 |
+
.. [1] https://en.wikipedia.org/wiki/Markov_chain#Continuous-time_Markov_chain
|
| 1573 |
+
.. [2] https://u.math.biu.ac.il/~amirgi/CTMCnotes.pdf
|
| 1574 |
+
"""
|
| 1575 |
+
index_set = S.Reals
|
| 1576 |
+
|
| 1577 |
+
def __new__(cls, sym, state_space=None, gen_mat=None):
|
| 1578 |
+
sym = _symbol_converter(sym)
|
| 1579 |
+
state_space, gen_mat = MarkovProcess._sanity_checks(state_space, gen_mat)
|
| 1580 |
+
obj = Basic.__new__(cls, sym, state_space, gen_mat)
|
| 1581 |
+
indices = {}
|
| 1582 |
+
if isinstance(obj.number_of_states, Integer):
|
| 1583 |
+
for index, state in enumerate(obj.state_space):
|
| 1584 |
+
indices[state] = index
|
| 1585 |
+
obj.index_of = indices
|
| 1586 |
+
return obj
|
| 1587 |
+
|
| 1588 |
+
@property
|
| 1589 |
+
def generator_matrix(self):
|
| 1590 |
+
return self.args[2]
|
| 1591 |
+
|
| 1592 |
+
@cacheit
|
| 1593 |
+
def transition_probabilities(self, gen_mat=None):
|
| 1594 |
+
t = Dummy('t')
|
| 1595 |
+
if isinstance(gen_mat, (Matrix, ImmutableMatrix)) and \
|
| 1596 |
+
gen_mat.is_diagonalizable():
|
| 1597 |
+
# for faster computation use diagonalized generator matrix
|
| 1598 |
+
Q, D = gen_mat.diagonalize()
|
| 1599 |
+
return Lambda(t, Q*exp(t*D)*Q.inv())
|
| 1600 |
+
if gen_mat != None:
|
| 1601 |
+
return Lambda(t, exp(t*gen_mat))
|
| 1602 |
+
|
| 1603 |
+
def limiting_distribution(self):
|
| 1604 |
+
gen_mat = self.generator_matrix
|
| 1605 |
+
if gen_mat is None:
|
| 1606 |
+
return None
|
| 1607 |
+
if isinstance(gen_mat, MatrixSymbol):
|
| 1608 |
+
wm = MatrixSymbol('wm', 1, gen_mat.shape[0])
|
| 1609 |
+
return Lambda((wm, gen_mat), Eq(wm*gen_mat, wm))
|
| 1610 |
+
w = IndexedBase('w')
|
| 1611 |
+
wi = [w[i] for i in range(gen_mat.shape[0])]
|
| 1612 |
+
wm = Matrix([wi])
|
| 1613 |
+
eqs = (wm*gen_mat).tolist()[0]
|
| 1614 |
+
eqs.append(sum(wi) - 1)
|
| 1615 |
+
soln = list(linsolve(eqs, wi))[0]
|
| 1616 |
+
return ImmutableMatrix([soln])
|
| 1617 |
+
|
| 1618 |
+
|
| 1619 |
+
class BernoulliProcess(DiscreteTimeStochasticProcess):
|
| 1620 |
+
"""
|
| 1621 |
+
The Bernoulli process consists of repeated
|
| 1622 |
+
independent Bernoulli process trials with the same parameter `p`.
|
| 1623 |
+
It's assumed that the probability `p` applies to every
|
| 1624 |
+
trial and that the outcomes of each trial
|
| 1625 |
+
are independent of all the rest. Therefore Bernoulli Process
|
| 1626 |
+
is Discrete State and Discrete Time Stochastic Process.
|
| 1627 |
+
|
| 1628 |
+
Parameters
|
| 1629 |
+
==========
|
| 1630 |
+
|
| 1631 |
+
sym : Symbol/str
|
| 1632 |
+
success : Integer/str
|
| 1633 |
+
The event which is considered to be success. Default: 1.
|
| 1634 |
+
failure: Integer/str
|
| 1635 |
+
The event which is considered to be failure. Default: 0.
|
| 1636 |
+
p : Real Number between 0 and 1
|
| 1637 |
+
Represents the probability of getting success.
|
| 1638 |
+
|
| 1639 |
+
Examples
|
| 1640 |
+
========
|
| 1641 |
+
|
| 1642 |
+
>>> from sympy.stats import BernoulliProcess, P, E
|
| 1643 |
+
>>> from sympy import Eq, Gt
|
| 1644 |
+
>>> B = BernoulliProcess("B", p=0.7, success=1, failure=0)
|
| 1645 |
+
>>> B.state_space
|
| 1646 |
+
{0, 1}
|
| 1647 |
+
>>> B.p.round(2)
|
| 1648 |
+
0.70
|
| 1649 |
+
>>> B.success
|
| 1650 |
+
1
|
| 1651 |
+
>>> B.failure
|
| 1652 |
+
0
|
| 1653 |
+
>>> X = B[1] + B[2] + B[3]
|
| 1654 |
+
>>> P(Eq(X, 0)).round(2)
|
| 1655 |
+
0.03
|
| 1656 |
+
>>> P(Eq(X, 2)).round(2)
|
| 1657 |
+
0.44
|
| 1658 |
+
>>> P(Eq(X, 4)).round(2)
|
| 1659 |
+
0
|
| 1660 |
+
>>> P(Gt(X, 1)).round(2)
|
| 1661 |
+
0.78
|
| 1662 |
+
>>> P(Eq(B[1], 0) & Eq(B[2], 1) & Eq(B[3], 0) & Eq(B[4], 1)).round(2)
|
| 1663 |
+
0.04
|
| 1664 |
+
>>> B.joint_distribution(B[1], B[2])
|
| 1665 |
+
JointDistributionHandmade(Lambda((B[1], B[2]), Piecewise((0.7, Eq(B[1], 1)),
|
| 1666 |
+
(0.3, Eq(B[1], 0)), (0, True))*Piecewise((0.7, Eq(B[2], 1)), (0.3, Eq(B[2], 0)),
|
| 1667 |
+
(0, True))))
|
| 1668 |
+
>>> E(2*B[1] + B[2]).round(2)
|
| 1669 |
+
2.10
|
| 1670 |
+
>>> P(B[1] < 1).round(2)
|
| 1671 |
+
0.30
|
| 1672 |
+
|
| 1673 |
+
References
|
| 1674 |
+
==========
|
| 1675 |
+
|
| 1676 |
+
.. [1] https://en.wikipedia.org/wiki/Bernoulli_process
|
| 1677 |
+
.. [2] https://mathcs.clarku.edu/~djoyce/ma217/bernoulli.pdf
|
| 1678 |
+
|
| 1679 |
+
"""
|
| 1680 |
+
|
| 1681 |
+
index_set = S.Naturals0
|
| 1682 |
+
|
| 1683 |
+
def __new__(cls, sym, p, success=1, failure=0):
|
| 1684 |
+
_value_check(p >= 0 and p <= 1, 'Value of p must be between 0 and 1.')
|
| 1685 |
+
sym = _symbol_converter(sym)
|
| 1686 |
+
p = _sympify(p)
|
| 1687 |
+
success = _sym_sympify(success)
|
| 1688 |
+
failure = _sym_sympify(failure)
|
| 1689 |
+
return Basic.__new__(cls, sym, p, success, failure)
|
| 1690 |
+
|
| 1691 |
+
@property
|
| 1692 |
+
def symbol(self):
|
| 1693 |
+
return self.args[0]
|
| 1694 |
+
|
| 1695 |
+
@property
|
| 1696 |
+
def p(self):
|
| 1697 |
+
return self.args[1]
|
| 1698 |
+
|
| 1699 |
+
@property
|
| 1700 |
+
def success(self):
|
| 1701 |
+
return self.args[2]
|
| 1702 |
+
|
| 1703 |
+
@property
|
| 1704 |
+
def failure(self):
|
| 1705 |
+
return self.args[3]
|
| 1706 |
+
|
| 1707 |
+
@property
|
| 1708 |
+
def state_space(self):
|
| 1709 |
+
return _set_converter([self.success, self.failure])
|
| 1710 |
+
|
| 1711 |
+
def distribution(self, key=None):
|
| 1712 |
+
if key is None:
|
| 1713 |
+
self._deprecation_warn_distribution()
|
| 1714 |
+
return BernoulliDistribution(self.p)
|
| 1715 |
+
return BernoulliDistribution(self.p, self.success, self.failure)
|
| 1716 |
+
|
| 1717 |
+
def simple_rv(self, rv):
|
| 1718 |
+
return Bernoulli(rv.name, p=self.p,
|
| 1719 |
+
succ=self.success, fail=self.failure)
|
| 1720 |
+
|
| 1721 |
+
def expectation(self, expr, condition=None, evaluate=True, **kwargs):
|
| 1722 |
+
"""
|
| 1723 |
+
Computes expectation.
|
| 1724 |
+
|
| 1725 |
+
Parameters
|
| 1726 |
+
==========
|
| 1727 |
+
|
| 1728 |
+
expr : RandomIndexedSymbol, Relational, Logic
|
| 1729 |
+
Condition for which expectation has to be computed. Must
|
| 1730 |
+
contain a RandomIndexedSymbol of the process.
|
| 1731 |
+
condition : Relational, Logic
|
| 1732 |
+
The given conditions under which computations should be done.
|
| 1733 |
+
|
| 1734 |
+
Returns
|
| 1735 |
+
=======
|
| 1736 |
+
|
| 1737 |
+
Expectation of the RandomIndexedSymbol.
|
| 1738 |
+
|
| 1739 |
+
"""
|
| 1740 |
+
|
| 1741 |
+
return _SubstituteRV._expectation(expr, condition, evaluate, **kwargs)
|
| 1742 |
+
|
| 1743 |
+
def probability(self, condition, given_condition=None, evaluate=True, **kwargs):
|
| 1744 |
+
"""
|
| 1745 |
+
Computes probability.
|
| 1746 |
+
|
| 1747 |
+
Parameters
|
| 1748 |
+
==========
|
| 1749 |
+
|
| 1750 |
+
condition : Relational
|
| 1751 |
+
Condition for which probability has to be computed. Must
|
| 1752 |
+
contain a RandomIndexedSymbol of the process.
|
| 1753 |
+
given_condition : Relational, Logic
|
| 1754 |
+
The given conditions under which computations should be done.
|
| 1755 |
+
|
| 1756 |
+
Returns
|
| 1757 |
+
=======
|
| 1758 |
+
|
| 1759 |
+
Probability of the condition.
|
| 1760 |
+
|
| 1761 |
+
"""
|
| 1762 |
+
|
| 1763 |
+
return _SubstituteRV._probability(condition, given_condition, evaluate, **kwargs)
|
| 1764 |
+
|
| 1765 |
+
def density(self, x):
|
| 1766 |
+
return Piecewise((self.p, Eq(x, self.success)),
|
| 1767 |
+
(1 - self.p, Eq(x, self.failure)),
|
| 1768 |
+
(S.Zero, True))
|
| 1769 |
+
|
| 1770 |
+
class _SubstituteRV:
|
| 1771 |
+
"""
|
| 1772 |
+
Internal class to handle the queries of expectation and probability
|
| 1773 |
+
by substitution.
|
| 1774 |
+
"""
|
| 1775 |
+
|
| 1776 |
+
@staticmethod
|
| 1777 |
+
def _rvindexed_subs(expr, condition=None):
|
| 1778 |
+
"""
|
| 1779 |
+
Substitutes the RandomIndexedSymbol with the RandomSymbol with
|
| 1780 |
+
same name, distribution and probability as RandomIndexedSymbol.
|
| 1781 |
+
|
| 1782 |
+
Parameters
|
| 1783 |
+
==========
|
| 1784 |
+
|
| 1785 |
+
expr: RandomIndexedSymbol, Relational, Logic
|
| 1786 |
+
Condition for which expectation has to be computed. Must
|
| 1787 |
+
contain a RandomIndexedSymbol of the process.
|
| 1788 |
+
condition: Relational, Logic
|
| 1789 |
+
The given conditions under which computations should be done.
|
| 1790 |
+
|
| 1791 |
+
"""
|
| 1792 |
+
|
| 1793 |
+
rvs_expr = random_symbols(expr)
|
| 1794 |
+
if len(rvs_expr) != 0:
|
| 1795 |
+
swapdict_expr = {}
|
| 1796 |
+
for rv in rvs_expr:
|
| 1797 |
+
if isinstance(rv, RandomIndexedSymbol):
|
| 1798 |
+
newrv = rv.pspace.process.simple_rv(rv) # substitute with equivalent simple rv
|
| 1799 |
+
swapdict_expr[rv] = newrv
|
| 1800 |
+
expr = expr.subs(swapdict_expr)
|
| 1801 |
+
rvs_cond = random_symbols(condition)
|
| 1802 |
+
if len(rvs_cond)!=0:
|
| 1803 |
+
swapdict_cond = {}
|
| 1804 |
+
for rv in rvs_cond:
|
| 1805 |
+
if isinstance(rv, RandomIndexedSymbol):
|
| 1806 |
+
newrv = rv.pspace.process.simple_rv(rv)
|
| 1807 |
+
swapdict_cond[rv] = newrv
|
| 1808 |
+
condition = condition.subs(swapdict_cond)
|
| 1809 |
+
return expr, condition
|
| 1810 |
+
|
| 1811 |
+
@classmethod
|
| 1812 |
+
def _expectation(self, expr, condition=None, evaluate=True, **kwargs):
|
| 1813 |
+
"""
|
| 1814 |
+
Internal method for computing expectation of indexed RV.
|
| 1815 |
+
|
| 1816 |
+
Parameters
|
| 1817 |
+
==========
|
| 1818 |
+
|
| 1819 |
+
expr: RandomIndexedSymbol, Relational, Logic
|
| 1820 |
+
Condition for which expectation has to be computed. Must
|
| 1821 |
+
contain a RandomIndexedSymbol of the process.
|
| 1822 |
+
condition: Relational, Logic
|
| 1823 |
+
The given conditions under which computations should be done.
|
| 1824 |
+
|
| 1825 |
+
Returns
|
| 1826 |
+
=======
|
| 1827 |
+
|
| 1828 |
+
Expectation of the RandomIndexedSymbol.
|
| 1829 |
+
|
| 1830 |
+
"""
|
| 1831 |
+
new_expr, new_condition = self._rvindexed_subs(expr, condition)
|
| 1832 |
+
|
| 1833 |
+
if not is_random(new_expr):
|
| 1834 |
+
return new_expr
|
| 1835 |
+
new_pspace = pspace(new_expr)
|
| 1836 |
+
if new_condition is not None:
|
| 1837 |
+
new_expr = given(new_expr, new_condition)
|
| 1838 |
+
if new_expr.is_Add: # As E is Linear
|
| 1839 |
+
return Add(*[new_pspace.compute_expectation(
|
| 1840 |
+
expr=arg, evaluate=evaluate, **kwargs)
|
| 1841 |
+
for arg in new_expr.args])
|
| 1842 |
+
return new_pspace.compute_expectation(
|
| 1843 |
+
new_expr, evaluate=evaluate, **kwargs)
|
| 1844 |
+
|
| 1845 |
+
@classmethod
|
| 1846 |
+
def _probability(self, condition, given_condition=None, evaluate=True, **kwargs):
|
| 1847 |
+
"""
|
| 1848 |
+
Internal method for computing probability of indexed RV
|
| 1849 |
+
|
| 1850 |
+
Parameters
|
| 1851 |
+
==========
|
| 1852 |
+
|
| 1853 |
+
condition: Relational
|
| 1854 |
+
Condition for which probability has to be computed. Must
|
| 1855 |
+
contain a RandomIndexedSymbol of the process.
|
| 1856 |
+
given_condition: Relational/And
|
| 1857 |
+
The given conditions under which computations should be done.
|
| 1858 |
+
|
| 1859 |
+
Returns
|
| 1860 |
+
=======
|
| 1861 |
+
|
| 1862 |
+
Probability of the condition.
|
| 1863 |
+
|
| 1864 |
+
"""
|
| 1865 |
+
new_condition, new_givencondition = self._rvindexed_subs(condition, given_condition)
|
| 1866 |
+
|
| 1867 |
+
if isinstance(new_givencondition, RandomSymbol):
|
| 1868 |
+
condrv = random_symbols(new_condition)
|
| 1869 |
+
if len(condrv) == 1 and condrv[0] == new_givencondition:
|
| 1870 |
+
return BernoulliDistribution(self._probability(new_condition), 0, 1)
|
| 1871 |
+
|
| 1872 |
+
if any(dependent(rv, new_givencondition) for rv in condrv):
|
| 1873 |
+
return Probability(new_condition, new_givencondition)
|
| 1874 |
+
else:
|
| 1875 |
+
return self._probability(new_condition)
|
| 1876 |
+
|
| 1877 |
+
if new_givencondition is not None and \
|
| 1878 |
+
not isinstance(new_givencondition, (Relational, Boolean)):
|
| 1879 |
+
raise ValueError("%s is not a relational or combination of relationals"
|
| 1880 |
+
% (new_givencondition))
|
| 1881 |
+
if new_givencondition == False or new_condition == False:
|
| 1882 |
+
return S.Zero
|
| 1883 |
+
if new_condition == True:
|
| 1884 |
+
return S.One
|
| 1885 |
+
if not isinstance(new_condition, (Relational, Boolean)):
|
| 1886 |
+
raise ValueError("%s is not a relational or combination of relationals"
|
| 1887 |
+
% (new_condition))
|
| 1888 |
+
|
| 1889 |
+
if new_givencondition is not None: # If there is a condition
|
| 1890 |
+
# Recompute on new conditional expr
|
| 1891 |
+
return self._probability(given(new_condition, new_givencondition, **kwargs), **kwargs)
|
| 1892 |
+
result = pspace(new_condition).probability(new_condition, **kwargs)
|
| 1893 |
+
if evaluate and hasattr(result, 'doit'):
|
| 1894 |
+
return result.doit()
|
| 1895 |
+
else:
|
| 1896 |
+
return result
|
| 1897 |
+
|
| 1898 |
+
def get_timerv_swaps(expr, condition):
|
| 1899 |
+
"""
|
| 1900 |
+
Finds the appropriate interval for each time stamp in expr by parsing
|
| 1901 |
+
the given condition and returns intervals for each timestamp and
|
| 1902 |
+
dictionary that maps variable time-stamped Random Indexed Symbol to its
|
| 1903 |
+
corresponding Random Indexed variable with fixed time stamp.
|
| 1904 |
+
|
| 1905 |
+
Parameters
|
| 1906 |
+
==========
|
| 1907 |
+
|
| 1908 |
+
expr: SymPy Expression
|
| 1909 |
+
Expression containing Random Indexed Symbols with variable time stamps
|
| 1910 |
+
condition: Relational/Boolean Expression
|
| 1911 |
+
Expression containing time bounds of variable time stamps in expr
|
| 1912 |
+
|
| 1913 |
+
Examples
|
| 1914 |
+
========
|
| 1915 |
+
|
| 1916 |
+
>>> from sympy.stats.stochastic_process_types import get_timerv_swaps, PoissonProcess
|
| 1917 |
+
>>> from sympy import symbols, Contains, Interval
|
| 1918 |
+
>>> x, t, d = symbols('x t d', positive=True)
|
| 1919 |
+
>>> X = PoissonProcess("X", 3)
|
| 1920 |
+
>>> get_timerv_swaps(x*X(t), Contains(t, Interval.Lopen(0, 1)))
|
| 1921 |
+
([Interval.Lopen(0, 1)], {X(t): X(1)})
|
| 1922 |
+
>>> get_timerv_swaps((X(t)**2 + X(d)**2), Contains(t, Interval.Lopen(0, 1))
|
| 1923 |
+
... & Contains(d, Interval.Ropen(1, 4))) # doctest: +SKIP
|
| 1924 |
+
([Interval.Ropen(1, 4), Interval.Lopen(0, 1)], {X(d): X(3), X(t): X(1)})
|
| 1925 |
+
|
| 1926 |
+
Returns
|
| 1927 |
+
=======
|
| 1928 |
+
|
| 1929 |
+
intervals: list
|
| 1930 |
+
List of Intervals/FiniteSet on which each time stamp is defined
|
| 1931 |
+
rv_swap: dict
|
| 1932 |
+
Dictionary mapping variable time Random Indexed Symbol to constant time
|
| 1933 |
+
Random Indexed Variable
|
| 1934 |
+
|
| 1935 |
+
"""
|
| 1936 |
+
|
| 1937 |
+
if not isinstance(condition, (Relational, Boolean)):
|
| 1938 |
+
raise ValueError("%s is not a relational or combination of relationals"
|
| 1939 |
+
% (condition))
|
| 1940 |
+
expr_syms = list(expr.atoms(RandomIndexedSymbol))
|
| 1941 |
+
if isinstance(condition, (And, Or)):
|
| 1942 |
+
given_cond_args = condition.args
|
| 1943 |
+
else: # single condition
|
| 1944 |
+
given_cond_args = (condition, )
|
| 1945 |
+
rv_swap = {}
|
| 1946 |
+
intervals = []
|
| 1947 |
+
for expr_sym in expr_syms:
|
| 1948 |
+
for arg in given_cond_args:
|
| 1949 |
+
if arg.has(expr_sym.key) and isinstance(expr_sym.key, Symbol):
|
| 1950 |
+
intv = _set_converter(arg.args[1])
|
| 1951 |
+
diff_key = intv._sup - intv._inf
|
| 1952 |
+
if diff_key == oo:
|
| 1953 |
+
raise ValueError("%s should have finite bounds" % str(expr_sym.name))
|
| 1954 |
+
elif diff_key == S.Zero: # has singleton set
|
| 1955 |
+
diff_key = intv._sup
|
| 1956 |
+
rv_swap[expr_sym] = expr_sym.subs({expr_sym.key: diff_key})
|
| 1957 |
+
intervals.append(intv)
|
| 1958 |
+
return intervals, rv_swap
|
| 1959 |
+
|
| 1960 |
+
|
| 1961 |
+
class CountingProcess(ContinuousTimeStochasticProcess):
|
| 1962 |
+
"""
|
| 1963 |
+
This class handles the common methods of the Counting Processes
|
| 1964 |
+
such as Poisson, Wiener and Gamma Processes
|
| 1965 |
+
"""
|
| 1966 |
+
index_set = _set_converter(Interval(0, oo))
|
| 1967 |
+
|
| 1968 |
+
@property
|
| 1969 |
+
def symbol(self):
|
| 1970 |
+
return self.args[0]
|
| 1971 |
+
|
| 1972 |
+
def expectation(self, expr, condition=None, evaluate=True, **kwargs):
|
| 1973 |
+
"""
|
| 1974 |
+
Computes expectation
|
| 1975 |
+
|
| 1976 |
+
Parameters
|
| 1977 |
+
==========
|
| 1978 |
+
|
| 1979 |
+
expr: RandomIndexedSymbol, Relational, Logic
|
| 1980 |
+
Condition for which expectation has to be computed. Must
|
| 1981 |
+
contain a RandomIndexedSymbol of the process.
|
| 1982 |
+
condition: Relational, Boolean
|
| 1983 |
+
The given conditions under which computations should be done, i.e,
|
| 1984 |
+
the intervals on which each variable time stamp in expr is defined
|
| 1985 |
+
|
| 1986 |
+
Returns
|
| 1987 |
+
=======
|
| 1988 |
+
|
| 1989 |
+
Expectation of the given expr
|
| 1990 |
+
|
| 1991 |
+
"""
|
| 1992 |
+
if condition is not None:
|
| 1993 |
+
intervals, rv_swap = get_timerv_swaps(expr, condition)
|
| 1994 |
+
# they are independent when they have non-overlapping intervals
|
| 1995 |
+
if len(intervals) == 1 or all(Intersection(*intv_comb) == EmptySet
|
| 1996 |
+
for intv_comb in itertools.combinations(intervals, 2)):
|
| 1997 |
+
if expr.is_Add:
|
| 1998 |
+
return Add.fromiter(self.expectation(arg, condition)
|
| 1999 |
+
for arg in expr.args)
|
| 2000 |
+
expr = expr.subs(rv_swap)
|
| 2001 |
+
else:
|
| 2002 |
+
return Expectation(expr, condition)
|
| 2003 |
+
|
| 2004 |
+
return _SubstituteRV._expectation(expr, evaluate=evaluate, **kwargs)
|
| 2005 |
+
|
| 2006 |
+
def _solve_argwith_tworvs(self, arg):
|
| 2007 |
+
if arg.args[0].key >= arg.args[1].key or isinstance(arg, Eq):
|
| 2008 |
+
diff_key = abs(arg.args[0].key - arg.args[1].key)
|
| 2009 |
+
rv = arg.args[0]
|
| 2010 |
+
arg = arg.__class__(rv.pspace.process(diff_key), 0)
|
| 2011 |
+
else:
|
| 2012 |
+
diff_key = arg.args[1].key - arg.args[0].key
|
| 2013 |
+
rv = arg.args[1]
|
| 2014 |
+
arg = arg.__class__(rv.pspace.process(diff_key), 0)
|
| 2015 |
+
return arg
|
| 2016 |
+
|
| 2017 |
+
def _solve_numerical(self, condition, given_condition=None):
|
| 2018 |
+
if isinstance(condition, And):
|
| 2019 |
+
args_list = list(condition.args)
|
| 2020 |
+
else:
|
| 2021 |
+
args_list = [condition]
|
| 2022 |
+
if given_condition is not None:
|
| 2023 |
+
if isinstance(given_condition, And):
|
| 2024 |
+
args_list.extend(list(given_condition.args))
|
| 2025 |
+
else:
|
| 2026 |
+
args_list.extend([given_condition])
|
| 2027 |
+
# sort the args based on timestamp to get the independent increments in
|
| 2028 |
+
# each segment using all the condition args as well as given_condition args
|
| 2029 |
+
args_list = sorted(args_list, key=lambda x: x.args[0].key)
|
| 2030 |
+
result = []
|
| 2031 |
+
cond_args = list(condition.args) if isinstance(condition, And) else [condition]
|
| 2032 |
+
if args_list[0] in cond_args and not (is_random(args_list[0].args[0])
|
| 2033 |
+
and is_random(args_list[0].args[1])):
|
| 2034 |
+
result.append(_SubstituteRV._probability(args_list[0]))
|
| 2035 |
+
|
| 2036 |
+
if is_random(args_list[0].args[0]) and is_random(args_list[0].args[1]):
|
| 2037 |
+
arg = self._solve_argwith_tworvs(args_list[0])
|
| 2038 |
+
result.append(_SubstituteRV._probability(arg))
|
| 2039 |
+
|
| 2040 |
+
for i in range(len(args_list) - 1):
|
| 2041 |
+
curr, nex = args_list[i], args_list[i + 1]
|
| 2042 |
+
diff_key = nex.args[0].key - curr.args[0].key
|
| 2043 |
+
working_set = curr.args[0].pspace.process.state_space
|
| 2044 |
+
if curr.args[1] > nex.args[1]: #impossible condition so return 0
|
| 2045 |
+
result.append(0)
|
| 2046 |
+
break
|
| 2047 |
+
if isinstance(curr, Eq):
|
| 2048 |
+
working_set = Intersection(working_set, Interval.Lopen(curr.args[1], oo))
|
| 2049 |
+
else:
|
| 2050 |
+
working_set = Intersection(working_set, curr.as_set())
|
| 2051 |
+
if isinstance(nex, Eq):
|
| 2052 |
+
working_set = Intersection(working_set, Interval(-oo, nex.args[1]))
|
| 2053 |
+
else:
|
| 2054 |
+
working_set = Intersection(working_set, nex.as_set())
|
| 2055 |
+
if working_set == EmptySet:
|
| 2056 |
+
rv = Eq(curr.args[0].pspace.process(diff_key), 0)
|
| 2057 |
+
result.append(_SubstituteRV._probability(rv))
|
| 2058 |
+
else:
|
| 2059 |
+
if working_set.is_finite_set:
|
| 2060 |
+
if isinstance(curr, Eq) and isinstance(nex, Eq):
|
| 2061 |
+
rv = Eq(curr.args[0].pspace.process(diff_key), len(working_set))
|
| 2062 |
+
result.append(_SubstituteRV._probability(rv))
|
| 2063 |
+
elif isinstance(curr, Eq) ^ isinstance(nex, Eq):
|
| 2064 |
+
result.append(Add.fromiter(_SubstituteRV._probability(Eq(
|
| 2065 |
+
curr.args[0].pspace.process(diff_key), x))
|
| 2066 |
+
for x in range(len(working_set))))
|
| 2067 |
+
else:
|
| 2068 |
+
n = len(working_set)
|
| 2069 |
+
result.append(Add.fromiter((n - x)*_SubstituteRV._probability(Eq(
|
| 2070 |
+
curr.args[0].pspace.process(diff_key), x)) for x in range(n)))
|
| 2071 |
+
else:
|
| 2072 |
+
result.append(_SubstituteRV._probability(
|
| 2073 |
+
curr.args[0].pspace.process(diff_key) <= working_set._sup - working_set._inf))
|
| 2074 |
+
return Mul.fromiter(result)
|
| 2075 |
+
|
| 2076 |
+
|
| 2077 |
+
def probability(self, condition, given_condition=None, evaluate=True, **kwargs):
|
| 2078 |
+
"""
|
| 2079 |
+
Computes probability.
|
| 2080 |
+
|
| 2081 |
+
Parameters
|
| 2082 |
+
==========
|
| 2083 |
+
|
| 2084 |
+
condition: Relational
|
| 2085 |
+
Condition for which probability has to be computed. Must
|
| 2086 |
+
contain a RandomIndexedSymbol of the process.
|
| 2087 |
+
given_condition: Relational, Boolean
|
| 2088 |
+
The given conditions under which computations should be done, i.e,
|
| 2089 |
+
the intervals on which each variable time stamp in expr is defined
|
| 2090 |
+
|
| 2091 |
+
Returns
|
| 2092 |
+
=======
|
| 2093 |
+
|
| 2094 |
+
Probability of the condition
|
| 2095 |
+
|
| 2096 |
+
"""
|
| 2097 |
+
check_numeric = True
|
| 2098 |
+
if isinstance(condition, (And, Or)):
|
| 2099 |
+
cond_args = condition.args
|
| 2100 |
+
else:
|
| 2101 |
+
cond_args = (condition, )
|
| 2102 |
+
# check that condition args are numeric or not
|
| 2103 |
+
if not all(arg.args[0].key.is_number for arg in cond_args):
|
| 2104 |
+
check_numeric = False
|
| 2105 |
+
if given_condition is not None:
|
| 2106 |
+
check_given_numeric = True
|
| 2107 |
+
if isinstance(given_condition, (And, Or)):
|
| 2108 |
+
given_cond_args = given_condition.args
|
| 2109 |
+
else:
|
| 2110 |
+
given_cond_args = (given_condition, )
|
| 2111 |
+
# check that given condition args are numeric or not
|
| 2112 |
+
if given_condition.has(Contains):
|
| 2113 |
+
check_given_numeric = False
|
| 2114 |
+
# Handle numerical queries
|
| 2115 |
+
if check_numeric and check_given_numeric:
|
| 2116 |
+
res = []
|
| 2117 |
+
if isinstance(condition, Or):
|
| 2118 |
+
res.append(Add.fromiter(self._solve_numerical(arg, given_condition)
|
| 2119 |
+
for arg in condition.args))
|
| 2120 |
+
if isinstance(given_condition, Or):
|
| 2121 |
+
res.append(Add.fromiter(self._solve_numerical(condition, arg)
|
| 2122 |
+
for arg in given_condition.args))
|
| 2123 |
+
if res:
|
| 2124 |
+
return Add.fromiter(res)
|
| 2125 |
+
return self._solve_numerical(condition, given_condition)
|
| 2126 |
+
|
| 2127 |
+
# No numeric queries, go by Contains?... then check that all the
|
| 2128 |
+
# given condition are in form of `Contains`
|
| 2129 |
+
if not all(arg.has(Contains) for arg in given_cond_args):
|
| 2130 |
+
raise ValueError("If given condition is passed with `Contains`, then "
|
| 2131 |
+
"please pass the evaluated condition with its corresponding information "
|
| 2132 |
+
"in terms of intervals of each time stamp to be passed in given condition.")
|
| 2133 |
+
|
| 2134 |
+
intervals, rv_swap = get_timerv_swaps(condition, given_condition)
|
| 2135 |
+
# they are independent when they have non-overlapping intervals
|
| 2136 |
+
if len(intervals) == 1 or all(Intersection(*intv_comb) == EmptySet
|
| 2137 |
+
for intv_comb in itertools.combinations(intervals, 2)):
|
| 2138 |
+
if isinstance(condition, And):
|
| 2139 |
+
return Mul.fromiter(self.probability(arg, given_condition)
|
| 2140 |
+
for arg in condition.args)
|
| 2141 |
+
elif isinstance(condition, Or):
|
| 2142 |
+
return Add.fromiter(self.probability(arg, given_condition)
|
| 2143 |
+
for arg in condition.args)
|
| 2144 |
+
condition = condition.subs(rv_swap)
|
| 2145 |
+
else:
|
| 2146 |
+
return Probability(condition, given_condition)
|
| 2147 |
+
if check_numeric:
|
| 2148 |
+
return self._solve_numerical(condition)
|
| 2149 |
+
return _SubstituteRV._probability(condition, evaluate=evaluate, **kwargs)
|
| 2150 |
+
|
| 2151 |
+
class PoissonProcess(CountingProcess):
|
| 2152 |
+
"""
|
| 2153 |
+
The Poisson process is a counting process. It is usually used in scenarios
|
| 2154 |
+
where we are counting the occurrences of certain events that appear
|
| 2155 |
+
to happen at a certain rate, but completely at random.
|
| 2156 |
+
|
| 2157 |
+
Parameters
|
| 2158 |
+
==========
|
| 2159 |
+
|
| 2160 |
+
sym : Symbol/str
|
| 2161 |
+
lamda : Positive number
|
| 2162 |
+
Rate of the process, ``lambda > 0``
|
| 2163 |
+
|
| 2164 |
+
Examples
|
| 2165 |
+
========
|
| 2166 |
+
|
| 2167 |
+
>>> from sympy.stats import PoissonProcess, P, E
|
| 2168 |
+
>>> from sympy import symbols, Eq, Ne, Contains, Interval
|
| 2169 |
+
>>> X = PoissonProcess("X", lamda=3)
|
| 2170 |
+
>>> X.state_space
|
| 2171 |
+
Naturals0
|
| 2172 |
+
>>> X.lamda
|
| 2173 |
+
3
|
| 2174 |
+
>>> t1, t2 = symbols('t1 t2', positive=True)
|
| 2175 |
+
>>> P(X(t1) < 4)
|
| 2176 |
+
(9*t1**3/2 + 9*t1**2/2 + 3*t1 + 1)*exp(-3*t1)
|
| 2177 |
+
>>> P(Eq(X(t1), 2) | Ne(X(t1), 4), Contains(t1, Interval.Ropen(2, 4)))
|
| 2178 |
+
1 - 36*exp(-6)
|
| 2179 |
+
>>> P(Eq(X(t1), 2) & Eq(X(t2), 3), Contains(t1, Interval.Lopen(0, 2))
|
| 2180 |
+
... & Contains(t2, Interval.Lopen(2, 4)))
|
| 2181 |
+
648*exp(-12)
|
| 2182 |
+
>>> E(X(t1))
|
| 2183 |
+
3*t1
|
| 2184 |
+
>>> E(X(t1)**2 + 2*X(t2), Contains(t1, Interval.Lopen(0, 1))
|
| 2185 |
+
... & Contains(t2, Interval.Lopen(1, 2)))
|
| 2186 |
+
18
|
| 2187 |
+
>>> P(X(3) < 1, Eq(X(1), 0))
|
| 2188 |
+
exp(-6)
|
| 2189 |
+
>>> P(Eq(X(4), 3), Eq(X(2), 3))
|
| 2190 |
+
exp(-6)
|
| 2191 |
+
>>> P(X(2) <= 3, X(1) > 1)
|
| 2192 |
+
5*exp(-3)
|
| 2193 |
+
|
| 2194 |
+
Merging two Poisson Processes
|
| 2195 |
+
|
| 2196 |
+
>>> Y = PoissonProcess("Y", lamda=4)
|
| 2197 |
+
>>> Z = X + Y
|
| 2198 |
+
>>> Z.lamda
|
| 2199 |
+
7
|
| 2200 |
+
|
| 2201 |
+
Splitting a Poisson Process into two independent Poisson Processes
|
| 2202 |
+
|
| 2203 |
+
>>> N, M = Z.split(l1=2, l2=5)
|
| 2204 |
+
>>> N.lamda, M.lamda
|
| 2205 |
+
(2, 5)
|
| 2206 |
+
|
| 2207 |
+
References
|
| 2208 |
+
==========
|
| 2209 |
+
|
| 2210 |
+
.. [1] https://www.probabilitycourse.com/chapter11/11_0_0_intro.php
|
| 2211 |
+
.. [2] https://en.wikipedia.org/wiki/Poisson_point_process
|
| 2212 |
+
|
| 2213 |
+
"""
|
| 2214 |
+
|
| 2215 |
+
def __new__(cls, sym, lamda):
|
| 2216 |
+
_value_check(lamda > 0, 'lamda should be a positive number.')
|
| 2217 |
+
sym = _symbol_converter(sym)
|
| 2218 |
+
lamda = _sympify(lamda)
|
| 2219 |
+
return Basic.__new__(cls, sym, lamda)
|
| 2220 |
+
|
| 2221 |
+
@property
|
| 2222 |
+
def lamda(self):
|
| 2223 |
+
return self.args[1]
|
| 2224 |
+
|
| 2225 |
+
@property
|
| 2226 |
+
def state_space(self):
|
| 2227 |
+
return S.Naturals0
|
| 2228 |
+
|
| 2229 |
+
def distribution(self, key):
|
| 2230 |
+
if isinstance(key, RandomIndexedSymbol):
|
| 2231 |
+
self._deprecation_warn_distribution()
|
| 2232 |
+
return PoissonDistribution(self.lamda*key.key)
|
| 2233 |
+
return PoissonDistribution(self.lamda*key)
|
| 2234 |
+
|
| 2235 |
+
def density(self, x):
|
| 2236 |
+
return (self.lamda*x.key)**x / factorial(x) * exp(-(self.lamda*x.key))
|
| 2237 |
+
|
| 2238 |
+
def simple_rv(self, rv):
|
| 2239 |
+
return Poisson(rv.name, lamda=self.lamda*rv.key)
|
| 2240 |
+
|
| 2241 |
+
def __add__(self, other):
|
| 2242 |
+
if not isinstance(other, PoissonProcess):
|
| 2243 |
+
raise ValueError("Only instances of Poisson Process can be merged")
|
| 2244 |
+
return PoissonProcess(Dummy(self.symbol.name + other.symbol.name),
|
| 2245 |
+
self.lamda + other.lamda)
|
| 2246 |
+
|
| 2247 |
+
def split(self, l1, l2):
|
| 2248 |
+
if _sympify(l1 + l2) != self.lamda:
|
| 2249 |
+
raise ValueError("Sum of l1 and l2 should be %s" % str(self.lamda))
|
| 2250 |
+
return PoissonProcess(Dummy("l1"), l1), PoissonProcess(Dummy("l2"), l2)
|
| 2251 |
+
|
| 2252 |
+
class WienerProcess(CountingProcess):
|
| 2253 |
+
"""
|
| 2254 |
+
The Wiener process is a real valued continuous-time stochastic process.
|
| 2255 |
+
In physics it is used to study Brownian motion and it is often also called
|
| 2256 |
+
Brownian motion due to its historical connection with physical process of the
|
| 2257 |
+
same name originally observed by Scottish botanist Robert Brown.
|
| 2258 |
+
|
| 2259 |
+
Parameters
|
| 2260 |
+
==========
|
| 2261 |
+
|
| 2262 |
+
sym : Symbol/str
|
| 2263 |
+
|
| 2264 |
+
Examples
|
| 2265 |
+
========
|
| 2266 |
+
|
| 2267 |
+
>>> from sympy.stats import WienerProcess, P, E
|
| 2268 |
+
>>> from sympy import symbols, Contains, Interval
|
| 2269 |
+
>>> X = WienerProcess("X")
|
| 2270 |
+
>>> X.state_space
|
| 2271 |
+
Reals
|
| 2272 |
+
>>> t1, t2 = symbols('t1 t2', positive=True)
|
| 2273 |
+
>>> P(X(t1) < 7).simplify()
|
| 2274 |
+
erf(7*sqrt(2)/(2*sqrt(t1)))/2 + 1/2
|
| 2275 |
+
>>> P((X(t1) > 2) | (X(t1) < 4), Contains(t1, Interval.Ropen(2, 4))).simplify()
|
| 2276 |
+
-erf(1)/2 + erf(2)/2 + 1
|
| 2277 |
+
>>> E(X(t1))
|
| 2278 |
+
0
|
| 2279 |
+
>>> E(X(t1) + 2*X(t2), Contains(t1, Interval.Lopen(0, 1))
|
| 2280 |
+
... & Contains(t2, Interval.Lopen(1, 2)))
|
| 2281 |
+
0
|
| 2282 |
+
|
| 2283 |
+
References
|
| 2284 |
+
==========
|
| 2285 |
+
|
| 2286 |
+
.. [1] https://www.probabilitycourse.com/chapter11/11_4_0_brownian_motion_wiener_process.php
|
| 2287 |
+
.. [2] https://en.wikipedia.org/wiki/Wiener_process
|
| 2288 |
+
|
| 2289 |
+
"""
|
| 2290 |
+
def __new__(cls, sym):
|
| 2291 |
+
sym = _symbol_converter(sym)
|
| 2292 |
+
return Basic.__new__(cls, sym)
|
| 2293 |
+
|
| 2294 |
+
@property
|
| 2295 |
+
def state_space(self):
|
| 2296 |
+
return S.Reals
|
| 2297 |
+
|
| 2298 |
+
def distribution(self, key):
|
| 2299 |
+
if isinstance(key, RandomIndexedSymbol):
|
| 2300 |
+
self._deprecation_warn_distribution()
|
| 2301 |
+
return NormalDistribution(0, sqrt(key.key))
|
| 2302 |
+
return NormalDistribution(0, sqrt(key))
|
| 2303 |
+
|
| 2304 |
+
def density(self, x):
|
| 2305 |
+
return exp(-x**2/(2*x.key)) / (sqrt(2*pi)*sqrt(x.key))
|
| 2306 |
+
|
| 2307 |
+
def simple_rv(self, rv):
|
| 2308 |
+
return Normal(rv.name, 0, sqrt(rv.key))
|
| 2309 |
+
|
| 2310 |
+
|
| 2311 |
+
class GammaProcess(CountingProcess):
|
| 2312 |
+
r"""
|
| 2313 |
+
A Gamma process is a random process with independent gamma distributed
|
| 2314 |
+
increments. It is a pure-jump increasing Levy process.
|
| 2315 |
+
|
| 2316 |
+
Parameters
|
| 2317 |
+
==========
|
| 2318 |
+
|
| 2319 |
+
sym : Symbol/str
|
| 2320 |
+
lamda : Positive number
|
| 2321 |
+
Jump size of the process, ``lamda > 0``
|
| 2322 |
+
gamma : Positive number
|
| 2323 |
+
Rate of jump arrivals, `\gamma > 0`
|
| 2324 |
+
|
| 2325 |
+
Examples
|
| 2326 |
+
========
|
| 2327 |
+
|
| 2328 |
+
>>> from sympy.stats import GammaProcess, E, P, variance
|
| 2329 |
+
>>> from sympy import symbols, Contains, Interval, Not
|
| 2330 |
+
>>> t, d, x, l, g = symbols('t d x l g', positive=True)
|
| 2331 |
+
>>> X = GammaProcess("X", l, g)
|
| 2332 |
+
>>> E(X(t))
|
| 2333 |
+
g*t/l
|
| 2334 |
+
>>> variance(X(t)).simplify()
|
| 2335 |
+
g*t/l**2
|
| 2336 |
+
>>> X = GammaProcess('X', 1, 2)
|
| 2337 |
+
>>> P(X(t) < 1).simplify()
|
| 2338 |
+
lowergamma(2*t, 1)/gamma(2*t)
|
| 2339 |
+
>>> P(Not((X(t) < 5) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) &
|
| 2340 |
+
... Contains(d, Interval.Lopen(7, 8))).simplify()
|
| 2341 |
+
-4*exp(-3) + 472*exp(-8)/3 + 1
|
| 2342 |
+
>>> E(X(2) + x*E(X(5)))
|
| 2343 |
+
10*x + 4
|
| 2344 |
+
|
| 2345 |
+
References
|
| 2346 |
+
==========
|
| 2347 |
+
|
| 2348 |
+
.. [1] https://en.wikipedia.org/wiki/Gamma_process
|
| 2349 |
+
|
| 2350 |
+
"""
|
| 2351 |
+
def __new__(cls, sym, lamda, gamma):
|
| 2352 |
+
_value_check(lamda > 0, 'lamda should be a positive number')
|
| 2353 |
+
_value_check(gamma > 0, 'gamma should be a positive number')
|
| 2354 |
+
sym = _symbol_converter(sym)
|
| 2355 |
+
gamma = _sympify(gamma)
|
| 2356 |
+
lamda = _sympify(lamda)
|
| 2357 |
+
return Basic.__new__(cls, sym, lamda, gamma)
|
| 2358 |
+
|
| 2359 |
+
@property
|
| 2360 |
+
def lamda(self):
|
| 2361 |
+
return self.args[1]
|
| 2362 |
+
|
| 2363 |
+
@property
|
| 2364 |
+
def gamma(self):
|
| 2365 |
+
return self.args[2]
|
| 2366 |
+
|
| 2367 |
+
@property
|
| 2368 |
+
def state_space(self):
|
| 2369 |
+
return _set_converter(Interval(0, oo))
|
| 2370 |
+
|
| 2371 |
+
def distribution(self, key):
|
| 2372 |
+
if isinstance(key, RandomIndexedSymbol):
|
| 2373 |
+
self._deprecation_warn_distribution()
|
| 2374 |
+
return GammaDistribution(self.gamma*key.key, 1/self.lamda)
|
| 2375 |
+
return GammaDistribution(self.gamma*key, 1/self.lamda)
|
| 2376 |
+
|
| 2377 |
+
def density(self, x):
|
| 2378 |
+
k = self.gamma*x.key
|
| 2379 |
+
theta = 1/self.lamda
|
| 2380 |
+
return x**(k - 1) * exp(-x/theta) / (gamma(k)*theta**k)
|
| 2381 |
+
|
| 2382 |
+
def simple_rv(self, rv):
|
| 2383 |
+
return Gamma(rv.name, self.gamma*rv.key, 1/self.lamda)
|
hug/lib/python3.12/site-packages/sympy/stats/symbolic_multivariate_probability.py
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import itertools
|
| 2 |
+
|
| 3 |
+
from sympy.core.add import Add
|
| 4 |
+
from sympy.core.expr import Expr
|
| 5 |
+
from sympy.core.function import expand as _expand
|
| 6 |
+
from sympy.core.mul import Mul
|
| 7 |
+
from sympy.core.singleton import S
|
| 8 |
+
from sympy.matrices.exceptions import ShapeError
|
| 9 |
+
from sympy.matrices.expressions.matexpr import MatrixExpr
|
| 10 |
+
from sympy.matrices.expressions.matmul import MatMul
|
| 11 |
+
from sympy.matrices.expressions.special import ZeroMatrix
|
| 12 |
+
from sympy.stats.rv import RandomSymbol, is_random
|
| 13 |
+
from sympy.core.sympify import _sympify
|
| 14 |
+
from sympy.stats.symbolic_probability import Variance, Covariance, Expectation
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class ExpectationMatrix(Expectation, MatrixExpr):
|
| 18 |
+
"""
|
| 19 |
+
Expectation of a random matrix expression.
|
| 20 |
+
|
| 21 |
+
Examples
|
| 22 |
+
========
|
| 23 |
+
|
| 24 |
+
>>> from sympy.stats import ExpectationMatrix, Normal
|
| 25 |
+
>>> from sympy.stats.rv import RandomMatrixSymbol
|
| 26 |
+
>>> from sympy import symbols, MatrixSymbol, Matrix
|
| 27 |
+
>>> k = symbols("k")
|
| 28 |
+
>>> A, B = MatrixSymbol("A", k, k), MatrixSymbol("B", k, k)
|
| 29 |
+
>>> X, Y = RandomMatrixSymbol("X", k, 1), RandomMatrixSymbol("Y", k, 1)
|
| 30 |
+
>>> ExpectationMatrix(X)
|
| 31 |
+
ExpectationMatrix(X)
|
| 32 |
+
>>> ExpectationMatrix(A*X).shape
|
| 33 |
+
(k, 1)
|
| 34 |
+
|
| 35 |
+
To expand the expectation in its expression, use ``expand()``:
|
| 36 |
+
|
| 37 |
+
>>> ExpectationMatrix(A*X + B*Y).expand()
|
| 38 |
+
A*ExpectationMatrix(X) + B*ExpectationMatrix(Y)
|
| 39 |
+
>>> ExpectationMatrix((X + Y)*(X - Y).T).expand()
|
| 40 |
+
ExpectationMatrix(X*X.T) - ExpectationMatrix(X*Y.T) + ExpectationMatrix(Y*X.T) - ExpectationMatrix(Y*Y.T)
|
| 41 |
+
|
| 42 |
+
To evaluate the ``ExpectationMatrix``, use ``doit()``:
|
| 43 |
+
|
| 44 |
+
>>> N11, N12 = Normal('N11', 11, 1), Normal('N12', 12, 1)
|
| 45 |
+
>>> N21, N22 = Normal('N21', 21, 1), Normal('N22', 22, 1)
|
| 46 |
+
>>> M11, M12 = Normal('M11', 1, 1), Normal('M12', 2, 1)
|
| 47 |
+
>>> M21, M22 = Normal('M21', 3, 1), Normal('M22', 4, 1)
|
| 48 |
+
>>> x1 = Matrix([[N11, N12], [N21, N22]])
|
| 49 |
+
>>> x2 = Matrix([[M11, M12], [M21, M22]])
|
| 50 |
+
>>> ExpectationMatrix(x1 + x2).doit()
|
| 51 |
+
Matrix([
|
| 52 |
+
[12, 14],
|
| 53 |
+
[24, 26]])
|
| 54 |
+
|
| 55 |
+
"""
|
| 56 |
+
def __new__(cls, expr, condition=None):
|
| 57 |
+
expr = _sympify(expr)
|
| 58 |
+
if condition is None:
|
| 59 |
+
if not is_random(expr):
|
| 60 |
+
return expr
|
| 61 |
+
obj = Expr.__new__(cls, expr)
|
| 62 |
+
else:
|
| 63 |
+
condition = _sympify(condition)
|
| 64 |
+
obj = Expr.__new__(cls, expr, condition)
|
| 65 |
+
|
| 66 |
+
obj._shape = expr.shape
|
| 67 |
+
obj._condition = condition
|
| 68 |
+
return obj
|
| 69 |
+
|
| 70 |
+
@property
|
| 71 |
+
def shape(self):
|
| 72 |
+
return self._shape
|
| 73 |
+
|
| 74 |
+
def expand(self, **hints):
|
| 75 |
+
expr = self.args[0]
|
| 76 |
+
condition = self._condition
|
| 77 |
+
if not is_random(expr):
|
| 78 |
+
return expr
|
| 79 |
+
|
| 80 |
+
if isinstance(expr, Add):
|
| 81 |
+
return Add.fromiter(Expectation(a, condition=condition).expand()
|
| 82 |
+
for a in expr.args)
|
| 83 |
+
|
| 84 |
+
expand_expr = _expand(expr)
|
| 85 |
+
if isinstance(expand_expr, Add):
|
| 86 |
+
return Add.fromiter(Expectation(a, condition=condition).expand()
|
| 87 |
+
for a in expand_expr.args)
|
| 88 |
+
|
| 89 |
+
elif isinstance(expr, (Mul, MatMul)):
|
| 90 |
+
rv = []
|
| 91 |
+
nonrv = []
|
| 92 |
+
postnon = []
|
| 93 |
+
|
| 94 |
+
for a in expr.args:
|
| 95 |
+
if is_random(a):
|
| 96 |
+
if rv:
|
| 97 |
+
rv.extend(postnon)
|
| 98 |
+
else:
|
| 99 |
+
nonrv.extend(postnon)
|
| 100 |
+
postnon = []
|
| 101 |
+
rv.append(a)
|
| 102 |
+
elif a.is_Matrix:
|
| 103 |
+
postnon.append(a)
|
| 104 |
+
else:
|
| 105 |
+
nonrv.append(a)
|
| 106 |
+
|
| 107 |
+
# In order to avoid infinite-looping (MatMul may call .doit() again),
|
| 108 |
+
# do not rebuild
|
| 109 |
+
if len(nonrv) == 0:
|
| 110 |
+
return self
|
| 111 |
+
return Mul.fromiter(nonrv)*Expectation(Mul.fromiter(rv),
|
| 112 |
+
condition=condition)*Mul.fromiter(postnon)
|
| 113 |
+
|
| 114 |
+
return self
|
| 115 |
+
|
| 116 |
+
class VarianceMatrix(Variance, MatrixExpr):
|
| 117 |
+
"""
|
| 118 |
+
Variance of a random matrix probability expression. Also known as
|
| 119 |
+
Covariance matrix, auto-covariance matrix, dispersion matrix,
|
| 120 |
+
or variance-covariance matrix.
|
| 121 |
+
|
| 122 |
+
Examples
|
| 123 |
+
========
|
| 124 |
+
|
| 125 |
+
>>> from sympy.stats import VarianceMatrix
|
| 126 |
+
>>> from sympy.stats.rv import RandomMatrixSymbol
|
| 127 |
+
>>> from sympy import symbols, MatrixSymbol
|
| 128 |
+
>>> k = symbols("k")
|
| 129 |
+
>>> A, B = MatrixSymbol("A", k, k), MatrixSymbol("B", k, k)
|
| 130 |
+
>>> X, Y = RandomMatrixSymbol("X", k, 1), RandomMatrixSymbol("Y", k, 1)
|
| 131 |
+
>>> VarianceMatrix(X)
|
| 132 |
+
VarianceMatrix(X)
|
| 133 |
+
>>> VarianceMatrix(X).shape
|
| 134 |
+
(k, k)
|
| 135 |
+
|
| 136 |
+
To expand the variance in its expression, use ``expand()``:
|
| 137 |
+
|
| 138 |
+
>>> VarianceMatrix(A*X).expand()
|
| 139 |
+
A*VarianceMatrix(X)*A.T
|
| 140 |
+
>>> VarianceMatrix(A*X + B*Y).expand()
|
| 141 |
+
2*A*CrossCovarianceMatrix(X, Y)*B.T + A*VarianceMatrix(X)*A.T + B*VarianceMatrix(Y)*B.T
|
| 142 |
+
"""
|
| 143 |
+
def __new__(cls, arg, condition=None):
|
| 144 |
+
arg = _sympify(arg)
|
| 145 |
+
|
| 146 |
+
if 1 not in arg.shape:
|
| 147 |
+
raise ShapeError("Expression is not a vector")
|
| 148 |
+
|
| 149 |
+
shape = (arg.shape[0], arg.shape[0]) if arg.shape[1] == 1 else (arg.shape[1], arg.shape[1])
|
| 150 |
+
|
| 151 |
+
if condition:
|
| 152 |
+
obj = Expr.__new__(cls, arg, condition)
|
| 153 |
+
else:
|
| 154 |
+
obj = Expr.__new__(cls, arg)
|
| 155 |
+
|
| 156 |
+
obj._shape = shape
|
| 157 |
+
obj._condition = condition
|
| 158 |
+
return obj
|
| 159 |
+
|
| 160 |
+
@property
|
| 161 |
+
def shape(self):
|
| 162 |
+
return self._shape
|
| 163 |
+
|
| 164 |
+
def expand(self, **hints):
|
| 165 |
+
arg = self.args[0]
|
| 166 |
+
condition = self._condition
|
| 167 |
+
|
| 168 |
+
if not is_random(arg):
|
| 169 |
+
return ZeroMatrix(*self.shape)
|
| 170 |
+
|
| 171 |
+
if isinstance(arg, RandomSymbol):
|
| 172 |
+
return self
|
| 173 |
+
elif isinstance(arg, Add):
|
| 174 |
+
rv = []
|
| 175 |
+
for a in arg.args:
|
| 176 |
+
if is_random(a):
|
| 177 |
+
rv.append(a)
|
| 178 |
+
variances = Add(*(Variance(xv, condition).expand() for xv in rv))
|
| 179 |
+
map_to_covar = lambda x: 2*Covariance(*x, condition=condition).expand()
|
| 180 |
+
covariances = Add(*map(map_to_covar, itertools.combinations(rv, 2)))
|
| 181 |
+
return variances + covariances
|
| 182 |
+
elif isinstance(arg, (Mul, MatMul)):
|
| 183 |
+
nonrv = []
|
| 184 |
+
rv = []
|
| 185 |
+
for a in arg.args:
|
| 186 |
+
if is_random(a):
|
| 187 |
+
rv.append(a)
|
| 188 |
+
else:
|
| 189 |
+
nonrv.append(a)
|
| 190 |
+
if len(rv) == 0:
|
| 191 |
+
return ZeroMatrix(*self.shape)
|
| 192 |
+
# Avoid possible infinite loops with MatMul:
|
| 193 |
+
if len(nonrv) == 0:
|
| 194 |
+
return self
|
| 195 |
+
# Variance of many multiple matrix products is not implemented:
|
| 196 |
+
if len(rv) > 1:
|
| 197 |
+
return self
|
| 198 |
+
return Mul.fromiter(nonrv)*Variance(Mul.fromiter(rv),
|
| 199 |
+
condition)*(Mul.fromiter(nonrv)).transpose()
|
| 200 |
+
|
| 201 |
+
# this expression contains a RandomSymbol somehow:
|
| 202 |
+
return self
|
| 203 |
+
|
| 204 |
+
class CrossCovarianceMatrix(Covariance, MatrixExpr):
|
| 205 |
+
"""
|
| 206 |
+
Covariance of a random matrix probability expression.
|
| 207 |
+
|
| 208 |
+
Examples
|
| 209 |
+
========
|
| 210 |
+
|
| 211 |
+
>>> from sympy.stats import CrossCovarianceMatrix
|
| 212 |
+
>>> from sympy.stats.rv import RandomMatrixSymbol
|
| 213 |
+
>>> from sympy import symbols, MatrixSymbol
|
| 214 |
+
>>> k = symbols("k")
|
| 215 |
+
>>> A, B = MatrixSymbol("A", k, k), MatrixSymbol("B", k, k)
|
| 216 |
+
>>> C, D = MatrixSymbol("C", k, k), MatrixSymbol("D", k, k)
|
| 217 |
+
>>> X, Y = RandomMatrixSymbol("X", k, 1), RandomMatrixSymbol("Y", k, 1)
|
| 218 |
+
>>> Z, W = RandomMatrixSymbol("Z", k, 1), RandomMatrixSymbol("W", k, 1)
|
| 219 |
+
>>> CrossCovarianceMatrix(X, Y)
|
| 220 |
+
CrossCovarianceMatrix(X, Y)
|
| 221 |
+
>>> CrossCovarianceMatrix(X, Y).shape
|
| 222 |
+
(k, k)
|
| 223 |
+
|
| 224 |
+
To expand the covariance in its expression, use ``expand()``:
|
| 225 |
+
|
| 226 |
+
>>> CrossCovarianceMatrix(X + Y, Z).expand()
|
| 227 |
+
CrossCovarianceMatrix(X, Z) + CrossCovarianceMatrix(Y, Z)
|
| 228 |
+
>>> CrossCovarianceMatrix(A*X, Y).expand()
|
| 229 |
+
A*CrossCovarianceMatrix(X, Y)
|
| 230 |
+
>>> CrossCovarianceMatrix(A*X, B.T*Y).expand()
|
| 231 |
+
A*CrossCovarianceMatrix(X, Y)*B
|
| 232 |
+
>>> CrossCovarianceMatrix(A*X + B*Y, C.T*Z + D.T*W).expand()
|
| 233 |
+
A*CrossCovarianceMatrix(X, W)*D + A*CrossCovarianceMatrix(X, Z)*C + B*CrossCovarianceMatrix(Y, W)*D + B*CrossCovarianceMatrix(Y, Z)*C
|
| 234 |
+
|
| 235 |
+
"""
|
| 236 |
+
def __new__(cls, arg1, arg2, condition=None):
|
| 237 |
+
arg1 = _sympify(arg1)
|
| 238 |
+
arg2 = _sympify(arg2)
|
| 239 |
+
|
| 240 |
+
if (1 not in arg1.shape) or (1 not in arg2.shape) or (arg1.shape[1] != arg2.shape[1]):
|
| 241 |
+
raise ShapeError("Expression is not a vector")
|
| 242 |
+
|
| 243 |
+
shape = (arg1.shape[0], arg2.shape[0]) if arg1.shape[1] == 1 and arg2.shape[1] == 1 \
|
| 244 |
+
else (1, 1)
|
| 245 |
+
|
| 246 |
+
if condition:
|
| 247 |
+
obj = Expr.__new__(cls, arg1, arg2, condition)
|
| 248 |
+
else:
|
| 249 |
+
obj = Expr.__new__(cls, arg1, arg2)
|
| 250 |
+
|
| 251 |
+
obj._shape = shape
|
| 252 |
+
obj._condition = condition
|
| 253 |
+
return obj
|
| 254 |
+
|
| 255 |
+
@property
|
| 256 |
+
def shape(self):
|
| 257 |
+
return self._shape
|
| 258 |
+
|
| 259 |
+
def expand(self, **hints):
|
| 260 |
+
arg1 = self.args[0]
|
| 261 |
+
arg2 = self.args[1]
|
| 262 |
+
condition = self._condition
|
| 263 |
+
|
| 264 |
+
if arg1 == arg2:
|
| 265 |
+
return VarianceMatrix(arg1, condition).expand()
|
| 266 |
+
|
| 267 |
+
if not is_random(arg1) or not is_random(arg2):
|
| 268 |
+
return ZeroMatrix(*self.shape)
|
| 269 |
+
|
| 270 |
+
if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol):
|
| 271 |
+
return CrossCovarianceMatrix(arg1, arg2, condition)
|
| 272 |
+
|
| 273 |
+
coeff_rv_list1 = self._expand_single_argument(arg1.expand())
|
| 274 |
+
coeff_rv_list2 = self._expand_single_argument(arg2.expand())
|
| 275 |
+
|
| 276 |
+
addends = [a*CrossCovarianceMatrix(r1, r2, condition=condition)*b.transpose()
|
| 277 |
+
for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2]
|
| 278 |
+
return Add.fromiter(addends)
|
| 279 |
+
|
| 280 |
+
@classmethod
|
| 281 |
+
def _expand_single_argument(cls, expr):
|
| 282 |
+
# return (coefficient, random_symbol) pairs:
|
| 283 |
+
if isinstance(expr, RandomSymbol):
|
| 284 |
+
return [(S.One, expr)]
|
| 285 |
+
elif isinstance(expr, Add):
|
| 286 |
+
outval = []
|
| 287 |
+
for a in expr.args:
|
| 288 |
+
if isinstance(a, (Mul, MatMul)):
|
| 289 |
+
outval.append(cls._get_mul_nonrv_rv_tuple(a))
|
| 290 |
+
elif is_random(a):
|
| 291 |
+
outval.append((S.One, a))
|
| 292 |
+
|
| 293 |
+
return outval
|
| 294 |
+
elif isinstance(expr, (Mul, MatMul)):
|
| 295 |
+
return [cls._get_mul_nonrv_rv_tuple(expr)]
|
| 296 |
+
elif is_random(expr):
|
| 297 |
+
return [(S.One, expr)]
|
| 298 |
+
|
| 299 |
+
@classmethod
|
| 300 |
+
def _get_mul_nonrv_rv_tuple(cls, m):
|
| 301 |
+
rv = []
|
| 302 |
+
nonrv = []
|
| 303 |
+
for a in m.args:
|
| 304 |
+
if is_random(a):
|
| 305 |
+
rv.append(a)
|
| 306 |
+
else:
|
| 307 |
+
nonrv.append(a)
|
| 308 |
+
return (Mul.fromiter(nonrv), Mul.fromiter(rv))
|
hug/lib/python3.12/site-packages/sympy/stats/symbolic_probability.py
ADDED
|
@@ -0,0 +1,698 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import itertools
|
| 2 |
+
from sympy.concrete.summations import Sum
|
| 3 |
+
from sympy.core.add import Add
|
| 4 |
+
from sympy.core.expr import Expr
|
| 5 |
+
from sympy.core.function import expand as _expand
|
| 6 |
+
from sympy.core.mul import Mul
|
| 7 |
+
from sympy.core.relational import Eq
|
| 8 |
+
from sympy.core.singleton import S
|
| 9 |
+
from sympy.core.symbol import Symbol
|
| 10 |
+
from sympy.integrals.integrals import Integral
|
| 11 |
+
from sympy.logic.boolalg import Not
|
| 12 |
+
from sympy.core.parameters import global_parameters
|
| 13 |
+
from sympy.core.sorting import default_sort_key
|
| 14 |
+
from sympy.core.sympify import _sympify
|
| 15 |
+
from sympy.core.relational import Relational
|
| 16 |
+
from sympy.logic.boolalg import Boolean
|
| 17 |
+
from sympy.stats import variance, covariance
|
| 18 |
+
from sympy.stats.rv import (RandomSymbol, pspace, dependent,
|
| 19 |
+
given, sampling_E, RandomIndexedSymbol, is_random,
|
| 20 |
+
PSpace, sampling_P, random_symbols)
|
| 21 |
+
|
| 22 |
+
__all__ = ['Probability', 'Expectation', 'Variance', 'Covariance']
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@is_random.register(Expr)
|
| 26 |
+
def _(x):
|
| 27 |
+
atoms = x.free_symbols
|
| 28 |
+
if len(atoms) == 1 and next(iter(atoms)) == x:
|
| 29 |
+
return False
|
| 30 |
+
return any(is_random(i) for i in atoms)
|
| 31 |
+
|
| 32 |
+
@is_random.register(RandomSymbol) # type: ignore
|
| 33 |
+
def _(x):
|
| 34 |
+
return True
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class Probability(Expr):
|
| 38 |
+
"""
|
| 39 |
+
Symbolic expression for the probability.
|
| 40 |
+
|
| 41 |
+
Examples
|
| 42 |
+
========
|
| 43 |
+
|
| 44 |
+
>>> from sympy.stats import Probability, Normal
|
| 45 |
+
>>> from sympy import Integral
|
| 46 |
+
>>> X = Normal("X", 0, 1)
|
| 47 |
+
>>> prob = Probability(X > 1)
|
| 48 |
+
>>> prob
|
| 49 |
+
Probability(X > 1)
|
| 50 |
+
|
| 51 |
+
Integral representation:
|
| 52 |
+
|
| 53 |
+
>>> prob.rewrite(Integral)
|
| 54 |
+
Integral(sqrt(2)*exp(-_z**2/2)/(2*sqrt(pi)), (_z, 1, oo))
|
| 55 |
+
|
| 56 |
+
Evaluation of the integral:
|
| 57 |
+
|
| 58 |
+
>>> prob.evaluate_integral()
|
| 59 |
+
sqrt(2)*(-sqrt(2)*sqrt(pi)*erf(sqrt(2)/2) + sqrt(2)*sqrt(pi))/(4*sqrt(pi))
|
| 60 |
+
"""
|
| 61 |
+
|
| 62 |
+
is_commutative = True
|
| 63 |
+
|
| 64 |
+
def __new__(cls, prob, condition=None, **kwargs):
|
| 65 |
+
prob = _sympify(prob)
|
| 66 |
+
if condition is None:
|
| 67 |
+
obj = Expr.__new__(cls, prob)
|
| 68 |
+
else:
|
| 69 |
+
condition = _sympify(condition)
|
| 70 |
+
obj = Expr.__new__(cls, prob, condition)
|
| 71 |
+
obj._condition = condition
|
| 72 |
+
return obj
|
| 73 |
+
|
| 74 |
+
def doit(self, **hints):
|
| 75 |
+
condition = self.args[0]
|
| 76 |
+
given_condition = self._condition
|
| 77 |
+
numsamples = hints.get('numsamples', False)
|
| 78 |
+
evaluate = hints.get('evaluate', True)
|
| 79 |
+
|
| 80 |
+
if isinstance(condition, Not):
|
| 81 |
+
return S.One - self.func(condition.args[0], given_condition,
|
| 82 |
+
evaluate=evaluate).doit(**hints)
|
| 83 |
+
|
| 84 |
+
if condition.has(RandomIndexedSymbol):
|
| 85 |
+
return pspace(condition).probability(condition, given_condition,
|
| 86 |
+
evaluate=evaluate)
|
| 87 |
+
|
| 88 |
+
if isinstance(given_condition, RandomSymbol):
|
| 89 |
+
condrv = random_symbols(condition)
|
| 90 |
+
if len(condrv) == 1 and condrv[0] == given_condition:
|
| 91 |
+
from sympy.stats.frv_types import BernoulliDistribution
|
| 92 |
+
return BernoulliDistribution(self.func(condition).doit(**hints), 0, 1)
|
| 93 |
+
if any(dependent(rv, given_condition) for rv in condrv):
|
| 94 |
+
return Probability(condition, given_condition)
|
| 95 |
+
else:
|
| 96 |
+
return Probability(condition).doit()
|
| 97 |
+
|
| 98 |
+
if given_condition is not None and \
|
| 99 |
+
not isinstance(given_condition, (Relational, Boolean)):
|
| 100 |
+
raise ValueError("%s is not a relational or combination of relationals"
|
| 101 |
+
% (given_condition))
|
| 102 |
+
|
| 103 |
+
if given_condition == False or condition is S.false:
|
| 104 |
+
return S.Zero
|
| 105 |
+
if not isinstance(condition, (Relational, Boolean)):
|
| 106 |
+
raise ValueError("%s is not a relational or combination of relationals"
|
| 107 |
+
% (condition))
|
| 108 |
+
if condition is S.true:
|
| 109 |
+
return S.One
|
| 110 |
+
|
| 111 |
+
if numsamples:
|
| 112 |
+
return sampling_P(condition, given_condition, numsamples=numsamples)
|
| 113 |
+
if given_condition is not None: # If there is a condition
|
| 114 |
+
# Recompute on new conditional expr
|
| 115 |
+
return Probability(given(condition, given_condition)).doit()
|
| 116 |
+
|
| 117 |
+
# Otherwise pass work off to the ProbabilitySpace
|
| 118 |
+
if pspace(condition) == PSpace():
|
| 119 |
+
return Probability(condition, given_condition)
|
| 120 |
+
|
| 121 |
+
result = pspace(condition).probability(condition)
|
| 122 |
+
if hasattr(result, 'doit') and evaluate:
|
| 123 |
+
return result.doit()
|
| 124 |
+
else:
|
| 125 |
+
return result
|
| 126 |
+
|
| 127 |
+
def _eval_rewrite_as_Integral(self, arg, condition=None, **kwargs):
|
| 128 |
+
return self.func(arg, condition=condition).doit(evaluate=False)
|
| 129 |
+
|
| 130 |
+
_eval_rewrite_as_Sum = _eval_rewrite_as_Integral
|
| 131 |
+
|
| 132 |
+
def evaluate_integral(self):
|
| 133 |
+
return self.rewrite(Integral).doit()
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
class Expectation(Expr):
|
| 137 |
+
"""
|
| 138 |
+
Symbolic expression for the expectation.
|
| 139 |
+
|
| 140 |
+
Examples
|
| 141 |
+
========
|
| 142 |
+
|
| 143 |
+
>>> from sympy.stats import Expectation, Normal, Probability, Poisson
|
| 144 |
+
>>> from sympy import symbols, Integral, Sum
|
| 145 |
+
>>> mu = symbols("mu")
|
| 146 |
+
>>> sigma = symbols("sigma", positive=True)
|
| 147 |
+
>>> X = Normal("X", mu, sigma)
|
| 148 |
+
>>> Expectation(X)
|
| 149 |
+
Expectation(X)
|
| 150 |
+
>>> Expectation(X).evaluate_integral().simplify()
|
| 151 |
+
mu
|
| 152 |
+
|
| 153 |
+
To get the integral expression of the expectation:
|
| 154 |
+
|
| 155 |
+
>>> Expectation(X).rewrite(Integral)
|
| 156 |
+
Integral(sqrt(2)*X*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo))
|
| 157 |
+
|
| 158 |
+
The same integral expression, in more abstract terms:
|
| 159 |
+
|
| 160 |
+
>>> Expectation(X).rewrite(Probability)
|
| 161 |
+
Integral(x*Probability(Eq(X, x)), (x, -oo, oo))
|
| 162 |
+
|
| 163 |
+
To get the Summation expression of the expectation for discrete random variables:
|
| 164 |
+
|
| 165 |
+
>>> lamda = symbols('lamda', positive=True)
|
| 166 |
+
>>> Z = Poisson('Z', lamda)
|
| 167 |
+
>>> Expectation(Z).rewrite(Sum)
|
| 168 |
+
Sum(Z*lamda**Z*exp(-lamda)/factorial(Z), (Z, 0, oo))
|
| 169 |
+
|
| 170 |
+
This class is aware of some properties of the expectation:
|
| 171 |
+
|
| 172 |
+
>>> from sympy.abc import a
|
| 173 |
+
>>> Expectation(a*X)
|
| 174 |
+
Expectation(a*X)
|
| 175 |
+
>>> Y = Normal("Y", 1, 2)
|
| 176 |
+
>>> Expectation(X + Y)
|
| 177 |
+
Expectation(X + Y)
|
| 178 |
+
|
| 179 |
+
To expand the ``Expectation`` into its expression, use ``expand()``:
|
| 180 |
+
|
| 181 |
+
>>> Expectation(X + Y).expand()
|
| 182 |
+
Expectation(X) + Expectation(Y)
|
| 183 |
+
>>> Expectation(a*X + Y).expand()
|
| 184 |
+
a*Expectation(X) + Expectation(Y)
|
| 185 |
+
>>> Expectation(a*X + Y)
|
| 186 |
+
Expectation(a*X + Y)
|
| 187 |
+
>>> Expectation((X + Y)*(X - Y)).expand()
|
| 188 |
+
Expectation(X**2) - Expectation(Y**2)
|
| 189 |
+
|
| 190 |
+
To evaluate the ``Expectation``, use ``doit()``:
|
| 191 |
+
|
| 192 |
+
>>> Expectation(X + Y).doit()
|
| 193 |
+
mu + 1
|
| 194 |
+
>>> Expectation(X + Expectation(Y + Expectation(2*X))).doit()
|
| 195 |
+
3*mu + 1
|
| 196 |
+
|
| 197 |
+
To prevent evaluating nested ``Expectation``, use ``doit(deep=False)``
|
| 198 |
+
|
| 199 |
+
>>> Expectation(X + Expectation(Y)).doit(deep=False)
|
| 200 |
+
mu + Expectation(Expectation(Y))
|
| 201 |
+
>>> Expectation(X + Expectation(Y + Expectation(2*X))).doit(deep=False)
|
| 202 |
+
mu + Expectation(Expectation(Expectation(2*X) + Y))
|
| 203 |
+
|
| 204 |
+
"""
|
| 205 |
+
|
| 206 |
+
def __new__(cls, expr, condition=None, **kwargs):
|
| 207 |
+
expr = _sympify(expr)
|
| 208 |
+
if expr.is_Matrix:
|
| 209 |
+
from sympy.stats.symbolic_multivariate_probability import ExpectationMatrix
|
| 210 |
+
return ExpectationMatrix(expr, condition)
|
| 211 |
+
if condition is None:
|
| 212 |
+
if not is_random(expr):
|
| 213 |
+
return expr
|
| 214 |
+
obj = Expr.__new__(cls, expr)
|
| 215 |
+
else:
|
| 216 |
+
condition = _sympify(condition)
|
| 217 |
+
obj = Expr.__new__(cls, expr, condition)
|
| 218 |
+
obj._condition = condition
|
| 219 |
+
return obj
|
| 220 |
+
|
| 221 |
+
def _eval_is_commutative(self):
|
| 222 |
+
return(self.args[0].is_commutative)
|
| 223 |
+
|
| 224 |
+
def expand(self, **hints):
|
| 225 |
+
expr = self.args[0]
|
| 226 |
+
condition = self._condition
|
| 227 |
+
|
| 228 |
+
if not is_random(expr):
|
| 229 |
+
return expr
|
| 230 |
+
|
| 231 |
+
if isinstance(expr, Add):
|
| 232 |
+
return Add.fromiter(Expectation(a, condition=condition).expand()
|
| 233 |
+
for a in expr.args)
|
| 234 |
+
|
| 235 |
+
expand_expr = _expand(expr)
|
| 236 |
+
if isinstance(expand_expr, Add):
|
| 237 |
+
return Add.fromiter(Expectation(a, condition=condition).expand()
|
| 238 |
+
for a in expand_expr.args)
|
| 239 |
+
|
| 240 |
+
elif isinstance(expr, Mul):
|
| 241 |
+
rv = []
|
| 242 |
+
nonrv = []
|
| 243 |
+
for a in expr.args:
|
| 244 |
+
if is_random(a):
|
| 245 |
+
rv.append(a)
|
| 246 |
+
else:
|
| 247 |
+
nonrv.append(a)
|
| 248 |
+
return Mul.fromiter(nonrv)*Expectation(Mul.fromiter(rv), condition=condition)
|
| 249 |
+
|
| 250 |
+
return self
|
| 251 |
+
|
| 252 |
+
def doit(self, **hints):
|
| 253 |
+
deep = hints.get('deep', True)
|
| 254 |
+
condition = self._condition
|
| 255 |
+
expr = self.args[0]
|
| 256 |
+
numsamples = hints.get('numsamples', False)
|
| 257 |
+
evaluate = hints.get('evaluate', True)
|
| 258 |
+
|
| 259 |
+
if deep:
|
| 260 |
+
expr = expr.doit(**hints)
|
| 261 |
+
|
| 262 |
+
if not is_random(expr) or isinstance(expr, Expectation): # expr isn't random?
|
| 263 |
+
return expr
|
| 264 |
+
if numsamples: # Computing by monte carlo sampling?
|
| 265 |
+
evalf = hints.get('evalf', True)
|
| 266 |
+
return sampling_E(expr, condition, numsamples=numsamples, evalf=evalf)
|
| 267 |
+
|
| 268 |
+
if expr.has(RandomIndexedSymbol):
|
| 269 |
+
return pspace(expr).compute_expectation(expr, condition)
|
| 270 |
+
|
| 271 |
+
# Create new expr and recompute E
|
| 272 |
+
if condition is not None: # If there is a condition
|
| 273 |
+
return self.func(given(expr, condition)).doit(**hints)
|
| 274 |
+
|
| 275 |
+
# A few known statements for efficiency
|
| 276 |
+
|
| 277 |
+
if expr.is_Add: # We know that E is Linear
|
| 278 |
+
return Add(*[self.func(arg, condition).doit(**hints)
|
| 279 |
+
if not isinstance(arg, Expectation) else self.func(arg, condition)
|
| 280 |
+
for arg in expr.args])
|
| 281 |
+
if expr.is_Mul:
|
| 282 |
+
if expr.atoms(Expectation):
|
| 283 |
+
return expr
|
| 284 |
+
|
| 285 |
+
if pspace(expr) == PSpace():
|
| 286 |
+
return self.func(expr)
|
| 287 |
+
# Otherwise case is simple, pass work off to the ProbabilitySpace
|
| 288 |
+
result = pspace(expr).compute_expectation(expr, evaluate=evaluate)
|
| 289 |
+
if hasattr(result, 'doit') and evaluate:
|
| 290 |
+
return result.doit(**hints)
|
| 291 |
+
else:
|
| 292 |
+
return result
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
def _eval_rewrite_as_Probability(self, arg, condition=None, **kwargs):
|
| 296 |
+
rvs = arg.atoms(RandomSymbol)
|
| 297 |
+
if len(rvs) > 1:
|
| 298 |
+
raise NotImplementedError()
|
| 299 |
+
if len(rvs) == 0:
|
| 300 |
+
return arg
|
| 301 |
+
|
| 302 |
+
rv = rvs.pop()
|
| 303 |
+
if rv.pspace is None:
|
| 304 |
+
raise ValueError("Probability space not known")
|
| 305 |
+
|
| 306 |
+
symbol = rv.symbol
|
| 307 |
+
if symbol.name[0].isupper():
|
| 308 |
+
symbol = Symbol(symbol.name.lower())
|
| 309 |
+
else :
|
| 310 |
+
symbol = Symbol(symbol.name + "_1")
|
| 311 |
+
|
| 312 |
+
if rv.pspace.is_Continuous:
|
| 313 |
+
return Integral(arg.replace(rv, symbol)*Probability(Eq(rv, symbol), condition), (symbol, rv.pspace.domain.set.inf, rv.pspace.domain.set.sup))
|
| 314 |
+
else:
|
| 315 |
+
if rv.pspace.is_Finite:
|
| 316 |
+
raise NotImplementedError
|
| 317 |
+
else:
|
| 318 |
+
return Sum(arg.replace(rv, symbol)*Probability(Eq(rv, symbol), condition), (symbol, rv.pspace.domain.set.inf, rv.pspace.set.sup))
|
| 319 |
+
|
| 320 |
+
def _eval_rewrite_as_Integral(self, arg, condition=None, evaluate=False, **kwargs):
|
| 321 |
+
return self.func(arg, condition=condition).doit(deep=False, evaluate=evaluate)
|
| 322 |
+
|
| 323 |
+
_eval_rewrite_as_Sum = _eval_rewrite_as_Integral # For discrete this will be Sum
|
| 324 |
+
|
| 325 |
+
def evaluate_integral(self):
|
| 326 |
+
return self.rewrite(Integral).doit()
|
| 327 |
+
|
| 328 |
+
evaluate_sum = evaluate_integral
|
| 329 |
+
|
| 330 |
+
class Variance(Expr):
|
| 331 |
+
"""
|
| 332 |
+
Symbolic expression for the variance.
|
| 333 |
+
|
| 334 |
+
Examples
|
| 335 |
+
========
|
| 336 |
+
|
| 337 |
+
>>> from sympy import symbols, Integral
|
| 338 |
+
>>> from sympy.stats import Normal, Expectation, Variance, Probability
|
| 339 |
+
>>> mu = symbols("mu", positive=True)
|
| 340 |
+
>>> sigma = symbols("sigma", positive=True)
|
| 341 |
+
>>> X = Normal("X", mu, sigma)
|
| 342 |
+
>>> Variance(X)
|
| 343 |
+
Variance(X)
|
| 344 |
+
>>> Variance(X).evaluate_integral()
|
| 345 |
+
sigma**2
|
| 346 |
+
|
| 347 |
+
Integral representation of the underlying calculations:
|
| 348 |
+
|
| 349 |
+
>>> Variance(X).rewrite(Integral)
|
| 350 |
+
Integral(sqrt(2)*(X - Integral(sqrt(2)*X*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo)))**2*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo))
|
| 351 |
+
|
| 352 |
+
Integral representation, without expanding the PDF:
|
| 353 |
+
|
| 354 |
+
>>> Variance(X).rewrite(Probability)
|
| 355 |
+
-Integral(x*Probability(Eq(X, x)), (x, -oo, oo))**2 + Integral(x**2*Probability(Eq(X, x)), (x, -oo, oo))
|
| 356 |
+
|
| 357 |
+
Rewrite the variance in terms of the expectation
|
| 358 |
+
|
| 359 |
+
>>> Variance(X).rewrite(Expectation)
|
| 360 |
+
-Expectation(X)**2 + Expectation(X**2)
|
| 361 |
+
|
| 362 |
+
Some transformations based on the properties of the variance may happen:
|
| 363 |
+
|
| 364 |
+
>>> from sympy.abc import a
|
| 365 |
+
>>> Y = Normal("Y", 0, 1)
|
| 366 |
+
>>> Variance(a*X)
|
| 367 |
+
Variance(a*X)
|
| 368 |
+
|
| 369 |
+
To expand the variance in its expression, use ``expand()``:
|
| 370 |
+
|
| 371 |
+
>>> Variance(a*X).expand()
|
| 372 |
+
a**2*Variance(X)
|
| 373 |
+
>>> Variance(X + Y)
|
| 374 |
+
Variance(X + Y)
|
| 375 |
+
>>> Variance(X + Y).expand()
|
| 376 |
+
2*Covariance(X, Y) + Variance(X) + Variance(Y)
|
| 377 |
+
|
| 378 |
+
"""
|
| 379 |
+
def __new__(cls, arg, condition=None, **kwargs):
|
| 380 |
+
arg = _sympify(arg)
|
| 381 |
+
|
| 382 |
+
if arg.is_Matrix:
|
| 383 |
+
from sympy.stats.symbolic_multivariate_probability import VarianceMatrix
|
| 384 |
+
return VarianceMatrix(arg, condition)
|
| 385 |
+
if condition is None:
|
| 386 |
+
obj = Expr.__new__(cls, arg)
|
| 387 |
+
else:
|
| 388 |
+
condition = _sympify(condition)
|
| 389 |
+
obj = Expr.__new__(cls, arg, condition)
|
| 390 |
+
obj._condition = condition
|
| 391 |
+
return obj
|
| 392 |
+
|
| 393 |
+
def _eval_is_commutative(self):
|
| 394 |
+
return self.args[0].is_commutative
|
| 395 |
+
|
| 396 |
+
def expand(self, **hints):
|
| 397 |
+
arg = self.args[0]
|
| 398 |
+
condition = self._condition
|
| 399 |
+
|
| 400 |
+
if not is_random(arg):
|
| 401 |
+
return S.Zero
|
| 402 |
+
|
| 403 |
+
if isinstance(arg, RandomSymbol):
|
| 404 |
+
return self
|
| 405 |
+
elif isinstance(arg, Add):
|
| 406 |
+
rv = []
|
| 407 |
+
for a in arg.args:
|
| 408 |
+
if is_random(a):
|
| 409 |
+
rv.append(a)
|
| 410 |
+
variances = Add(*(Variance(xv, condition).expand() for xv in rv))
|
| 411 |
+
map_to_covar = lambda x: 2*Covariance(*x, condition=condition).expand()
|
| 412 |
+
covariances = Add(*map(map_to_covar, itertools.combinations(rv, 2)))
|
| 413 |
+
return variances + covariances
|
| 414 |
+
elif isinstance(arg, Mul):
|
| 415 |
+
nonrv = []
|
| 416 |
+
rv = []
|
| 417 |
+
for a in arg.args:
|
| 418 |
+
if is_random(a):
|
| 419 |
+
rv.append(a)
|
| 420 |
+
else:
|
| 421 |
+
nonrv.append(a**2)
|
| 422 |
+
if len(rv) == 0:
|
| 423 |
+
return S.Zero
|
| 424 |
+
return Mul.fromiter(nonrv)*Variance(Mul.fromiter(rv), condition)
|
| 425 |
+
|
| 426 |
+
# this expression contains a RandomSymbol somehow:
|
| 427 |
+
return self
|
| 428 |
+
|
| 429 |
+
def _eval_rewrite_as_Expectation(self, arg, condition=None, **kwargs):
|
| 430 |
+
e1 = Expectation(arg**2, condition)
|
| 431 |
+
e2 = Expectation(arg, condition)**2
|
| 432 |
+
return e1 - e2
|
| 433 |
+
|
| 434 |
+
def _eval_rewrite_as_Probability(self, arg, condition=None, **kwargs):
|
| 435 |
+
return self.rewrite(Expectation).rewrite(Probability)
|
| 436 |
+
|
| 437 |
+
def _eval_rewrite_as_Integral(self, arg, condition=None, **kwargs):
|
| 438 |
+
return variance(self.args[0], self._condition, evaluate=False)
|
| 439 |
+
|
| 440 |
+
_eval_rewrite_as_Sum = _eval_rewrite_as_Integral
|
| 441 |
+
|
| 442 |
+
def evaluate_integral(self):
|
| 443 |
+
return self.rewrite(Integral).doit()
|
| 444 |
+
|
| 445 |
+
|
| 446 |
+
class Covariance(Expr):
|
| 447 |
+
"""
|
| 448 |
+
Symbolic expression for the covariance.
|
| 449 |
+
|
| 450 |
+
Examples
|
| 451 |
+
========
|
| 452 |
+
|
| 453 |
+
>>> from sympy.stats import Covariance
|
| 454 |
+
>>> from sympy.stats import Normal
|
| 455 |
+
>>> X = Normal("X", 3, 2)
|
| 456 |
+
>>> Y = Normal("Y", 0, 1)
|
| 457 |
+
>>> Z = Normal("Z", 0, 1)
|
| 458 |
+
>>> W = Normal("W", 0, 1)
|
| 459 |
+
>>> cexpr = Covariance(X, Y)
|
| 460 |
+
>>> cexpr
|
| 461 |
+
Covariance(X, Y)
|
| 462 |
+
|
| 463 |
+
Evaluate the covariance, `X` and `Y` are independent,
|
| 464 |
+
therefore zero is the result:
|
| 465 |
+
|
| 466 |
+
>>> cexpr.evaluate_integral()
|
| 467 |
+
0
|
| 468 |
+
|
| 469 |
+
Rewrite the covariance expression in terms of expectations:
|
| 470 |
+
|
| 471 |
+
>>> from sympy.stats import Expectation
|
| 472 |
+
>>> cexpr.rewrite(Expectation)
|
| 473 |
+
Expectation(X*Y) - Expectation(X)*Expectation(Y)
|
| 474 |
+
|
| 475 |
+
In order to expand the argument, use ``expand()``:
|
| 476 |
+
|
| 477 |
+
>>> from sympy.abc import a, b, c, d
|
| 478 |
+
>>> Covariance(a*X + b*Y, c*Z + d*W)
|
| 479 |
+
Covariance(a*X + b*Y, c*Z + d*W)
|
| 480 |
+
>>> Covariance(a*X + b*Y, c*Z + d*W).expand()
|
| 481 |
+
a*c*Covariance(X, Z) + a*d*Covariance(W, X) + b*c*Covariance(Y, Z) + b*d*Covariance(W, Y)
|
| 482 |
+
|
| 483 |
+
This class is aware of some properties of the covariance:
|
| 484 |
+
|
| 485 |
+
>>> Covariance(X, X).expand()
|
| 486 |
+
Variance(X)
|
| 487 |
+
>>> Covariance(a*X, b*Y).expand()
|
| 488 |
+
a*b*Covariance(X, Y)
|
| 489 |
+
"""
|
| 490 |
+
|
| 491 |
+
def __new__(cls, arg1, arg2, condition=None, **kwargs):
|
| 492 |
+
arg1 = _sympify(arg1)
|
| 493 |
+
arg2 = _sympify(arg2)
|
| 494 |
+
|
| 495 |
+
if arg1.is_Matrix or arg2.is_Matrix:
|
| 496 |
+
from sympy.stats.symbolic_multivariate_probability import CrossCovarianceMatrix
|
| 497 |
+
return CrossCovarianceMatrix(arg1, arg2, condition)
|
| 498 |
+
|
| 499 |
+
if kwargs.pop('evaluate', global_parameters.evaluate):
|
| 500 |
+
arg1, arg2 = sorted([arg1, arg2], key=default_sort_key)
|
| 501 |
+
|
| 502 |
+
if condition is None:
|
| 503 |
+
obj = Expr.__new__(cls, arg1, arg2)
|
| 504 |
+
else:
|
| 505 |
+
condition = _sympify(condition)
|
| 506 |
+
obj = Expr.__new__(cls, arg1, arg2, condition)
|
| 507 |
+
obj._condition = condition
|
| 508 |
+
return obj
|
| 509 |
+
|
| 510 |
+
def _eval_is_commutative(self):
|
| 511 |
+
return self.args[0].is_commutative
|
| 512 |
+
|
| 513 |
+
def expand(self, **hints):
|
| 514 |
+
arg1 = self.args[0]
|
| 515 |
+
arg2 = self.args[1]
|
| 516 |
+
condition = self._condition
|
| 517 |
+
|
| 518 |
+
if arg1 == arg2:
|
| 519 |
+
return Variance(arg1, condition).expand()
|
| 520 |
+
|
| 521 |
+
if not is_random(arg1):
|
| 522 |
+
return S.Zero
|
| 523 |
+
if not is_random(arg2):
|
| 524 |
+
return S.Zero
|
| 525 |
+
|
| 526 |
+
arg1, arg2 = sorted([arg1, arg2], key=default_sort_key)
|
| 527 |
+
|
| 528 |
+
if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol):
|
| 529 |
+
return Covariance(arg1, arg2, condition)
|
| 530 |
+
|
| 531 |
+
coeff_rv_list1 = self._expand_single_argument(arg1.expand())
|
| 532 |
+
coeff_rv_list2 = self._expand_single_argument(arg2.expand())
|
| 533 |
+
|
| 534 |
+
addends = [a*b*Covariance(*sorted([r1, r2], key=default_sort_key), condition=condition)
|
| 535 |
+
for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2]
|
| 536 |
+
return Add.fromiter(addends)
|
| 537 |
+
|
| 538 |
+
@classmethod
|
| 539 |
+
def _expand_single_argument(cls, expr):
|
| 540 |
+
# return (coefficient, random_symbol) pairs:
|
| 541 |
+
if isinstance(expr, RandomSymbol):
|
| 542 |
+
return [(S.One, expr)]
|
| 543 |
+
elif isinstance(expr, Add):
|
| 544 |
+
outval = []
|
| 545 |
+
for a in expr.args:
|
| 546 |
+
if isinstance(a, Mul):
|
| 547 |
+
outval.append(cls._get_mul_nonrv_rv_tuple(a))
|
| 548 |
+
elif is_random(a):
|
| 549 |
+
outval.append((S.One, a))
|
| 550 |
+
|
| 551 |
+
return outval
|
| 552 |
+
elif isinstance(expr, Mul):
|
| 553 |
+
return [cls._get_mul_nonrv_rv_tuple(expr)]
|
| 554 |
+
elif is_random(expr):
|
| 555 |
+
return [(S.One, expr)]
|
| 556 |
+
|
| 557 |
+
@classmethod
|
| 558 |
+
def _get_mul_nonrv_rv_tuple(cls, m):
|
| 559 |
+
rv = []
|
| 560 |
+
nonrv = []
|
| 561 |
+
for a in m.args:
|
| 562 |
+
if is_random(a):
|
| 563 |
+
rv.append(a)
|
| 564 |
+
else:
|
| 565 |
+
nonrv.append(a)
|
| 566 |
+
return (Mul.fromiter(nonrv), Mul.fromiter(rv))
|
| 567 |
+
|
| 568 |
+
def _eval_rewrite_as_Expectation(self, arg1, arg2, condition=None, **kwargs):
|
| 569 |
+
e1 = Expectation(arg1*arg2, condition)
|
| 570 |
+
e2 = Expectation(arg1, condition)*Expectation(arg2, condition)
|
| 571 |
+
return e1 - e2
|
| 572 |
+
|
| 573 |
+
def _eval_rewrite_as_Probability(self, arg1, arg2, condition=None, **kwargs):
|
| 574 |
+
return self.rewrite(Expectation).rewrite(Probability)
|
| 575 |
+
|
| 576 |
+
def _eval_rewrite_as_Integral(self, arg1, arg2, condition=None, **kwargs):
|
| 577 |
+
return covariance(self.args[0], self.args[1], self._condition, evaluate=False)
|
| 578 |
+
|
| 579 |
+
_eval_rewrite_as_Sum = _eval_rewrite_as_Integral
|
| 580 |
+
|
| 581 |
+
def evaluate_integral(self):
|
| 582 |
+
return self.rewrite(Integral).doit()
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
class Moment(Expr):
|
| 586 |
+
"""
|
| 587 |
+
Symbolic class for Moment
|
| 588 |
+
|
| 589 |
+
Examples
|
| 590 |
+
========
|
| 591 |
+
|
| 592 |
+
>>> from sympy import Symbol, Integral
|
| 593 |
+
>>> from sympy.stats import Normal, Expectation, Probability, Moment
|
| 594 |
+
>>> mu = Symbol('mu', real=True)
|
| 595 |
+
>>> sigma = Symbol('sigma', positive=True)
|
| 596 |
+
>>> X = Normal('X', mu, sigma)
|
| 597 |
+
>>> M = Moment(X, 3, 1)
|
| 598 |
+
|
| 599 |
+
To evaluate the result of Moment use `doit`:
|
| 600 |
+
|
| 601 |
+
>>> M.doit()
|
| 602 |
+
mu**3 - 3*mu**2 + 3*mu*sigma**2 + 3*mu - 3*sigma**2 - 1
|
| 603 |
+
|
| 604 |
+
Rewrite the Moment expression in terms of Expectation:
|
| 605 |
+
|
| 606 |
+
>>> M.rewrite(Expectation)
|
| 607 |
+
Expectation((X - 1)**3)
|
| 608 |
+
|
| 609 |
+
Rewrite the Moment expression in terms of Probability:
|
| 610 |
+
|
| 611 |
+
>>> M.rewrite(Probability)
|
| 612 |
+
Integral((x - 1)**3*Probability(Eq(X, x)), (x, -oo, oo))
|
| 613 |
+
|
| 614 |
+
Rewrite the Moment expression in terms of Integral:
|
| 615 |
+
|
| 616 |
+
>>> M.rewrite(Integral)
|
| 617 |
+
Integral(sqrt(2)*(X - 1)**3*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo))
|
| 618 |
+
|
| 619 |
+
"""
|
| 620 |
+
def __new__(cls, X, n, c=0, condition=None, **kwargs):
|
| 621 |
+
X = _sympify(X)
|
| 622 |
+
n = _sympify(n)
|
| 623 |
+
c = _sympify(c)
|
| 624 |
+
if condition is not None:
|
| 625 |
+
condition = _sympify(condition)
|
| 626 |
+
return super().__new__(cls, X, n, c, condition)
|
| 627 |
+
else:
|
| 628 |
+
return super().__new__(cls, X, n, c)
|
| 629 |
+
|
| 630 |
+
def doit(self, **hints):
|
| 631 |
+
return self.rewrite(Expectation).doit(**hints)
|
| 632 |
+
|
| 633 |
+
def _eval_rewrite_as_Expectation(self, X, n, c=0, condition=None, **kwargs):
|
| 634 |
+
return Expectation((X - c)**n, condition)
|
| 635 |
+
|
| 636 |
+
def _eval_rewrite_as_Probability(self, X, n, c=0, condition=None, **kwargs):
|
| 637 |
+
return self.rewrite(Expectation).rewrite(Probability)
|
| 638 |
+
|
| 639 |
+
def _eval_rewrite_as_Integral(self, X, n, c=0, condition=None, **kwargs):
|
| 640 |
+
return self.rewrite(Expectation).rewrite(Integral)
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
class CentralMoment(Expr):
|
| 644 |
+
"""
|
| 645 |
+
Symbolic class Central Moment
|
| 646 |
+
|
| 647 |
+
Examples
|
| 648 |
+
========
|
| 649 |
+
|
| 650 |
+
>>> from sympy import Symbol, Integral
|
| 651 |
+
>>> from sympy.stats import Normal, Expectation, Probability, CentralMoment
|
| 652 |
+
>>> mu = Symbol('mu', real=True)
|
| 653 |
+
>>> sigma = Symbol('sigma', positive=True)
|
| 654 |
+
>>> X = Normal('X', mu, sigma)
|
| 655 |
+
>>> CM = CentralMoment(X, 4)
|
| 656 |
+
|
| 657 |
+
To evaluate the result of CentralMoment use `doit`:
|
| 658 |
+
|
| 659 |
+
>>> CM.doit().simplify()
|
| 660 |
+
3*sigma**4
|
| 661 |
+
|
| 662 |
+
Rewrite the CentralMoment expression in terms of Expectation:
|
| 663 |
+
|
| 664 |
+
>>> CM.rewrite(Expectation)
|
| 665 |
+
Expectation((-Expectation(X) + X)**4)
|
| 666 |
+
|
| 667 |
+
Rewrite the CentralMoment expression in terms of Probability:
|
| 668 |
+
|
| 669 |
+
>>> CM.rewrite(Probability)
|
| 670 |
+
Integral((x - Integral(x*Probability(True), (x, -oo, oo)))**4*Probability(Eq(X, x)), (x, -oo, oo))
|
| 671 |
+
|
| 672 |
+
Rewrite the CentralMoment expression in terms of Integral:
|
| 673 |
+
|
| 674 |
+
>>> CM.rewrite(Integral)
|
| 675 |
+
Integral(sqrt(2)*(X - Integral(sqrt(2)*X*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo)))**4*exp(-(X - mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (X, -oo, oo))
|
| 676 |
+
|
| 677 |
+
"""
|
| 678 |
+
def __new__(cls, X, n, condition=None, **kwargs):
|
| 679 |
+
X = _sympify(X)
|
| 680 |
+
n = _sympify(n)
|
| 681 |
+
if condition is not None:
|
| 682 |
+
condition = _sympify(condition)
|
| 683 |
+
return super().__new__(cls, X, n, condition)
|
| 684 |
+
else:
|
| 685 |
+
return super().__new__(cls, X, n)
|
| 686 |
+
|
| 687 |
+
def doit(self, **hints):
|
| 688 |
+
return self.rewrite(Expectation).doit(**hints)
|
| 689 |
+
|
| 690 |
+
def _eval_rewrite_as_Expectation(self, X, n, condition=None, **kwargs):
|
| 691 |
+
mu = Expectation(X, condition, **kwargs)
|
| 692 |
+
return Moment(X, n, mu, condition, **kwargs).rewrite(Expectation)
|
| 693 |
+
|
| 694 |
+
def _eval_rewrite_as_Probability(self, X, n, condition=None, **kwargs):
|
| 695 |
+
return self.rewrite(Expectation).rewrite(Probability)
|
| 696 |
+
|
| 697 |
+
def _eval_rewrite_as_Integral(self, X, n, condition=None, **kwargs):
|
| 698 |
+
return self.rewrite(Expectation).rewrite(Integral)
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__init__.py
ADDED
|
File without changes
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (184 Bytes). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_compound_rv.cpython-312.pyc
ADDED
|
Binary file (11.7 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_continuous_rv.cpython-312.pyc
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a2a523ce768f5e98213027ced9d1ecfc4f51b816e8646eaa196093919a06b5f7
|
| 3 |
+
size 125806
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_discrete_rv.cpython-312.pyc
ADDED
|
Binary file (24.8 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_error_prop.cpython-312.pyc
ADDED
|
Binary file (3.5 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_finite_rv.cpython-312.pyc
ADDED
|
Binary file (49.6 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_joint_rv.cpython-312.pyc
ADDED
|
Binary file (35.5 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_matrix_distributions.cpython-312.pyc
ADDED
|
Binary file (20.5 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_mix.cpython-312.pyc
ADDED
|
Binary file (8.09 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_random_matrix.cpython-312.pyc
ADDED
|
Binary file (11.9 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_rv.cpython-312.pyc
ADDED
|
Binary file (29.1 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_stochastic_process.cpython-312.pyc
ADDED
|
Binary file (86.4 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_multivariate.cpython-312.pyc
ADDED
|
Binary file (12.3 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_probability.cpython-312.pyc
ADDED
|
Binary file (20.5 kB). View file
|
|
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_compound_rv.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.numbers import (oo, pi)
|
| 3 |
+
from sympy.core.relational import Eq
|
| 4 |
+
from sympy.core.singleton import S
|
| 5 |
+
from sympy.core.symbol import symbols
|
| 6 |
+
from sympy.functions.combinatorial.factorials import factorial
|
| 7 |
+
from sympy.functions.elementary.exponential import exp
|
| 8 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 9 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 10 |
+
from sympy.functions.special.beta_functions import beta
|
| 11 |
+
from sympy.functions.special.error_functions import erf
|
| 12 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 13 |
+
from sympy.integrals.integrals import Integral
|
| 14 |
+
from sympy.sets.sets import Interval
|
| 15 |
+
from sympy.stats import (Normal, P, E, density, Gamma, Poisson, Rayleigh,
|
| 16 |
+
variance, Bernoulli, Beta, Uniform, cdf)
|
| 17 |
+
from sympy.stats.compound_rv import CompoundDistribution, CompoundPSpace
|
| 18 |
+
from sympy.stats.crv_types import NormalDistribution
|
| 19 |
+
from sympy.stats.drv_types import PoissonDistribution
|
| 20 |
+
from sympy.stats.frv_types import BernoulliDistribution
|
| 21 |
+
from sympy.testing.pytest import raises, ignore_warnings
|
| 22 |
+
from sympy.stats.joint_rv_types import MultivariateNormalDistribution
|
| 23 |
+
|
| 24 |
+
from sympy.abc import x
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# helpers for testing troublesome unevaluated expressions
|
| 28 |
+
flat = lambda s: ''.join(str(s).split())
|
| 29 |
+
streq = lambda *a: len(set(map(flat, a))) == 1
|
| 30 |
+
assert streq(x, x)
|
| 31 |
+
assert streq(x, 'x')
|
| 32 |
+
assert not streq(x, x + 1)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def test_normal_CompoundDist():
|
| 36 |
+
X = Normal('X', 1, 2)
|
| 37 |
+
Y = Normal('X', X, 4)
|
| 38 |
+
assert density(Y)(x).simplify() == sqrt(10)*exp(-x**2/40 + x/20 - S(1)/40)/(20*sqrt(pi))
|
| 39 |
+
assert E(Y) == 1 # it is always equal to mean of X
|
| 40 |
+
assert P(Y > 1) == S(1)/2 # as 1 is the mean
|
| 41 |
+
assert P(Y > 5).simplify() == S(1)/2 - erf(sqrt(10)/5)/2
|
| 42 |
+
assert variance(Y) == variance(X) + 4**2 # 2**2 + 4**2
|
| 43 |
+
# https://math.stackexchange.com/questions/1484451/
|
| 44 |
+
# (Contains proof of E and variance computation)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def test_poisson_CompoundDist():
|
| 48 |
+
k, t, y = symbols('k t y', positive=True, real=True)
|
| 49 |
+
G = Gamma('G', k, t)
|
| 50 |
+
D = Poisson('P', G)
|
| 51 |
+
assert density(D)(y).simplify() == t**y*(t + 1)**(-k - y)*gamma(k + y)/(gamma(k)*gamma(y + 1))
|
| 52 |
+
# https://en.wikipedia.org/wiki/Negative_binomial_distribution#Gamma%E2%80%93Poisson_mixture
|
| 53 |
+
assert E(D).simplify() == k*t # mean of NegativeBinomialDistribution
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def test_bernoulli_CompoundDist():
|
| 57 |
+
X = Beta('X', 1, 2)
|
| 58 |
+
Y = Bernoulli('Y', X)
|
| 59 |
+
assert density(Y).dict == {0: S(2)/3, 1: S(1)/3}
|
| 60 |
+
assert E(Y) == P(Eq(Y, 1)) == S(1)/3
|
| 61 |
+
assert variance(Y) == S(2)/9
|
| 62 |
+
assert cdf(Y) == {0: S(2)/3, 1: 1}
|
| 63 |
+
|
| 64 |
+
# test issue 8128
|
| 65 |
+
a = Bernoulli('a', S(1)/2)
|
| 66 |
+
b = Bernoulli('b', a)
|
| 67 |
+
assert density(b).dict == {0: S(1)/2, 1: S(1)/2}
|
| 68 |
+
assert P(b > 0.5) == S(1)/2
|
| 69 |
+
|
| 70 |
+
X = Uniform('X', 0, 1)
|
| 71 |
+
Y = Bernoulli('Y', X)
|
| 72 |
+
assert E(Y) == S(1)/2
|
| 73 |
+
assert P(Eq(Y, 1)) == E(Y)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_unevaluated_CompoundDist():
|
| 77 |
+
# these tests need to be removed once they work with evaluation as they are currently not
|
| 78 |
+
# evaluated completely in sympy.
|
| 79 |
+
R = Rayleigh('R', 4)
|
| 80 |
+
X = Normal('X', 3, R)
|
| 81 |
+
ans = '''
|
| 82 |
+
Piecewise(((-sqrt(pi)*sinh(x/4 - 3/4) + sqrt(pi)*cosh(x/4 - 3/4))/(
|
| 83 |
+
8*sqrt(pi)), Abs(arg(x - 3)) <= pi/4), (Integral(sqrt(2)*exp(-(x - 3)
|
| 84 |
+
**2/(2*R**2))*exp(-R**2/32)/(32*sqrt(pi)), (R, 0, oo)), True))'''
|
| 85 |
+
assert streq(density(X)(x), ans)
|
| 86 |
+
|
| 87 |
+
expre = '''
|
| 88 |
+
Integral(X*Integral(sqrt(2)*exp(-(X-3)**2/(2*R**2))*exp(-R**2/32)/(32*
|
| 89 |
+
sqrt(pi)),(R,0,oo)),(X,-oo,oo))'''
|
| 90 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 91 |
+
assert streq(E(X, evaluate=False).rewrite(Integral), expre)
|
| 92 |
+
|
| 93 |
+
X = Poisson('X', 1)
|
| 94 |
+
Y = Poisson('Y', X)
|
| 95 |
+
Z = Poisson('Z', Y)
|
| 96 |
+
exprd = Sum(exp(-Y)*Y**x*Sum(exp(-1)*exp(-X)*X**Y/(factorial(X)*factorial(Y)
|
| 97 |
+
), (X, 0, oo))/factorial(x), (Y, 0, oo))
|
| 98 |
+
assert density(Z)(x) == exprd
|
| 99 |
+
|
| 100 |
+
N = Normal('N', 1, 2)
|
| 101 |
+
M = Normal('M', 3, 4)
|
| 102 |
+
D = Normal('D', M, N)
|
| 103 |
+
exprd = '''
|
| 104 |
+
Integral(sqrt(2)*exp(-(N-1)**2/8)*Integral(exp(-(x-M)**2/(2*N**2))*exp
|
| 105 |
+
(-(M-3)**2/32)/(8*pi*N),(M,-oo,oo))/(4*sqrt(pi)),(N,-oo,oo))'''
|
| 106 |
+
assert streq(density(D, evaluate=False)(x), exprd)
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def test_Compound_Distribution():
|
| 110 |
+
X = Normal('X', 2, 4)
|
| 111 |
+
N = NormalDistribution(X, 4)
|
| 112 |
+
C = CompoundDistribution(N)
|
| 113 |
+
assert C.is_Continuous
|
| 114 |
+
assert C.set == Interval(-oo, oo)
|
| 115 |
+
assert C.pdf(x, evaluate=True).simplify() == exp(-x**2/64 + x/16 - S(1)/16)/(8*sqrt(pi))
|
| 116 |
+
|
| 117 |
+
assert not isinstance(CompoundDistribution(NormalDistribution(2, 3)),
|
| 118 |
+
CompoundDistribution)
|
| 119 |
+
M = MultivariateNormalDistribution([1, 2], [[2, 1], [1, 2]])
|
| 120 |
+
raises(NotImplementedError, lambda: CompoundDistribution(M))
|
| 121 |
+
|
| 122 |
+
X = Beta('X', 2, 4)
|
| 123 |
+
B = BernoulliDistribution(X, 1, 0)
|
| 124 |
+
C = CompoundDistribution(B)
|
| 125 |
+
assert C.is_Finite
|
| 126 |
+
assert C.set == {0, 1}
|
| 127 |
+
y = symbols('y', negative=False, integer=True)
|
| 128 |
+
assert C.pdf(y, evaluate=True) == Piecewise((S(1)/(30*beta(2, 4)), Eq(y, 0)),
|
| 129 |
+
(S(1)/(60*beta(2, 4)), Eq(y, 1)), (0, True))
|
| 130 |
+
|
| 131 |
+
k, t, z = symbols('k t z', positive=True, real=True)
|
| 132 |
+
G = Gamma('G', k, t)
|
| 133 |
+
X = PoissonDistribution(G)
|
| 134 |
+
C = CompoundDistribution(X)
|
| 135 |
+
assert C.is_Discrete
|
| 136 |
+
assert C.set == S.Naturals0
|
| 137 |
+
assert C.pdf(z, evaluate=True).simplify() == t**z*(t + 1)**(-k - z)*gamma(k \
|
| 138 |
+
+ z)/(gamma(k)*gamma(z + 1))
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_compound_pspace():
|
| 142 |
+
X = Normal('X', 2, 4)
|
| 143 |
+
Y = Normal('Y', 3, 6)
|
| 144 |
+
assert not isinstance(Y.pspace, CompoundPSpace)
|
| 145 |
+
N = NormalDistribution(1, 2)
|
| 146 |
+
D = PoissonDistribution(3)
|
| 147 |
+
B = BernoulliDistribution(0.2, 1, 0)
|
| 148 |
+
pspace1 = CompoundPSpace('N', N)
|
| 149 |
+
pspace2 = CompoundPSpace('D', D)
|
| 150 |
+
pspace3 = CompoundPSpace('B', B)
|
| 151 |
+
assert not isinstance(pspace1, CompoundPSpace)
|
| 152 |
+
assert not isinstance(pspace2, CompoundPSpace)
|
| 153 |
+
assert not isinstance(pspace3, CompoundPSpace)
|
| 154 |
+
M = MultivariateNormalDistribution([1, 2], [[2, 1], [1, 2]])
|
| 155 |
+
raises(ValueError, lambda: CompoundPSpace('M', M))
|
| 156 |
+
Y = Normal('Y', X, 6)
|
| 157 |
+
assert isinstance(Y.pspace, CompoundPSpace)
|
| 158 |
+
assert Y.pspace.distribution == CompoundDistribution(NormalDistribution(X, 6))
|
| 159 |
+
assert Y.pspace.domain.set == Interval(-oo, oo)
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_continuous_rv.py
ADDED
|
@@ -0,0 +1,1583 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.function import (Lambda, diff, expand_func)
|
| 3 |
+
from sympy.core.mul import Mul
|
| 4 |
+
from sympy.core import EulerGamma
|
| 5 |
+
from sympy.core.numbers import (E as e, I, Rational, pi)
|
| 6 |
+
from sympy.core.relational import (Eq, Ne)
|
| 7 |
+
from sympy.core.singleton import S
|
| 8 |
+
from sympy.core.symbol import (Dummy, Symbol, symbols)
|
| 9 |
+
from sympy.functions.combinatorial.factorials import (binomial, factorial)
|
| 10 |
+
from sympy.functions.elementary.complexes import (Abs, im, re, sign)
|
| 11 |
+
from sympy.functions.elementary.exponential import (exp, log)
|
| 12 |
+
from sympy.functions.elementary.hyperbolic import (cosh, sinh)
|
| 13 |
+
from sympy.functions.elementary.integers import floor
|
| 14 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 15 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 16 |
+
from sympy.functions.elementary.trigonometric import (asin, atan, cos, sin, tan)
|
| 17 |
+
from sympy.functions.special.bessel import (besseli, besselj, besselk)
|
| 18 |
+
from sympy.functions.special.beta_functions import beta
|
| 19 |
+
from sympy.functions.special.error_functions import (erf, erfc, erfi, expint)
|
| 20 |
+
from sympy.functions.special.gamma_functions import (gamma, lowergamma, uppergamma)
|
| 21 |
+
from sympy.functions.special.zeta_functions import zeta
|
| 22 |
+
from sympy.functions.special.hyper import hyper
|
| 23 |
+
from sympy.integrals.integrals import Integral
|
| 24 |
+
from sympy.logic.boolalg import (And, Or)
|
| 25 |
+
from sympy.sets.sets import Interval
|
| 26 |
+
from sympy.simplify.simplify import simplify
|
| 27 |
+
from sympy.utilities.lambdify import lambdify
|
| 28 |
+
from sympy.functions.special.error_functions import erfinv
|
| 29 |
+
from sympy.functions.special.hyper import meijerg
|
| 30 |
+
from sympy.sets.sets import FiniteSet, Complement, Intersection
|
| 31 |
+
from sympy.stats import (P, E, where, density, variance, covariance, skewness, kurtosis, median,
|
| 32 |
+
given, pspace, cdf, characteristic_function, moment_generating_function,
|
| 33 |
+
ContinuousRV, Arcsin, Benini, Beta, BetaNoncentral, BetaPrime,
|
| 34 |
+
Cauchy, Chi, ChiSquared, ChiNoncentral, Dagum, Davis, Erlang, ExGaussian,
|
| 35 |
+
Exponential, ExponentialPower, FDistribution, FisherZ, Frechet, Gamma,
|
| 36 |
+
GammaInverse, Gompertz, Gumbel, Kumaraswamy, Laplace, Levy, Logistic, LogCauchy,
|
| 37 |
+
LogLogistic, LogitNormal, LogNormal, Maxwell, Moyal, Nakagami, Normal, GaussianInverse,
|
| 38 |
+
Pareto, PowerFunction, QuadraticU, RaisedCosine, Rayleigh, Reciprocal, ShiftedGompertz, StudentT,
|
| 39 |
+
Trapezoidal, Triangular, Uniform, UniformSum, VonMises, Weibull, coskewness,
|
| 40 |
+
WignerSemicircle, Wald, correlation, moment, cmoment, smoment, quantile,
|
| 41 |
+
Lomax, BoundedPareto)
|
| 42 |
+
|
| 43 |
+
from sympy.stats.crv_types import NormalDistribution, ExponentialDistribution, ContinuousDistributionHandmade
|
| 44 |
+
from sympy.stats.joint_rv_types import MultivariateLaplaceDistribution, MultivariateNormalDistribution
|
| 45 |
+
from sympy.stats.crv import SingleContinuousPSpace, SingleContinuousDomain
|
| 46 |
+
from sympy.stats.compound_rv import CompoundPSpace
|
| 47 |
+
from sympy.stats.symbolic_probability import Probability
|
| 48 |
+
from sympy.testing.pytest import raises, XFAIL, slow, ignore_warnings
|
| 49 |
+
from sympy.core.random import verify_numerically as tn
|
| 50 |
+
|
| 51 |
+
oo = S.Infinity
|
| 52 |
+
|
| 53 |
+
x, y, z = map(Symbol, 'xyz')
|
| 54 |
+
|
| 55 |
+
def test_single_normal():
|
| 56 |
+
mu = Symbol('mu', real=True)
|
| 57 |
+
sigma = Symbol('sigma', positive=True)
|
| 58 |
+
X = Normal('x', 0, 1)
|
| 59 |
+
Y = X*sigma + mu
|
| 60 |
+
|
| 61 |
+
assert E(Y) == mu
|
| 62 |
+
assert variance(Y) == sigma**2
|
| 63 |
+
pdf = density(Y)
|
| 64 |
+
x = Symbol('x', real=True)
|
| 65 |
+
assert (pdf(x) ==
|
| 66 |
+
2**S.Half*exp(-(x - mu)**2/(2*sigma**2))/(2*pi**S.Half*sigma))
|
| 67 |
+
|
| 68 |
+
assert P(X**2 < 1) == erf(2**S.Half/2)
|
| 69 |
+
ans = quantile(Y)(x)
|
| 70 |
+
assert ans == Complement(Intersection(FiniteSet(
|
| 71 |
+
sqrt(2)*sigma*(sqrt(2)*mu/(2*sigma)+ erfinv(2*x - 1))),
|
| 72 |
+
Interval(-oo, oo)), FiniteSet(mu))
|
| 73 |
+
assert E(X, Eq(X, mu)) == mu
|
| 74 |
+
|
| 75 |
+
assert median(X) == FiniteSet(0)
|
| 76 |
+
# issue 8248
|
| 77 |
+
assert X.pspace.compute_expectation(1).doit() == 1
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_conditional_1d():
|
| 81 |
+
X = Normal('x', 0, 1)
|
| 82 |
+
Y = given(X, X >= 0)
|
| 83 |
+
z = Symbol('z')
|
| 84 |
+
|
| 85 |
+
assert density(Y)(z) == 2 * density(X)(z)
|
| 86 |
+
|
| 87 |
+
assert Y.pspace.domain.set == Interval(0, oo)
|
| 88 |
+
assert E(Y) == sqrt(2) / sqrt(pi)
|
| 89 |
+
|
| 90 |
+
assert E(X**2) == E(Y**2)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def test_ContinuousDomain():
|
| 94 |
+
X = Normal('x', 0, 1)
|
| 95 |
+
assert where(X**2 <= 1).set == Interval(-1, 1)
|
| 96 |
+
assert where(X**2 <= 1).symbol == X.symbol
|
| 97 |
+
assert where(And(X**2 <= 1, X >= 0)).set == Interval(0, 1)
|
| 98 |
+
raises(ValueError, lambda: where(sin(X) > 1))
|
| 99 |
+
|
| 100 |
+
Y = given(X, X >= 0)
|
| 101 |
+
|
| 102 |
+
assert Y.pspace.domain.set == Interval(0, oo)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def test_multiple_normal():
|
| 106 |
+
X, Y = Normal('x', 0, 1), Normal('y', 0, 1)
|
| 107 |
+
p = Symbol("p", positive=True)
|
| 108 |
+
|
| 109 |
+
assert E(X + Y) == 0
|
| 110 |
+
assert variance(X + Y) == 2
|
| 111 |
+
assert variance(X + X) == 4
|
| 112 |
+
assert covariance(X, Y) == 0
|
| 113 |
+
assert covariance(2*X + Y, -X) == -2*variance(X)
|
| 114 |
+
assert skewness(X) == 0
|
| 115 |
+
assert skewness(X + Y) == 0
|
| 116 |
+
assert kurtosis(X) == 3
|
| 117 |
+
assert kurtosis(X+Y) == 3
|
| 118 |
+
assert correlation(X, Y) == 0
|
| 119 |
+
assert correlation(X, X + Y) == correlation(X, X - Y)
|
| 120 |
+
assert moment(X, 2) == 1
|
| 121 |
+
assert cmoment(X, 3) == 0
|
| 122 |
+
assert moment(X + Y, 4) == 12
|
| 123 |
+
assert cmoment(X, 2) == variance(X)
|
| 124 |
+
assert smoment(X*X, 2) == 1
|
| 125 |
+
assert smoment(X + Y, 3) == skewness(X + Y)
|
| 126 |
+
assert smoment(X + Y, 4) == kurtosis(X + Y)
|
| 127 |
+
assert E(X, Eq(X + Y, 0)) == 0
|
| 128 |
+
assert variance(X, Eq(X + Y, 0)) == S.Half
|
| 129 |
+
assert quantile(X)(p) == sqrt(2)*erfinv(2*p - S.One)
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def test_symbolic():
|
| 133 |
+
mu1, mu2 = symbols('mu1 mu2', real=True)
|
| 134 |
+
s1, s2 = symbols('sigma1 sigma2', positive=True)
|
| 135 |
+
rate = Symbol('lambda', positive=True)
|
| 136 |
+
X = Normal('x', mu1, s1)
|
| 137 |
+
Y = Normal('y', mu2, s2)
|
| 138 |
+
Z = Exponential('z', rate)
|
| 139 |
+
a, b, c = symbols('a b c', real=True)
|
| 140 |
+
|
| 141 |
+
assert E(X) == mu1
|
| 142 |
+
assert E(X + Y) == mu1 + mu2
|
| 143 |
+
assert E(a*X + b) == a*E(X) + b
|
| 144 |
+
assert variance(X) == s1**2
|
| 145 |
+
assert variance(X + a*Y + b) == variance(X) + a**2*variance(Y)
|
| 146 |
+
|
| 147 |
+
assert E(Z) == 1/rate
|
| 148 |
+
assert E(a*Z + b) == a*E(Z) + b
|
| 149 |
+
assert E(X + a*Z + b) == mu1 + a/rate + b
|
| 150 |
+
assert median(X) == FiniteSet(mu1)
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def test_cdf():
|
| 154 |
+
X = Normal('x', 0, 1)
|
| 155 |
+
|
| 156 |
+
d = cdf(X)
|
| 157 |
+
assert P(X < 1) == d(1).rewrite(erfc)
|
| 158 |
+
assert d(0) == S.Half
|
| 159 |
+
|
| 160 |
+
d = cdf(X, X > 0) # given X>0
|
| 161 |
+
assert d(0) == 0
|
| 162 |
+
|
| 163 |
+
Y = Exponential('y', 10)
|
| 164 |
+
d = cdf(Y)
|
| 165 |
+
assert d(-5) == 0
|
| 166 |
+
assert P(Y > 3) == 1 - d(3)
|
| 167 |
+
|
| 168 |
+
raises(ValueError, lambda: cdf(X + Y))
|
| 169 |
+
|
| 170 |
+
Z = Exponential('z', 1)
|
| 171 |
+
f = cdf(Z)
|
| 172 |
+
assert f(z) == Piecewise((1 - exp(-z), z >= 0), (0, True))
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def test_characteristic_function():
|
| 176 |
+
X = Uniform('x', 0, 1)
|
| 177 |
+
|
| 178 |
+
cf = characteristic_function(X)
|
| 179 |
+
assert cf(1) == -I*(-1 + exp(I))
|
| 180 |
+
|
| 181 |
+
Y = Normal('y', 1, 1)
|
| 182 |
+
cf = characteristic_function(Y)
|
| 183 |
+
assert cf(0) == 1
|
| 184 |
+
assert cf(1) == exp(I - S.Half)
|
| 185 |
+
|
| 186 |
+
Z = Exponential('z', 5)
|
| 187 |
+
cf = characteristic_function(Z)
|
| 188 |
+
assert cf(0) == 1
|
| 189 |
+
assert cf(1).expand() == Rational(25, 26) + I*5/26
|
| 190 |
+
|
| 191 |
+
X = GaussianInverse('x', 1, 1)
|
| 192 |
+
cf = characteristic_function(X)
|
| 193 |
+
assert cf(0) == 1
|
| 194 |
+
assert cf(1) == exp(1 - sqrt(1 - 2*I))
|
| 195 |
+
|
| 196 |
+
X = ExGaussian('x', 0, 1, 1)
|
| 197 |
+
cf = characteristic_function(X)
|
| 198 |
+
assert cf(0) == 1
|
| 199 |
+
assert cf(1) == (1 + I)*exp(Rational(-1, 2))/2
|
| 200 |
+
|
| 201 |
+
L = Levy('x', 0, 1)
|
| 202 |
+
cf = characteristic_function(L)
|
| 203 |
+
assert cf(0) == 1
|
| 204 |
+
assert cf(1) == exp(-sqrt(2)*sqrt(-I))
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def test_moment_generating_function():
|
| 208 |
+
t = symbols('t', positive=True)
|
| 209 |
+
|
| 210 |
+
# Symbolic tests
|
| 211 |
+
a, b, c = symbols('a b c')
|
| 212 |
+
|
| 213 |
+
mgf = moment_generating_function(Beta('x', a, b))(t)
|
| 214 |
+
assert mgf == hyper((a,), (a + b,), t)
|
| 215 |
+
|
| 216 |
+
mgf = moment_generating_function(Chi('x', a))(t)
|
| 217 |
+
assert mgf == sqrt(2)*t*gamma(a/2 + S.Half)*\
|
| 218 |
+
hyper((a/2 + S.Half,), (Rational(3, 2),), t**2/2)/gamma(a/2) +\
|
| 219 |
+
hyper((a/2,), (S.Half,), t**2/2)
|
| 220 |
+
|
| 221 |
+
mgf = moment_generating_function(ChiSquared('x', a))(t)
|
| 222 |
+
assert mgf == (1 - 2*t)**(-a/2)
|
| 223 |
+
|
| 224 |
+
mgf = moment_generating_function(Erlang('x', a, b))(t)
|
| 225 |
+
assert mgf == (1 - t/b)**(-a)
|
| 226 |
+
|
| 227 |
+
mgf = moment_generating_function(ExGaussian("x", a, b, c))(t)
|
| 228 |
+
assert mgf == exp(a*t + b**2*t**2/2)/(1 - t/c)
|
| 229 |
+
|
| 230 |
+
mgf = moment_generating_function(Exponential('x', a))(t)
|
| 231 |
+
assert mgf == a/(a - t)
|
| 232 |
+
|
| 233 |
+
mgf = moment_generating_function(Gamma('x', a, b))(t)
|
| 234 |
+
assert mgf == (-b*t + 1)**(-a)
|
| 235 |
+
|
| 236 |
+
mgf = moment_generating_function(Gumbel('x', a, b))(t)
|
| 237 |
+
assert mgf == exp(b*t)*gamma(-a*t + 1)
|
| 238 |
+
|
| 239 |
+
mgf = moment_generating_function(Gompertz('x', a, b))(t)
|
| 240 |
+
assert mgf == b*exp(b)*expint(t/a, b)
|
| 241 |
+
|
| 242 |
+
mgf = moment_generating_function(Laplace('x', a, b))(t)
|
| 243 |
+
assert mgf == exp(a*t)/(-b**2*t**2 + 1)
|
| 244 |
+
|
| 245 |
+
mgf = moment_generating_function(Logistic('x', a, b))(t)
|
| 246 |
+
assert mgf == exp(a*t)*beta(-b*t + 1, b*t + 1)
|
| 247 |
+
|
| 248 |
+
mgf = moment_generating_function(Normal('x', a, b))(t)
|
| 249 |
+
assert mgf == exp(a*t + b**2*t**2/2)
|
| 250 |
+
|
| 251 |
+
mgf = moment_generating_function(Pareto('x', a, b))(t)
|
| 252 |
+
assert mgf == b*(-a*t)**b*uppergamma(-b, -a*t)
|
| 253 |
+
|
| 254 |
+
mgf = moment_generating_function(QuadraticU('x', a, b))(t)
|
| 255 |
+
assert str(mgf) == ("(3*(t*(-4*b + (a + b)**2) + 4)*exp(b*t) - "
|
| 256 |
+
"3*(t*(a**2 + 2*a*(b - 2) + b**2) + 4)*exp(a*t))/(t**2*(a - b)**3)")
|
| 257 |
+
|
| 258 |
+
mgf = moment_generating_function(RaisedCosine('x', a, b))(t)
|
| 259 |
+
assert mgf == pi**2*exp(a*t)*sinh(b*t)/(b*t*(b**2*t**2 + pi**2))
|
| 260 |
+
|
| 261 |
+
mgf = moment_generating_function(Rayleigh('x', a))(t)
|
| 262 |
+
assert mgf == sqrt(2)*sqrt(pi)*a*t*(erf(sqrt(2)*a*t/2) + 1)\
|
| 263 |
+
*exp(a**2*t**2/2)/2 + 1
|
| 264 |
+
|
| 265 |
+
mgf = moment_generating_function(Triangular('x', a, b, c))(t)
|
| 266 |
+
assert str(mgf) == ("(-2*(-a + b)*exp(c*t) + 2*(-a + c)*exp(b*t) + "
|
| 267 |
+
"2*(b - c)*exp(a*t))/(t**2*(-a + b)*(-a + c)*(b - c))")
|
| 268 |
+
|
| 269 |
+
mgf = moment_generating_function(Uniform('x', a, b))(t)
|
| 270 |
+
assert mgf == (-exp(a*t) + exp(b*t))/(t*(-a + b))
|
| 271 |
+
|
| 272 |
+
mgf = moment_generating_function(UniformSum('x', a))(t)
|
| 273 |
+
assert mgf == ((exp(t) - 1)/t)**a
|
| 274 |
+
|
| 275 |
+
mgf = moment_generating_function(WignerSemicircle('x', a))(t)
|
| 276 |
+
assert mgf == 2*besseli(1, a*t)/(a*t)
|
| 277 |
+
|
| 278 |
+
# Numeric tests
|
| 279 |
+
|
| 280 |
+
mgf = moment_generating_function(Beta('x', 1, 1))(t)
|
| 281 |
+
assert mgf.diff(t).subs(t, 1) == hyper((2,), (3,), 1)/2
|
| 282 |
+
|
| 283 |
+
mgf = moment_generating_function(Chi('x', 1))(t)
|
| 284 |
+
assert mgf.diff(t).subs(t, 1) == sqrt(2)*hyper((1,), (Rational(3, 2),), S.Half
|
| 285 |
+
)/sqrt(pi) + hyper((Rational(3, 2),), (Rational(3, 2),), S.Half) + 2*sqrt(2)*hyper((2,),
|
| 286 |
+
(Rational(5, 2),), S.Half)/(3*sqrt(pi))
|
| 287 |
+
|
| 288 |
+
mgf = moment_generating_function(ChiSquared('x', 1))(t)
|
| 289 |
+
assert mgf.diff(t).subs(t, 1) == I
|
| 290 |
+
|
| 291 |
+
mgf = moment_generating_function(Erlang('x', 1, 1))(t)
|
| 292 |
+
assert mgf.diff(t).subs(t, 0) == 1
|
| 293 |
+
|
| 294 |
+
mgf = moment_generating_function(ExGaussian("x", 0, 1, 1))(t)
|
| 295 |
+
assert mgf.diff(t).subs(t, 2) == -exp(2)
|
| 296 |
+
|
| 297 |
+
mgf = moment_generating_function(Exponential('x', 1))(t)
|
| 298 |
+
assert mgf.diff(t).subs(t, 0) == 1
|
| 299 |
+
|
| 300 |
+
mgf = moment_generating_function(Gamma('x', 1, 1))(t)
|
| 301 |
+
assert mgf.diff(t).subs(t, 0) == 1
|
| 302 |
+
|
| 303 |
+
mgf = moment_generating_function(Gumbel('x', 1, 1))(t)
|
| 304 |
+
assert mgf.diff(t).subs(t, 0) == EulerGamma + 1
|
| 305 |
+
|
| 306 |
+
mgf = moment_generating_function(Gompertz('x', 1, 1))(t)
|
| 307 |
+
assert mgf.diff(t).subs(t, 1) == -e*meijerg(((), (1, 1)),
|
| 308 |
+
((0, 0, 0), ()), 1)
|
| 309 |
+
|
| 310 |
+
mgf = moment_generating_function(Laplace('x', 1, 1))(t)
|
| 311 |
+
assert mgf.diff(t).subs(t, 0) == 1
|
| 312 |
+
|
| 313 |
+
mgf = moment_generating_function(Logistic('x', 1, 1))(t)
|
| 314 |
+
assert mgf.diff(t).subs(t, 0) == beta(1, 1)
|
| 315 |
+
|
| 316 |
+
mgf = moment_generating_function(Normal('x', 0, 1))(t)
|
| 317 |
+
assert mgf.diff(t).subs(t, 1) == exp(S.Half)
|
| 318 |
+
|
| 319 |
+
mgf = moment_generating_function(Pareto('x', 1, 1))(t)
|
| 320 |
+
assert mgf.diff(t).subs(t, 0) == expint(1, 0)
|
| 321 |
+
|
| 322 |
+
mgf = moment_generating_function(QuadraticU('x', 1, 2))(t)
|
| 323 |
+
assert mgf.diff(t).subs(t, 1) == -12*e - 3*exp(2)
|
| 324 |
+
|
| 325 |
+
mgf = moment_generating_function(RaisedCosine('x', 1, 1))(t)
|
| 326 |
+
assert mgf.diff(t).subs(t, 1) == -2*e*pi**2*sinh(1)/\
|
| 327 |
+
(1 + pi**2)**2 + e*pi**2*cosh(1)/(1 + pi**2)
|
| 328 |
+
|
| 329 |
+
mgf = moment_generating_function(Rayleigh('x', 1))(t)
|
| 330 |
+
assert mgf.diff(t).subs(t, 0) == sqrt(2)*sqrt(pi)/2
|
| 331 |
+
|
| 332 |
+
mgf = moment_generating_function(Triangular('x', 1, 3, 2))(t)
|
| 333 |
+
assert mgf.diff(t).subs(t, 1) == -e + exp(3)
|
| 334 |
+
|
| 335 |
+
mgf = moment_generating_function(Uniform('x', 0, 1))(t)
|
| 336 |
+
assert mgf.diff(t).subs(t, 1) == 1
|
| 337 |
+
|
| 338 |
+
mgf = moment_generating_function(UniformSum('x', 1))(t)
|
| 339 |
+
assert mgf.diff(t).subs(t, 1) == 1
|
| 340 |
+
|
| 341 |
+
mgf = moment_generating_function(WignerSemicircle('x', 1))(t)
|
| 342 |
+
assert mgf.diff(t).subs(t, 1) == -2*besseli(1, 1) + besseli(2, 1) +\
|
| 343 |
+
besseli(0, 1)
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
def test_ContinuousRV():
|
| 347 |
+
pdf = sqrt(2)*exp(-x**2/2)/(2*sqrt(pi)) # Normal distribution
|
| 348 |
+
# X and Y should be equivalent
|
| 349 |
+
X = ContinuousRV(x, pdf, check=True)
|
| 350 |
+
Y = Normal('y', 0, 1)
|
| 351 |
+
|
| 352 |
+
assert variance(X) == variance(Y)
|
| 353 |
+
assert P(X > 0) == P(Y > 0)
|
| 354 |
+
Z = ContinuousRV(z, exp(-z), set=Interval(0, oo))
|
| 355 |
+
assert Z.pspace.domain.set == Interval(0, oo)
|
| 356 |
+
assert E(Z) == 1
|
| 357 |
+
assert P(Z > 5) == exp(-5)
|
| 358 |
+
raises(ValueError, lambda: ContinuousRV(z, exp(-z), set=Interval(0, 10), check=True))
|
| 359 |
+
|
| 360 |
+
# the correct pdf for Gamma(k, theta) but the integral in `check`
|
| 361 |
+
# integrates to something equivalent to 1 and not to 1 exactly
|
| 362 |
+
_x, k, theta = symbols("x k theta", positive=True)
|
| 363 |
+
pdf = 1/(gamma(k)*theta**k)*_x**(k-1)*exp(-_x/theta)
|
| 364 |
+
X = ContinuousRV(_x, pdf, set=Interval(0, oo))
|
| 365 |
+
Y = Gamma('y', k, theta)
|
| 366 |
+
assert (E(X) - E(Y)).simplify() == 0
|
| 367 |
+
assert (variance(X) - variance(Y)).simplify() == 0
|
| 368 |
+
|
| 369 |
+
|
| 370 |
+
def test_arcsin():
|
| 371 |
+
|
| 372 |
+
a = Symbol("a", real=True)
|
| 373 |
+
b = Symbol("b", real=True)
|
| 374 |
+
|
| 375 |
+
X = Arcsin('x', a, b)
|
| 376 |
+
assert density(X)(x) == 1/(pi*sqrt((-x + b)*(x - a)))
|
| 377 |
+
assert cdf(X)(x) == Piecewise((0, a > x),
|
| 378 |
+
(2*asin(sqrt((-a + x)/(-a + b)))/pi, b >= x),
|
| 379 |
+
(1, True))
|
| 380 |
+
assert pspace(X).domain.set == Interval(a, b)
|
| 381 |
+
|
| 382 |
+
def test_benini():
|
| 383 |
+
alpha = Symbol("alpha", positive=True)
|
| 384 |
+
beta = Symbol("beta", positive=True)
|
| 385 |
+
sigma = Symbol("sigma", positive=True)
|
| 386 |
+
X = Benini('x', alpha, beta, sigma)
|
| 387 |
+
|
| 388 |
+
assert density(X)(x) == ((alpha/x + 2*beta*log(x/sigma)/x)
|
| 389 |
+
*exp(-alpha*log(x/sigma) - beta*log(x/sigma)**2))
|
| 390 |
+
|
| 391 |
+
assert pspace(X).domain.set == Interval(sigma, oo)
|
| 392 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 393 |
+
alpha = Symbol("alpha", nonpositive=True)
|
| 394 |
+
raises(ValueError, lambda: Benini('x', alpha, beta, sigma))
|
| 395 |
+
|
| 396 |
+
beta = Symbol("beta", nonpositive=True)
|
| 397 |
+
raises(ValueError, lambda: Benini('x', alpha, beta, sigma))
|
| 398 |
+
|
| 399 |
+
alpha = Symbol("alpha", positive=True)
|
| 400 |
+
raises(ValueError, lambda: Benini('x', alpha, beta, sigma))
|
| 401 |
+
|
| 402 |
+
beta = Symbol("beta", positive=True)
|
| 403 |
+
sigma = Symbol("sigma", nonpositive=True)
|
| 404 |
+
raises(ValueError, lambda: Benini('x', alpha, beta, sigma))
|
| 405 |
+
|
| 406 |
+
def test_beta():
|
| 407 |
+
a, b = symbols('alpha beta', positive=True)
|
| 408 |
+
B = Beta('x', a, b)
|
| 409 |
+
|
| 410 |
+
assert pspace(B).domain.set == Interval(0, 1)
|
| 411 |
+
assert characteristic_function(B)(x) == hyper((a,), (a + b,), I*x)
|
| 412 |
+
assert density(B)(x) == x**(a - 1)*(1 - x)**(b - 1)/beta(a, b)
|
| 413 |
+
|
| 414 |
+
assert simplify(E(B)) == a / (a + b)
|
| 415 |
+
assert simplify(variance(B)) == a*b / (a**3 + 3*a**2*b + a**2 + 3*a*b**2 + 2*a*b + b**3 + b**2)
|
| 416 |
+
|
| 417 |
+
# Full symbolic solution is too much, test with numeric version
|
| 418 |
+
a, b = 1, 2
|
| 419 |
+
B = Beta('x', a, b)
|
| 420 |
+
assert expand_func(E(B)) == a / S(a + b)
|
| 421 |
+
assert expand_func(variance(B)) == (a*b) / S((a + b)**2 * (a + b + 1))
|
| 422 |
+
assert median(B) == FiniteSet(1 - 1/sqrt(2))
|
| 423 |
+
|
| 424 |
+
def test_beta_noncentral():
|
| 425 |
+
a, b = symbols('a b', positive=True)
|
| 426 |
+
c = Symbol('c', nonnegative=True)
|
| 427 |
+
_k = Dummy('k')
|
| 428 |
+
|
| 429 |
+
X = BetaNoncentral('x', a, b, c)
|
| 430 |
+
|
| 431 |
+
assert pspace(X).domain.set == Interval(0, 1)
|
| 432 |
+
|
| 433 |
+
dens = density(X)
|
| 434 |
+
z = Symbol('z')
|
| 435 |
+
|
| 436 |
+
res = Sum( z**(_k + a - 1)*(c/2)**_k*(1 - z)**(b - 1)*exp(-c/2)/
|
| 437 |
+
(beta(_k + a, b)*factorial(_k)), (_k, 0, oo))
|
| 438 |
+
assert dens(z).dummy_eq(res)
|
| 439 |
+
|
| 440 |
+
# BetaCentral should not raise if the assumptions
|
| 441 |
+
# on the symbols can not be determined
|
| 442 |
+
a, b, c = symbols('a b c')
|
| 443 |
+
assert BetaNoncentral('x', a, b, c)
|
| 444 |
+
|
| 445 |
+
a = Symbol('a', positive=False, real=True)
|
| 446 |
+
raises(ValueError, lambda: BetaNoncentral('x', a, b, c))
|
| 447 |
+
|
| 448 |
+
a = Symbol('a', positive=True)
|
| 449 |
+
b = Symbol('b', positive=False, real=True)
|
| 450 |
+
raises(ValueError, lambda: BetaNoncentral('x', a, b, c))
|
| 451 |
+
|
| 452 |
+
a = Symbol('a', positive=True)
|
| 453 |
+
b = Symbol('b', positive=True)
|
| 454 |
+
c = Symbol('c', nonnegative=False, real=True)
|
| 455 |
+
raises(ValueError, lambda: BetaNoncentral('x', a, b, c))
|
| 456 |
+
|
| 457 |
+
def test_betaprime():
|
| 458 |
+
alpha = Symbol("alpha", positive=True)
|
| 459 |
+
|
| 460 |
+
betap = Symbol("beta", positive=True)
|
| 461 |
+
|
| 462 |
+
X = BetaPrime('x', alpha, betap)
|
| 463 |
+
assert density(X)(x) == x**(alpha - 1)*(x + 1)**(-alpha - betap)/beta(alpha, betap)
|
| 464 |
+
|
| 465 |
+
alpha = Symbol("alpha", nonpositive=True)
|
| 466 |
+
raises(ValueError, lambda: BetaPrime('x', alpha, betap))
|
| 467 |
+
|
| 468 |
+
alpha = Symbol("alpha", positive=True)
|
| 469 |
+
betap = Symbol("beta", nonpositive=True)
|
| 470 |
+
raises(ValueError, lambda: BetaPrime('x', alpha, betap))
|
| 471 |
+
X = BetaPrime('x', 1, 1)
|
| 472 |
+
assert median(X) == FiniteSet(1)
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
def test_BoundedPareto():
|
| 476 |
+
L, H = symbols('L, H', negative=True)
|
| 477 |
+
raises(ValueError, lambda: BoundedPareto('X', 1, L, H))
|
| 478 |
+
L, H = symbols('L, H', real=False)
|
| 479 |
+
raises(ValueError, lambda: BoundedPareto('X', 1, L, H))
|
| 480 |
+
L, H = symbols('L, H', positive=True)
|
| 481 |
+
raises(ValueError, lambda: BoundedPareto('X', -1, L, H))
|
| 482 |
+
|
| 483 |
+
X = BoundedPareto('X', 2, L, H)
|
| 484 |
+
assert X.pspace.domain.set == Interval(L, H)
|
| 485 |
+
assert density(X)(x) == 2*L**2/(x**3*(1 - L**2/H**2))
|
| 486 |
+
assert cdf(X)(x) == Piecewise((-H**2*L**2/(x**2*(H**2 - L**2)) \
|
| 487 |
+
+ H**2/(H**2 - L**2), L <= x), (0, True))
|
| 488 |
+
assert E(X).simplify() == 2*H*L/(H + L)
|
| 489 |
+
X = BoundedPareto('X', 1, 2, 4)
|
| 490 |
+
assert E(X).simplify() == log(16)
|
| 491 |
+
assert median(X) == FiniteSet(Rational(8, 3))
|
| 492 |
+
assert variance(X).simplify() == 8 - 16*log(2)**2
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
def test_cauchy():
|
| 496 |
+
x0 = Symbol("x0", real=True)
|
| 497 |
+
gamma = Symbol("gamma", positive=True)
|
| 498 |
+
p = Symbol("p", positive=True)
|
| 499 |
+
|
| 500 |
+
X = Cauchy('x', x0, gamma)
|
| 501 |
+
# Tests the characteristic function
|
| 502 |
+
assert characteristic_function(X)(x) == exp(-gamma*Abs(x) + I*x*x0)
|
| 503 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 504 |
+
assert density(X)(x) == 1/(pi*gamma*(1 + (x - x0)**2/gamma**2))
|
| 505 |
+
assert diff(cdf(X)(x), x) == density(X)(x)
|
| 506 |
+
assert quantile(X)(p) == gamma*tan(pi*(p - S.Half)) + x0
|
| 507 |
+
|
| 508 |
+
x1 = Symbol("x1", real=False)
|
| 509 |
+
raises(ValueError, lambda: Cauchy('x', x1, gamma))
|
| 510 |
+
gamma = Symbol("gamma", nonpositive=True)
|
| 511 |
+
raises(ValueError, lambda: Cauchy('x', x0, gamma))
|
| 512 |
+
assert median(X) == FiniteSet(x0)
|
| 513 |
+
|
| 514 |
+
def test_chi():
|
| 515 |
+
from sympy.core.numbers import I
|
| 516 |
+
k = Symbol("k", integer=True)
|
| 517 |
+
|
| 518 |
+
X = Chi('x', k)
|
| 519 |
+
assert density(X)(x) == 2**(-k/2 + 1)*x**(k - 1)*exp(-x**2/2)/gamma(k/2)
|
| 520 |
+
|
| 521 |
+
# Tests the characteristic function
|
| 522 |
+
assert characteristic_function(X)(x) == sqrt(2)*I*x*gamma(k/2 + S(1)/2)*hyper((k/2 + S(1)/2,),
|
| 523 |
+
(S(3)/2,), -x**2/2)/gamma(k/2) + hyper((k/2,), (S(1)/2,), -x**2/2)
|
| 524 |
+
|
| 525 |
+
# Tests the moment generating function
|
| 526 |
+
assert moment_generating_function(X)(x) == sqrt(2)*x*gamma(k/2 + S(1)/2)*hyper((k/2 + S(1)/2,),
|
| 527 |
+
(S(3)/2,), x**2/2)/gamma(k/2) + hyper((k/2,), (S(1)/2,), x**2/2)
|
| 528 |
+
|
| 529 |
+
k = Symbol("k", integer=True, positive=False)
|
| 530 |
+
raises(ValueError, lambda: Chi('x', k))
|
| 531 |
+
|
| 532 |
+
k = Symbol("k", integer=False, positive=True)
|
| 533 |
+
raises(ValueError, lambda: Chi('x', k))
|
| 534 |
+
|
| 535 |
+
def test_chi_noncentral():
|
| 536 |
+
k = Symbol("k", integer=True)
|
| 537 |
+
l = Symbol("l")
|
| 538 |
+
|
| 539 |
+
X = ChiNoncentral("x", k, l)
|
| 540 |
+
assert density(X)(x) == (x**k*l*(x*l)**(-k/2)*
|
| 541 |
+
exp(-x**2/2 - l**2/2)*besseli(k/2 - 1, x*l))
|
| 542 |
+
|
| 543 |
+
k = Symbol("k", integer=True, positive=False)
|
| 544 |
+
raises(ValueError, lambda: ChiNoncentral('x', k, l))
|
| 545 |
+
|
| 546 |
+
k = Symbol("k", integer=True, positive=True)
|
| 547 |
+
l = Symbol("l", nonpositive=True)
|
| 548 |
+
raises(ValueError, lambda: ChiNoncentral('x', k, l))
|
| 549 |
+
|
| 550 |
+
k = Symbol("k", integer=False)
|
| 551 |
+
l = Symbol("l", positive=True)
|
| 552 |
+
raises(ValueError, lambda: ChiNoncentral('x', k, l))
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
def test_chi_squared():
|
| 556 |
+
k = Symbol("k", integer=True)
|
| 557 |
+
X = ChiSquared('x', k)
|
| 558 |
+
|
| 559 |
+
# Tests the characteristic function
|
| 560 |
+
assert characteristic_function(X)(x) == ((-2*I*x + 1)**(-k/2))
|
| 561 |
+
|
| 562 |
+
assert density(X)(x) == 2**(-k/2)*x**(k/2 - 1)*exp(-x/2)/gamma(k/2)
|
| 563 |
+
assert cdf(X)(x) == Piecewise((lowergamma(k/2, x/2)/gamma(k/2), x >= 0), (0, True))
|
| 564 |
+
assert E(X) == k
|
| 565 |
+
assert variance(X) == 2*k
|
| 566 |
+
|
| 567 |
+
X = ChiSquared('x', 15)
|
| 568 |
+
assert cdf(X)(3) == -14873*sqrt(6)*exp(Rational(-3, 2))/(5005*sqrt(pi)) + erf(sqrt(6)/2)
|
| 569 |
+
|
| 570 |
+
k = Symbol("k", integer=True, positive=False)
|
| 571 |
+
raises(ValueError, lambda: ChiSquared('x', k))
|
| 572 |
+
|
| 573 |
+
k = Symbol("k", integer=False, positive=True)
|
| 574 |
+
raises(ValueError, lambda: ChiSquared('x', k))
|
| 575 |
+
|
| 576 |
+
|
| 577 |
+
def test_dagum():
|
| 578 |
+
p = Symbol("p", positive=True)
|
| 579 |
+
b = Symbol("b", positive=True)
|
| 580 |
+
a = Symbol("a", positive=True)
|
| 581 |
+
|
| 582 |
+
X = Dagum('x', p, a, b)
|
| 583 |
+
assert density(X)(x) == a*p*(x/b)**(a*p)*((x/b)**a + 1)**(-p - 1)/x
|
| 584 |
+
assert cdf(X)(x) == Piecewise(((1 + (x/b)**(-a))**(-p), x >= 0),
|
| 585 |
+
(0, True))
|
| 586 |
+
|
| 587 |
+
p = Symbol("p", nonpositive=True)
|
| 588 |
+
raises(ValueError, lambda: Dagum('x', p, a, b))
|
| 589 |
+
|
| 590 |
+
p = Symbol("p", positive=True)
|
| 591 |
+
b = Symbol("b", nonpositive=True)
|
| 592 |
+
raises(ValueError, lambda: Dagum('x', p, a, b))
|
| 593 |
+
|
| 594 |
+
b = Symbol("b", positive=True)
|
| 595 |
+
a = Symbol("a", nonpositive=True)
|
| 596 |
+
raises(ValueError, lambda: Dagum('x', p, a, b))
|
| 597 |
+
X = Dagum('x', 1, 1, 1)
|
| 598 |
+
assert median(X) == FiniteSet(1)
|
| 599 |
+
|
| 600 |
+
def test_davis():
|
| 601 |
+
b = Symbol("b", positive=True)
|
| 602 |
+
n = Symbol("n", positive=True)
|
| 603 |
+
mu = Symbol("mu", positive=True)
|
| 604 |
+
|
| 605 |
+
X = Davis('x', b, n, mu)
|
| 606 |
+
dividend = b**n*(x - mu)**(-1-n)
|
| 607 |
+
divisor = (exp(b/(x-mu))-1)*(gamma(n)*zeta(n))
|
| 608 |
+
assert density(X)(x) == dividend/divisor
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
def test_erlang():
|
| 612 |
+
k = Symbol("k", integer=True, positive=True)
|
| 613 |
+
l = Symbol("l", positive=True)
|
| 614 |
+
|
| 615 |
+
X = Erlang("x", k, l)
|
| 616 |
+
assert density(X)(x) == x**(k - 1)*l**k*exp(-x*l)/gamma(k)
|
| 617 |
+
assert cdf(X)(x) == Piecewise((lowergamma(k, l*x)/gamma(k), x > 0),
|
| 618 |
+
(0, True))
|
| 619 |
+
|
| 620 |
+
|
| 621 |
+
def test_exgaussian():
|
| 622 |
+
m, z = symbols("m, z")
|
| 623 |
+
s, l = symbols("s, l", positive=True)
|
| 624 |
+
X = ExGaussian("x", m, s, l)
|
| 625 |
+
|
| 626 |
+
assert density(X)(z) == l*exp(l*(l*s**2 + 2*m - 2*z)/2) *\
|
| 627 |
+
erfc(sqrt(2)*(l*s**2 + m - z)/(2*s))/2
|
| 628 |
+
|
| 629 |
+
# Note: actual_output simplifies to expected_output.
|
| 630 |
+
# Ideally cdf(X)(z) would return expected_output
|
| 631 |
+
# expected_output = (erf(sqrt(2)*(l*s**2 + m - z)/(2*s)) - 1)*exp(l*(l*s**2 + 2*m - 2*z)/2)/2 - erf(sqrt(2)*(m - z)/(2*s))/2 + S.Half
|
| 632 |
+
u = l*(z - m)
|
| 633 |
+
v = l*s
|
| 634 |
+
GaussianCDF1 = cdf(Normal('x', 0, v))(u)
|
| 635 |
+
GaussianCDF2 = cdf(Normal('x', v**2, v))(u)
|
| 636 |
+
actual_output = GaussianCDF1 - exp(-u + (v**2/2) + log(GaussianCDF2))
|
| 637 |
+
assert cdf(X)(z) == actual_output
|
| 638 |
+
# assert simplify(actual_output) == expected_output
|
| 639 |
+
|
| 640 |
+
assert variance(X).expand() == s**2 + l**(-2)
|
| 641 |
+
|
| 642 |
+
assert skewness(X).expand() == 2/(l**3*s**2*sqrt(s**2 + l**(-2)) + l *
|
| 643 |
+
sqrt(s**2 + l**(-2)))
|
| 644 |
+
|
| 645 |
+
|
| 646 |
+
@slow
|
| 647 |
+
def test_exponential():
|
| 648 |
+
rate = Symbol('lambda', positive=True)
|
| 649 |
+
X = Exponential('x', rate)
|
| 650 |
+
p = Symbol("p", positive=True, real=True)
|
| 651 |
+
|
| 652 |
+
assert E(X) == 1/rate
|
| 653 |
+
assert variance(X) == 1/rate**2
|
| 654 |
+
assert skewness(X) == 2
|
| 655 |
+
assert skewness(X) == smoment(X, 3)
|
| 656 |
+
assert kurtosis(X) == 9
|
| 657 |
+
assert kurtosis(X) == smoment(X, 4)
|
| 658 |
+
assert smoment(2*X, 4) == smoment(X, 4)
|
| 659 |
+
assert moment(X, 3) == 3*2*1/rate**3
|
| 660 |
+
assert P(X > 0) is S.One
|
| 661 |
+
assert P(X > 1) == exp(-rate)
|
| 662 |
+
assert P(X > 10) == exp(-10*rate)
|
| 663 |
+
assert quantile(X)(p) == -log(1-p)/rate
|
| 664 |
+
|
| 665 |
+
assert where(X <= 1).set == Interval(0, 1)
|
| 666 |
+
Y = Exponential('y', 1)
|
| 667 |
+
assert median(Y) == FiniteSet(log(2))
|
| 668 |
+
#Test issue 9970
|
| 669 |
+
z = Dummy('z')
|
| 670 |
+
assert P(X > z) == exp(-z*rate)
|
| 671 |
+
assert P(X < z) == 0
|
| 672 |
+
#Test issue 10076 (Distribution with interval(0,oo))
|
| 673 |
+
x = Symbol('x')
|
| 674 |
+
_z = Dummy('_z')
|
| 675 |
+
b = SingleContinuousPSpace(x, ExponentialDistribution(2))
|
| 676 |
+
|
| 677 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 678 |
+
expected1 = Integral(2*exp(-2*_z), (_z, 3, oo))
|
| 679 |
+
assert b.probability(x > 3, evaluate=False).rewrite(Integral).dummy_eq(expected1)
|
| 680 |
+
|
| 681 |
+
expected2 = Integral(2*exp(-2*_z), (_z, 0, 4))
|
| 682 |
+
assert b.probability(x < 4, evaluate=False).rewrite(Integral).dummy_eq(expected2)
|
| 683 |
+
Y = Exponential('y', 2*rate)
|
| 684 |
+
assert coskewness(X, X, X) == skewness(X)
|
| 685 |
+
assert coskewness(X, Y + rate*X, Y + 2*rate*X) == \
|
| 686 |
+
4/(sqrt(1 + 1/(4*rate**2))*sqrt(4 + 1/(4*rate**2)))
|
| 687 |
+
assert coskewness(X + 2*Y, Y + X, Y + 2*X, X > 3) == \
|
| 688 |
+
sqrt(170)*Rational(9, 85)
|
| 689 |
+
|
| 690 |
+
def test_exponential_power():
|
| 691 |
+
mu = Symbol('mu')
|
| 692 |
+
z = Symbol('z')
|
| 693 |
+
alpha = Symbol('alpha', positive=True)
|
| 694 |
+
beta = Symbol('beta', positive=True)
|
| 695 |
+
|
| 696 |
+
X = ExponentialPower('x', mu, alpha, beta)
|
| 697 |
+
|
| 698 |
+
assert density(X)(z) == beta*exp(-(Abs(mu - z)/alpha)
|
| 699 |
+
** beta)/(2*alpha*gamma(1/beta))
|
| 700 |
+
assert cdf(X)(z) == S.Half + lowergamma(1/beta,
|
| 701 |
+
(Abs(mu - z)/alpha)**beta)*sign(-mu + z)/\
|
| 702 |
+
(2*gamma(1/beta))
|
| 703 |
+
|
| 704 |
+
|
| 705 |
+
def test_f_distribution():
|
| 706 |
+
d1 = Symbol("d1", positive=True)
|
| 707 |
+
d2 = Symbol("d2", positive=True)
|
| 708 |
+
|
| 709 |
+
X = FDistribution("x", d1, d2)
|
| 710 |
+
|
| 711 |
+
assert density(X)(x) == (d2**(d2/2)*sqrt((d1*x)**d1*(d1*x + d2)**(-d1 - d2))
|
| 712 |
+
/(x*beta(d1/2, d2/2)))
|
| 713 |
+
|
| 714 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 715 |
+
d1 = Symbol("d1", nonpositive=True)
|
| 716 |
+
raises(ValueError, lambda: FDistribution('x', d1, d1))
|
| 717 |
+
|
| 718 |
+
d1 = Symbol("d1", positive=True, integer=False)
|
| 719 |
+
raises(ValueError, lambda: FDistribution('x', d1, d1))
|
| 720 |
+
|
| 721 |
+
d1 = Symbol("d1", positive=True)
|
| 722 |
+
d2 = Symbol("d2", nonpositive=True)
|
| 723 |
+
raises(ValueError, lambda: FDistribution('x', d1, d2))
|
| 724 |
+
|
| 725 |
+
d2 = Symbol("d2", positive=True, integer=False)
|
| 726 |
+
raises(ValueError, lambda: FDistribution('x', d1, d2))
|
| 727 |
+
|
| 728 |
+
|
| 729 |
+
def test_fisher_z():
|
| 730 |
+
d1 = Symbol("d1", positive=True)
|
| 731 |
+
d2 = Symbol("d2", positive=True)
|
| 732 |
+
|
| 733 |
+
X = FisherZ("x", d1, d2)
|
| 734 |
+
assert density(X)(x) == (2*d1**(d1/2)*d2**(d2/2)*(d1*exp(2*x) + d2)
|
| 735 |
+
**(-d1/2 - d2/2)*exp(d1*x)/beta(d1/2, d2/2))
|
| 736 |
+
|
| 737 |
+
def test_frechet():
|
| 738 |
+
a = Symbol("a", positive=True)
|
| 739 |
+
s = Symbol("s", positive=True)
|
| 740 |
+
m = Symbol("m", real=True)
|
| 741 |
+
|
| 742 |
+
X = Frechet("x", a, s=s, m=m)
|
| 743 |
+
assert density(X)(x) == a*((x - m)/s)**(-a - 1)*exp(-((x - m)/s)**(-a))/s
|
| 744 |
+
assert cdf(X)(x) == Piecewise((exp(-((-m + x)/s)**(-a)), m <= x), (0, True))
|
| 745 |
+
|
| 746 |
+
@slow
|
| 747 |
+
def test_gamma():
|
| 748 |
+
k = Symbol("k", positive=True)
|
| 749 |
+
theta = Symbol("theta", positive=True)
|
| 750 |
+
|
| 751 |
+
X = Gamma('x', k, theta)
|
| 752 |
+
|
| 753 |
+
# Tests characteristic function
|
| 754 |
+
assert characteristic_function(X)(x) == ((-I*theta*x + 1)**(-k))
|
| 755 |
+
|
| 756 |
+
assert density(X)(x) == x**(k - 1)*theta**(-k)*exp(-x/theta)/gamma(k)
|
| 757 |
+
assert cdf(X, meijerg=True)(z) == Piecewise(
|
| 758 |
+
(-k*lowergamma(k, 0)/gamma(k + 1) +
|
| 759 |
+
k*lowergamma(k, z/theta)/gamma(k + 1), z >= 0),
|
| 760 |
+
(0, True))
|
| 761 |
+
|
| 762 |
+
# assert simplify(variance(X)) == k*theta**2 # handled numerically below
|
| 763 |
+
assert E(X) == moment(X, 1)
|
| 764 |
+
|
| 765 |
+
k, theta = symbols('k theta', positive=True)
|
| 766 |
+
X = Gamma('x', k, theta)
|
| 767 |
+
assert E(X) == k*theta
|
| 768 |
+
assert variance(X) == k*theta**2
|
| 769 |
+
assert skewness(X).expand() == 2/sqrt(k)
|
| 770 |
+
assert kurtosis(X).expand() == 3 + 6/k
|
| 771 |
+
|
| 772 |
+
Y = Gamma('y', 2*k, 3*theta)
|
| 773 |
+
assert coskewness(X, theta*X + Y, k*X + Y).simplify() == \
|
| 774 |
+
2*531441**(-k)*sqrt(k)*theta*(3*3**(12*k) - 2*531441**k) \
|
| 775 |
+
/(sqrt(k**2 + 18)*sqrt(theta**2 + 18))
|
| 776 |
+
|
| 777 |
+
def test_gamma_inverse():
|
| 778 |
+
a = Symbol("a", positive=True)
|
| 779 |
+
b = Symbol("b", positive=True)
|
| 780 |
+
X = GammaInverse("x", a, b)
|
| 781 |
+
assert density(X)(x) == x**(-a - 1)*b**a*exp(-b/x)/gamma(a)
|
| 782 |
+
assert cdf(X)(x) == Piecewise((uppergamma(a, b/x)/gamma(a), x > 0), (0, True))
|
| 783 |
+
assert characteristic_function(X)(x) == 2 * (-I*b*x)**(a/2) \
|
| 784 |
+
* besselk(a, 2*sqrt(b)*sqrt(-I*x))/gamma(a)
|
| 785 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 786 |
+
|
| 787 |
+
def test_gompertz():
|
| 788 |
+
b = Symbol("b", positive=True)
|
| 789 |
+
eta = Symbol("eta", positive=True)
|
| 790 |
+
|
| 791 |
+
X = Gompertz("x", b, eta)
|
| 792 |
+
|
| 793 |
+
assert density(X)(x) == b*eta*exp(eta)*exp(b*x)*exp(-eta*exp(b*x))
|
| 794 |
+
assert cdf(X)(x) == 1 - exp(eta)*exp(-eta*exp(b*x))
|
| 795 |
+
assert diff(cdf(X)(x), x) == density(X)(x)
|
| 796 |
+
|
| 797 |
+
|
| 798 |
+
def test_gumbel():
|
| 799 |
+
beta = Symbol("beta", positive=True)
|
| 800 |
+
mu = Symbol("mu")
|
| 801 |
+
x = Symbol("x")
|
| 802 |
+
y = Symbol("y")
|
| 803 |
+
X = Gumbel("x", beta, mu)
|
| 804 |
+
Y = Gumbel("y", beta, mu, minimum=True)
|
| 805 |
+
assert density(X)(x).expand() == \
|
| 806 |
+
exp(mu/beta)*exp(-x/beta)*exp(-exp(mu/beta)*exp(-x/beta))/beta
|
| 807 |
+
assert density(Y)(y).expand() == \
|
| 808 |
+
exp(-mu/beta)*exp(y/beta)*exp(-exp(-mu/beta)*exp(y/beta))/beta
|
| 809 |
+
assert cdf(X)(x).expand() == \
|
| 810 |
+
exp(-exp(mu/beta)*exp(-x/beta))
|
| 811 |
+
assert characteristic_function(X)(x) == exp(I*mu*x)*gamma(-I*beta*x + 1)
|
| 812 |
+
|
| 813 |
+
def test_kumaraswamy():
|
| 814 |
+
a = Symbol("a", positive=True)
|
| 815 |
+
b = Symbol("b", positive=True)
|
| 816 |
+
|
| 817 |
+
X = Kumaraswamy("x", a, b)
|
| 818 |
+
assert density(X)(x) == x**(a - 1)*a*b*(-x**a + 1)**(b - 1)
|
| 819 |
+
assert cdf(X)(x) == Piecewise((0, x < 0),
|
| 820 |
+
(-(-x**a + 1)**b + 1, x <= 1),
|
| 821 |
+
(1, True))
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
def test_laplace():
|
| 825 |
+
mu = Symbol("mu")
|
| 826 |
+
b = Symbol("b", positive=True)
|
| 827 |
+
|
| 828 |
+
X = Laplace('x', mu, b)
|
| 829 |
+
|
| 830 |
+
#Tests characteristic_function
|
| 831 |
+
assert characteristic_function(X)(x) == (exp(I*mu*x)/(b**2*x**2 + 1))
|
| 832 |
+
|
| 833 |
+
assert density(X)(x) == exp(-Abs(x - mu)/b)/(2*b)
|
| 834 |
+
assert cdf(X)(x) == Piecewise((exp((-mu + x)/b)/2, mu > x),
|
| 835 |
+
(-exp((mu - x)/b)/2 + 1, True))
|
| 836 |
+
X = Laplace('x', [1, 2], [[1, 0], [0, 1]])
|
| 837 |
+
assert isinstance(pspace(X).distribution, MultivariateLaplaceDistribution)
|
| 838 |
+
|
| 839 |
+
def test_levy():
|
| 840 |
+
mu = Symbol("mu", real=True)
|
| 841 |
+
c = Symbol("c", positive=True)
|
| 842 |
+
|
| 843 |
+
X = Levy('x', mu, c)
|
| 844 |
+
assert X.pspace.domain.set == Interval(mu, oo)
|
| 845 |
+
assert density(X)(x) == sqrt(c/(2*pi))*exp(-c/(2*(x - mu)))/((x - mu)**(S.One + S.Half))
|
| 846 |
+
assert cdf(X)(x) == erfc(sqrt(c/(2*(x - mu))))
|
| 847 |
+
|
| 848 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 849 |
+
mu = Symbol("mu", real=False)
|
| 850 |
+
raises(ValueError, lambda: Levy('x',mu,c))
|
| 851 |
+
|
| 852 |
+
c = Symbol("c", nonpositive=True)
|
| 853 |
+
raises(ValueError, lambda: Levy('x',mu,c))
|
| 854 |
+
|
| 855 |
+
mu = Symbol("mu", real=True)
|
| 856 |
+
raises(ValueError, lambda: Levy('x',mu,c))
|
| 857 |
+
|
| 858 |
+
def test_logcauchy():
|
| 859 |
+
mu = Symbol("mu", positive=True)
|
| 860 |
+
sigma = Symbol("sigma", positive=True)
|
| 861 |
+
|
| 862 |
+
X = LogCauchy("x", mu, sigma)
|
| 863 |
+
|
| 864 |
+
assert density(X)(x) == sigma/(x*pi*(sigma**2 + (-mu + log(x))**2))
|
| 865 |
+
assert cdf(X)(x) == atan((log(x) - mu)/sigma)/pi + S.Half
|
| 866 |
+
|
| 867 |
+
|
| 868 |
+
def test_logistic():
|
| 869 |
+
mu = Symbol("mu", real=True)
|
| 870 |
+
s = Symbol("s", positive=True)
|
| 871 |
+
p = Symbol("p", positive=True)
|
| 872 |
+
|
| 873 |
+
X = Logistic('x', mu, s)
|
| 874 |
+
|
| 875 |
+
#Tests characteristics_function
|
| 876 |
+
assert characteristic_function(X)(x) == \
|
| 877 |
+
(Piecewise((pi*s*x*exp(I*mu*x)/sinh(pi*s*x), Ne(x, 0)), (1, True)))
|
| 878 |
+
|
| 879 |
+
assert density(X)(x) == exp((-x + mu)/s)/(s*(exp((-x + mu)/s) + 1)**2)
|
| 880 |
+
assert cdf(X)(x) == 1/(exp((mu - x)/s) + 1)
|
| 881 |
+
assert quantile(X)(p) == mu - s*log(-S.One + 1/p)
|
| 882 |
+
|
| 883 |
+
def test_loglogistic():
|
| 884 |
+
a, b = symbols('a b')
|
| 885 |
+
assert LogLogistic('x', a, b)
|
| 886 |
+
|
| 887 |
+
a = Symbol('a', negative=True)
|
| 888 |
+
b = Symbol('b', positive=True)
|
| 889 |
+
raises(ValueError, lambda: LogLogistic('x', a, b))
|
| 890 |
+
|
| 891 |
+
a = Symbol('a', positive=True)
|
| 892 |
+
b = Symbol('b', negative=True)
|
| 893 |
+
raises(ValueError, lambda: LogLogistic('x', a, b))
|
| 894 |
+
|
| 895 |
+
a, b, z, p = symbols('a b z p', positive=True)
|
| 896 |
+
X = LogLogistic('x', a, b)
|
| 897 |
+
assert density(X)(z) == b*(z/a)**(b - 1)/(a*((z/a)**b + 1)**2)
|
| 898 |
+
assert cdf(X)(z) == 1/(1 + (z/a)**(-b))
|
| 899 |
+
assert quantile(X)(p) == a*(p/(1 - p))**(1/b)
|
| 900 |
+
|
| 901 |
+
# Expectation
|
| 902 |
+
assert E(X) == Piecewise((S.NaN, b <= 1), (pi*a/(b*sin(pi/b)), True))
|
| 903 |
+
b = symbols('b', prime=True) # b > 1
|
| 904 |
+
X = LogLogistic('x', a, b)
|
| 905 |
+
assert E(X) == pi*a/(b*sin(pi/b))
|
| 906 |
+
X = LogLogistic('x', 1, 2)
|
| 907 |
+
assert median(X) == FiniteSet(1)
|
| 908 |
+
|
| 909 |
+
def test_logitnormal():
|
| 910 |
+
mu = Symbol('mu', real=True)
|
| 911 |
+
s = Symbol('s', positive=True)
|
| 912 |
+
X = LogitNormal('x', mu, s)
|
| 913 |
+
x = Symbol('x')
|
| 914 |
+
|
| 915 |
+
assert density(X)(x) == sqrt(2)*exp(-(-mu + log(x/(1 - x)))**2/(2*s**2))/(2*sqrt(pi)*s*x*(1 - x))
|
| 916 |
+
assert cdf(X)(x) == erf(sqrt(2)*(-mu + log(x/(1 - x)))/(2*s))/2 + S(1)/2
|
| 917 |
+
|
| 918 |
+
def test_lognormal():
|
| 919 |
+
mean = Symbol('mu', real=True)
|
| 920 |
+
std = Symbol('sigma', positive=True)
|
| 921 |
+
X = LogNormal('x', mean, std)
|
| 922 |
+
# The sympy integrator can't do this too well
|
| 923 |
+
#assert E(X) == exp(mean+std**2/2)
|
| 924 |
+
#assert variance(X) == (exp(std**2)-1) * exp(2*mean + std**2)
|
| 925 |
+
|
| 926 |
+
# The sympy integrator can't do this too well
|
| 927 |
+
#assert E(X) ==
|
| 928 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 929 |
+
mu = Symbol("mu", real=True)
|
| 930 |
+
sigma = Symbol("sigma", positive=True)
|
| 931 |
+
|
| 932 |
+
X = LogNormal('x', mu, sigma)
|
| 933 |
+
assert density(X)(x) == (sqrt(2)*exp(-(-mu + log(x))**2
|
| 934 |
+
/(2*sigma**2))/(2*x*sqrt(pi)*sigma))
|
| 935 |
+
# Tests cdf
|
| 936 |
+
assert cdf(X)(x) == Piecewise(
|
| 937 |
+
(erf(sqrt(2)*(-mu + log(x))/(2*sigma))/2
|
| 938 |
+
+ S(1)/2, x > 0), (0, True))
|
| 939 |
+
|
| 940 |
+
X = LogNormal('x', 0, 1) # Mean 0, standard deviation 1
|
| 941 |
+
assert density(X)(x) == sqrt(2)*exp(-log(x)**2/2)/(2*x*sqrt(pi))
|
| 942 |
+
|
| 943 |
+
|
| 944 |
+
def test_Lomax():
|
| 945 |
+
a, l = symbols('a, l', negative=True)
|
| 946 |
+
raises(ValueError, lambda: Lomax('X', a, l))
|
| 947 |
+
a, l = symbols('a, l', real=False)
|
| 948 |
+
raises(ValueError, lambda: Lomax('X', a, l))
|
| 949 |
+
|
| 950 |
+
a, l = symbols('a, l', positive=True)
|
| 951 |
+
X = Lomax('X', a, l)
|
| 952 |
+
assert X.pspace.domain.set == Interval(0, oo)
|
| 953 |
+
assert density(X)(x) == a*(1 + x/l)**(-a - 1)/l
|
| 954 |
+
assert cdf(X)(x) == Piecewise((1 - (1 + x/l)**(-a), x >= 0), (0, True))
|
| 955 |
+
a = 3
|
| 956 |
+
X = Lomax('X', a, l)
|
| 957 |
+
assert E(X) == l/2
|
| 958 |
+
assert median(X) == FiniteSet(l*(-1 + 2**Rational(1, 3)))
|
| 959 |
+
assert variance(X) == 3*l**2/4
|
| 960 |
+
|
| 961 |
+
|
| 962 |
+
def test_maxwell():
|
| 963 |
+
a = Symbol("a", positive=True)
|
| 964 |
+
|
| 965 |
+
X = Maxwell('x', a)
|
| 966 |
+
|
| 967 |
+
assert density(X)(x) == (sqrt(2)*x**2*exp(-x**2/(2*a**2))/
|
| 968 |
+
(sqrt(pi)*a**3))
|
| 969 |
+
assert E(X) == 2*sqrt(2)*a/sqrt(pi)
|
| 970 |
+
assert variance(X) == -8*a**2/pi + 3*a**2
|
| 971 |
+
assert cdf(X)(x) == erf(sqrt(2)*x/(2*a)) - sqrt(2)*x*exp(-x**2/(2*a**2))/(sqrt(pi)*a)
|
| 972 |
+
assert diff(cdf(X)(x), x) == density(X)(x)
|
| 973 |
+
|
| 974 |
+
|
| 975 |
+
@slow
|
| 976 |
+
def test_Moyal():
|
| 977 |
+
mu = Symbol('mu',real=False)
|
| 978 |
+
sigma = Symbol('sigma', positive=True)
|
| 979 |
+
raises(ValueError, lambda: Moyal('M',mu, sigma))
|
| 980 |
+
|
| 981 |
+
mu = Symbol('mu', real=True)
|
| 982 |
+
sigma = Symbol('sigma', negative=True)
|
| 983 |
+
raises(ValueError, lambda: Moyal('M',mu, sigma))
|
| 984 |
+
|
| 985 |
+
sigma = Symbol('sigma', positive=True)
|
| 986 |
+
M = Moyal('M', mu, sigma)
|
| 987 |
+
assert density(M)(z) == sqrt(2)*exp(-exp((mu - z)/sigma)/2
|
| 988 |
+
- (-mu + z)/(2*sigma))/(2*sqrt(pi)*sigma)
|
| 989 |
+
assert cdf(M)(z).simplify() == 1 - erf(sqrt(2)*exp((mu - z)/(2*sigma))/2)
|
| 990 |
+
assert characteristic_function(M)(z) == 2**(-I*sigma*z)*exp(I*mu*z) \
|
| 991 |
+
*gamma(-I*sigma*z + Rational(1, 2))/sqrt(pi)
|
| 992 |
+
assert E(M) == mu + EulerGamma*sigma + sigma*log(2)
|
| 993 |
+
assert moment_generating_function(M)(z) == 2**(-sigma*z)*exp(mu*z) \
|
| 994 |
+
*gamma(-sigma*z + Rational(1, 2))/sqrt(pi)
|
| 995 |
+
|
| 996 |
+
|
| 997 |
+
def test_nakagami():
|
| 998 |
+
mu = Symbol("mu", positive=True)
|
| 999 |
+
omega = Symbol("omega", positive=True)
|
| 1000 |
+
|
| 1001 |
+
X = Nakagami('x', mu, omega)
|
| 1002 |
+
assert density(X)(x) == (2*x**(2*mu - 1)*mu**mu*omega**(-mu)
|
| 1003 |
+
*exp(-x**2*mu/omega)/gamma(mu))
|
| 1004 |
+
assert simplify(E(X)) == (sqrt(mu)*sqrt(omega)
|
| 1005 |
+
*gamma(mu + S.Half)/gamma(mu + 1))
|
| 1006 |
+
assert simplify(variance(X)) == (
|
| 1007 |
+
omega - omega*gamma(mu + S.Half)**2/(gamma(mu)*gamma(mu + 1)))
|
| 1008 |
+
assert cdf(X)(x) == Piecewise(
|
| 1009 |
+
(lowergamma(mu, mu*x**2/omega)/gamma(mu), x > 0),
|
| 1010 |
+
(0, True))
|
| 1011 |
+
X = Nakagami('x', 1, 1)
|
| 1012 |
+
assert median(X) == FiniteSet(sqrt(log(2)))
|
| 1013 |
+
|
| 1014 |
+
def test_gaussian_inverse():
|
| 1015 |
+
# test for symbolic parameters
|
| 1016 |
+
a, b = symbols('a b')
|
| 1017 |
+
assert GaussianInverse('x', a, b)
|
| 1018 |
+
|
| 1019 |
+
# Inverse Gaussian distribution is also known as Wald distribution
|
| 1020 |
+
# `GaussianInverse` can also be referred by the name `Wald`
|
| 1021 |
+
a, b, z = symbols('a b z')
|
| 1022 |
+
X = Wald('x', a, b)
|
| 1023 |
+
assert density(X)(z) == sqrt(2)*sqrt(b/z**3)*exp(-b*(-a + z)**2/(2*a**2*z))/(2*sqrt(pi))
|
| 1024 |
+
|
| 1025 |
+
a, b = symbols('a b', positive=True)
|
| 1026 |
+
z = Symbol('z', positive=True)
|
| 1027 |
+
|
| 1028 |
+
X = GaussianInverse('x', a, b)
|
| 1029 |
+
assert density(X)(z) == sqrt(2)*sqrt(b)*sqrt(z**(-3))*exp(-b*(-a + z)**2/(2*a**2*z))/(2*sqrt(pi))
|
| 1030 |
+
assert E(X) == a
|
| 1031 |
+
assert variance(X).expand() == a**3/b
|
| 1032 |
+
assert cdf(X)(z) == (S.Half - erf(sqrt(2)*sqrt(b)*(1 + z/a)/(2*sqrt(z)))/2)*exp(2*b/a) +\
|
| 1033 |
+
erf(sqrt(2)*sqrt(b)*(-1 + z/a)/(2*sqrt(z)))/2 + S.Half
|
| 1034 |
+
|
| 1035 |
+
a = symbols('a', nonpositive=True)
|
| 1036 |
+
raises(ValueError, lambda: GaussianInverse('x', a, b))
|
| 1037 |
+
|
| 1038 |
+
a = symbols('a', positive=True)
|
| 1039 |
+
b = symbols('b', nonpositive=True)
|
| 1040 |
+
raises(ValueError, lambda: GaussianInverse('x', a, b))
|
| 1041 |
+
|
| 1042 |
+
def test_pareto():
|
| 1043 |
+
xm, beta = symbols('xm beta', positive=True)
|
| 1044 |
+
alpha = beta + 5
|
| 1045 |
+
X = Pareto('x', xm, alpha)
|
| 1046 |
+
|
| 1047 |
+
dens = density(X)
|
| 1048 |
+
|
| 1049 |
+
#Tests cdf function
|
| 1050 |
+
assert cdf(X)(x) == \
|
| 1051 |
+
Piecewise((-x**(-beta - 5)*xm**(beta + 5) + 1, x >= xm), (0, True))
|
| 1052 |
+
|
| 1053 |
+
#Tests characteristic_function
|
| 1054 |
+
assert characteristic_function(X)(x) == \
|
| 1055 |
+
((-I*x*xm)**(beta + 5)*(beta + 5)*uppergamma(-beta - 5, -I*x*xm))
|
| 1056 |
+
|
| 1057 |
+
assert dens(x) == x**(-(alpha + 1))*xm**(alpha)*(alpha)
|
| 1058 |
+
|
| 1059 |
+
assert simplify(E(X)) == alpha*xm/(alpha-1)
|
| 1060 |
+
|
| 1061 |
+
# computation of taylor series for MGF still too slow
|
| 1062 |
+
#assert simplify(variance(X)) == xm**2*alpha / ((alpha-1)**2*(alpha-2))
|
| 1063 |
+
|
| 1064 |
+
|
| 1065 |
+
def test_pareto_numeric():
|
| 1066 |
+
xm, beta = 3, 2
|
| 1067 |
+
alpha = beta + 5
|
| 1068 |
+
X = Pareto('x', xm, alpha)
|
| 1069 |
+
|
| 1070 |
+
assert E(X) == alpha*xm/S(alpha - 1)
|
| 1071 |
+
assert variance(X) == xm**2*alpha / S((alpha - 1)**2*(alpha - 2))
|
| 1072 |
+
assert median(X) == FiniteSet(3*2**Rational(1, 7))
|
| 1073 |
+
# Skewness tests too slow. Try shortcutting function?
|
| 1074 |
+
|
| 1075 |
+
|
| 1076 |
+
def test_PowerFunction():
|
| 1077 |
+
alpha = Symbol("alpha", nonpositive=True)
|
| 1078 |
+
a, b = symbols('a, b', real=True)
|
| 1079 |
+
raises (ValueError, lambda: PowerFunction('x', alpha, a, b))
|
| 1080 |
+
|
| 1081 |
+
a, b = symbols('a, b', real=False)
|
| 1082 |
+
raises (ValueError, lambda: PowerFunction('x', alpha, a, b))
|
| 1083 |
+
|
| 1084 |
+
alpha = Symbol("alpha", positive=True)
|
| 1085 |
+
a, b = symbols('a, b', real=True)
|
| 1086 |
+
raises (ValueError, lambda: PowerFunction('x', alpha, 5, 2))
|
| 1087 |
+
|
| 1088 |
+
X = PowerFunction('X', 2, a, b)
|
| 1089 |
+
assert density(X)(z) == (-2*a + 2*z)/(-a + b)**2
|
| 1090 |
+
assert cdf(X)(z) == Piecewise((a**2/(a**2 - 2*a*b + b**2) -
|
| 1091 |
+
2*a*z/(a**2 - 2*a*b + b**2) + z**2/(a**2 - 2*a*b + b**2), a <= z), (0, True))
|
| 1092 |
+
|
| 1093 |
+
X = PowerFunction('X', 2, 0, 1)
|
| 1094 |
+
assert density(X)(z) == 2*z
|
| 1095 |
+
assert cdf(X)(z) == Piecewise((z**2, z >= 0), (0,True))
|
| 1096 |
+
assert E(X) == Rational(2,3)
|
| 1097 |
+
assert P(X < 0) == 0
|
| 1098 |
+
assert P(X < 1) == 1
|
| 1099 |
+
assert median(X) == FiniteSet(1/sqrt(2))
|
| 1100 |
+
|
| 1101 |
+
def test_raised_cosine():
|
| 1102 |
+
mu = Symbol("mu", real=True)
|
| 1103 |
+
s = Symbol("s", positive=True)
|
| 1104 |
+
|
| 1105 |
+
X = RaisedCosine("x", mu, s)
|
| 1106 |
+
|
| 1107 |
+
assert pspace(X).domain.set == Interval(mu - s, mu + s)
|
| 1108 |
+
#Tests characteristics_function
|
| 1109 |
+
assert characteristic_function(X)(x) == \
|
| 1110 |
+
Piecewise((exp(-I*pi*mu/s)/2, Eq(x, -pi/s)), (exp(I*pi*mu/s)/2, Eq(x, pi/s)), (pi**2*exp(I*mu*x)*sin(s*x)/(s*x*(-s**2*x**2 + pi**2)), True))
|
| 1111 |
+
|
| 1112 |
+
assert density(X)(x) == (Piecewise(((cos(pi*(x - mu)/s) + 1)/(2*s),
|
| 1113 |
+
And(x <= mu + s, mu - s <= x)), (0, True)))
|
| 1114 |
+
|
| 1115 |
+
|
| 1116 |
+
def test_rayleigh():
|
| 1117 |
+
sigma = Symbol("sigma", positive=True)
|
| 1118 |
+
|
| 1119 |
+
X = Rayleigh('x', sigma)
|
| 1120 |
+
|
| 1121 |
+
#Tests characteristic_function
|
| 1122 |
+
assert characteristic_function(X)(x) == (-sqrt(2)*sqrt(pi)*sigma*x*(erfi(sqrt(2)*sigma*x/2) - I)*exp(-sigma**2*x**2/2)/2 + 1)
|
| 1123 |
+
|
| 1124 |
+
assert density(X)(x) == x*exp(-x**2/(2*sigma**2))/sigma**2
|
| 1125 |
+
assert E(X) == sqrt(2)*sqrt(pi)*sigma/2
|
| 1126 |
+
assert variance(X) == -pi*sigma**2/2 + 2*sigma**2
|
| 1127 |
+
assert cdf(X)(x) == 1 - exp(-x**2/(2*sigma**2))
|
| 1128 |
+
assert diff(cdf(X)(x), x) == density(X)(x)
|
| 1129 |
+
|
| 1130 |
+
def test_reciprocal():
|
| 1131 |
+
a = Symbol("a", real=True)
|
| 1132 |
+
b = Symbol("b", real=True)
|
| 1133 |
+
|
| 1134 |
+
X = Reciprocal('x', a, b)
|
| 1135 |
+
assert density(X)(x) == 1/(x*(-log(a) + log(b)))
|
| 1136 |
+
assert cdf(X)(x) == Piecewise((log(a)/(log(a) - log(b)) - log(x)/(log(a) - log(b)), a <= x), (0, True))
|
| 1137 |
+
X = Reciprocal('x', 5, 30)
|
| 1138 |
+
|
| 1139 |
+
assert E(X) == 25/(log(30) - log(5))
|
| 1140 |
+
assert P(X < 4) == S.Zero
|
| 1141 |
+
assert P(X < 20) == log(20) / (log(30) - log(5)) - log(5) / (log(30) - log(5))
|
| 1142 |
+
assert cdf(X)(10) == log(10) / (log(30) - log(5)) - log(5) / (log(30) - log(5))
|
| 1143 |
+
|
| 1144 |
+
a = symbols('a', nonpositive=True)
|
| 1145 |
+
raises(ValueError, lambda: Reciprocal('x', a, b))
|
| 1146 |
+
|
| 1147 |
+
a = symbols('a', positive=True)
|
| 1148 |
+
b = symbols('b', positive=True)
|
| 1149 |
+
raises(ValueError, lambda: Reciprocal('x', a + b, a))
|
| 1150 |
+
|
| 1151 |
+
def test_shiftedgompertz():
|
| 1152 |
+
b = Symbol("b", positive=True)
|
| 1153 |
+
eta = Symbol("eta", positive=True)
|
| 1154 |
+
X = ShiftedGompertz("x", b, eta)
|
| 1155 |
+
assert density(X)(x) == b*(eta*(1 - exp(-b*x)) + 1)*exp(-b*x)*exp(-eta*exp(-b*x))
|
| 1156 |
+
|
| 1157 |
+
|
| 1158 |
+
def test_studentt():
|
| 1159 |
+
nu = Symbol("nu", positive=True)
|
| 1160 |
+
|
| 1161 |
+
X = StudentT('x', nu)
|
| 1162 |
+
assert density(X)(x) == (1 + x**2/nu)**(-nu/2 - S.Half)/(sqrt(nu)*beta(S.Half, nu/2))
|
| 1163 |
+
assert cdf(X)(x) == S.Half + x*gamma(nu/2 + S.Half)*hyper((S.Half, nu/2 + S.Half),
|
| 1164 |
+
(Rational(3, 2),), -x**2/nu)/(sqrt(pi)*sqrt(nu)*gamma(nu/2))
|
| 1165 |
+
raises(NotImplementedError, lambda: moment_generating_function(X))
|
| 1166 |
+
|
| 1167 |
+
def test_trapezoidal():
|
| 1168 |
+
a = Symbol("a", real=True)
|
| 1169 |
+
b = Symbol("b", real=True)
|
| 1170 |
+
c = Symbol("c", real=True)
|
| 1171 |
+
d = Symbol("d", real=True)
|
| 1172 |
+
|
| 1173 |
+
X = Trapezoidal('x', a, b, c, d)
|
| 1174 |
+
assert density(X)(x) == Piecewise(((-2*a + 2*x)/((-a + b)*(-a - b + c + d)), (a <= x) & (x < b)),
|
| 1175 |
+
(2/(-a - b + c + d), (b <= x) & (x < c)),
|
| 1176 |
+
((2*d - 2*x)/((-c + d)*(-a - b + c + d)), (c <= x) & (x <= d)),
|
| 1177 |
+
(0, True))
|
| 1178 |
+
|
| 1179 |
+
X = Trapezoidal('x', 0, 1, 2, 3)
|
| 1180 |
+
assert E(X) == Rational(3, 2)
|
| 1181 |
+
assert variance(X) == Rational(5, 12)
|
| 1182 |
+
assert P(X < 2) == Rational(3, 4)
|
| 1183 |
+
assert median(X) == FiniteSet(Rational(3, 2))
|
| 1184 |
+
|
| 1185 |
+
def test_triangular():
|
| 1186 |
+
a = Symbol("a")
|
| 1187 |
+
b = Symbol("b")
|
| 1188 |
+
c = Symbol("c")
|
| 1189 |
+
|
| 1190 |
+
X = Triangular('x', a, b, c)
|
| 1191 |
+
assert pspace(X).domain.set == Interval(a, b)
|
| 1192 |
+
assert str(density(X)(x)) == ("Piecewise(((-2*a + 2*x)/((-a + b)*(-a + c)), (a <= x) & (c > x)), "
|
| 1193 |
+
"(2/(-a + b), Eq(c, x)), ((2*b - 2*x)/((-a + b)*(b - c)), (b >= x) & (c < x)), (0, True))")
|
| 1194 |
+
|
| 1195 |
+
#Tests moment_generating_function
|
| 1196 |
+
assert moment_generating_function(X)(x).expand() == \
|
| 1197 |
+
((-2*(-a + b)*exp(c*x) + 2*(-a + c)*exp(b*x) + 2*(b - c)*exp(a*x))/(x**2*(-a + b)*(-a + c)*(b - c))).expand()
|
| 1198 |
+
assert str(characteristic_function(X)(x)) == \
|
| 1199 |
+
'(2*(-a + b)*exp(I*c*x) - 2*(-a + c)*exp(I*b*x) - 2*(b - c)*exp(I*a*x))/(x**2*(-a + b)*(-a + c)*(b - c))'
|
| 1200 |
+
|
| 1201 |
+
def test_quadratic_u():
|
| 1202 |
+
a = Symbol("a", real=True)
|
| 1203 |
+
b = Symbol("b", real=True)
|
| 1204 |
+
|
| 1205 |
+
X = QuadraticU("x", a, b)
|
| 1206 |
+
Y = QuadraticU("x", 1, 2)
|
| 1207 |
+
|
| 1208 |
+
assert pspace(X).domain.set == Interval(a, b)
|
| 1209 |
+
# Tests _moment_generating_function
|
| 1210 |
+
assert moment_generating_function(Y)(1) == -15*exp(2) + 27*exp(1)
|
| 1211 |
+
assert moment_generating_function(Y)(2) == -9*exp(4)/2 + 21*exp(2)/2
|
| 1212 |
+
|
| 1213 |
+
assert characteristic_function(Y)(1) == 3*I*(-1 + 4*I)*exp(I*exp(2*I))
|
| 1214 |
+
assert density(X)(x) == (Piecewise((12*(x - a/2 - b/2)**2/(-a + b)**3,
|
| 1215 |
+
And(x <= b, a <= x)), (0, True)))
|
| 1216 |
+
|
| 1217 |
+
|
| 1218 |
+
def test_uniform():
|
| 1219 |
+
l = Symbol('l', real=True)
|
| 1220 |
+
w = Symbol('w', positive=True)
|
| 1221 |
+
X = Uniform('x', l, l + w)
|
| 1222 |
+
|
| 1223 |
+
assert E(X) == l + w/2
|
| 1224 |
+
assert variance(X).expand() == w**2/12
|
| 1225 |
+
|
| 1226 |
+
# With numbers all is well
|
| 1227 |
+
X = Uniform('x', 3, 5)
|
| 1228 |
+
assert P(X < 3) == 0 and P(X > 5) == 0
|
| 1229 |
+
assert P(X < 4) == P(X > 4) == S.Half
|
| 1230 |
+
assert median(X) == FiniteSet(4)
|
| 1231 |
+
|
| 1232 |
+
z = Symbol('z')
|
| 1233 |
+
p = density(X)(z)
|
| 1234 |
+
assert p.subs(z, 3.7) == S.Half
|
| 1235 |
+
assert p.subs(z, -1) == 0
|
| 1236 |
+
assert p.subs(z, 6) == 0
|
| 1237 |
+
|
| 1238 |
+
c = cdf(X)
|
| 1239 |
+
assert c(2) == 0 and c(3) == 0
|
| 1240 |
+
assert c(Rational(7, 2)) == Rational(1, 4)
|
| 1241 |
+
assert c(5) == 1 and c(6) == 1
|
| 1242 |
+
|
| 1243 |
+
|
| 1244 |
+
@XFAIL
|
| 1245 |
+
@slow
|
| 1246 |
+
def test_uniform_P():
|
| 1247 |
+
""" This stopped working because SingleContinuousPSpace.compute_density no
|
| 1248 |
+
longer calls integrate on a DiracDelta but rather just solves directly.
|
| 1249 |
+
integrate used to call UniformDistribution.expectation which special-cased
|
| 1250 |
+
subsed out the Min and Max terms that Uniform produces
|
| 1251 |
+
|
| 1252 |
+
I decided to regress on this class for general cleanliness (and I suspect
|
| 1253 |
+
speed) of the algorithm.
|
| 1254 |
+
"""
|
| 1255 |
+
l = Symbol('l', real=True)
|
| 1256 |
+
w = Symbol('w', positive=True)
|
| 1257 |
+
X = Uniform('x', l, l + w)
|
| 1258 |
+
assert P(X < l) == 0 and P(X > l + w) == 0
|
| 1259 |
+
|
| 1260 |
+
|
| 1261 |
+
def test_uniformsum():
|
| 1262 |
+
n = Symbol("n", integer=True)
|
| 1263 |
+
_k = Dummy("k")
|
| 1264 |
+
x = Symbol("x")
|
| 1265 |
+
|
| 1266 |
+
X = UniformSum('x', n)
|
| 1267 |
+
res = Sum((-1)**_k*(-_k + x)**(n - 1)*binomial(n, _k), (_k, 0, floor(x)))/factorial(n - 1)
|
| 1268 |
+
assert density(X)(x).dummy_eq(res)
|
| 1269 |
+
|
| 1270 |
+
#Tests set functions
|
| 1271 |
+
assert X.pspace.domain.set == Interval(0, n)
|
| 1272 |
+
|
| 1273 |
+
#Tests the characteristic_function
|
| 1274 |
+
assert characteristic_function(X)(x) == (-I*(exp(I*x) - 1)/x)**n
|
| 1275 |
+
|
| 1276 |
+
#Tests the moment_generating_function
|
| 1277 |
+
assert moment_generating_function(X)(x) == ((exp(x) - 1)/x)**n
|
| 1278 |
+
|
| 1279 |
+
|
| 1280 |
+
def test_von_mises():
|
| 1281 |
+
mu = Symbol("mu")
|
| 1282 |
+
k = Symbol("k", positive=True)
|
| 1283 |
+
|
| 1284 |
+
X = VonMises("x", mu, k)
|
| 1285 |
+
assert density(X)(x) == exp(k*cos(x - mu))/(2*pi*besseli(0, k))
|
| 1286 |
+
|
| 1287 |
+
|
| 1288 |
+
def test_weibull():
|
| 1289 |
+
a, b = symbols('a b', positive=True)
|
| 1290 |
+
# FIXME: simplify(E(X)) seems to hang without extended_positive=True
|
| 1291 |
+
# On a Linux machine this had a rapid memory leak...
|
| 1292 |
+
# a, b = symbols('a b', positive=True)
|
| 1293 |
+
X = Weibull('x', a, b)
|
| 1294 |
+
|
| 1295 |
+
assert E(X).expand() == a * gamma(1 + 1/b)
|
| 1296 |
+
assert variance(X).expand() == (a**2 * gamma(1 + 2/b) - E(X)**2).expand()
|
| 1297 |
+
assert simplify(skewness(X)) == (2*gamma(1 + 1/b)**3 - 3*gamma(1 + 1/b)*gamma(1 + 2/b) + gamma(1 + 3/b))/(-gamma(1 + 1/b)**2 + gamma(1 + 2/b))**Rational(3, 2)
|
| 1298 |
+
assert simplify(kurtosis(X)) == (-3*gamma(1 + 1/b)**4 +\
|
| 1299 |
+
6*gamma(1 + 1/b)**2*gamma(1 + 2/b) - 4*gamma(1 + 1/b)*gamma(1 + 3/b) + gamma(1 + 4/b))/(gamma(1 + 1/b)**2 - gamma(1 + 2/b))**2
|
| 1300 |
+
|
| 1301 |
+
def test_weibull_numeric():
|
| 1302 |
+
# Test for integers and rationals
|
| 1303 |
+
a = 1
|
| 1304 |
+
bvals = [S.Half, 1, Rational(3, 2), 5]
|
| 1305 |
+
for b in bvals:
|
| 1306 |
+
X = Weibull('x', a, b)
|
| 1307 |
+
assert simplify(E(X)) == expand_func(a * gamma(1 + 1/S(b)))
|
| 1308 |
+
assert simplify(variance(X)) == simplify(
|
| 1309 |
+
a**2 * gamma(1 + 2/S(b)) - E(X)**2)
|
| 1310 |
+
# Not testing Skew... it's slow with int/frac values > 3/2
|
| 1311 |
+
|
| 1312 |
+
|
| 1313 |
+
def test_wignersemicircle():
|
| 1314 |
+
R = Symbol("R", positive=True)
|
| 1315 |
+
|
| 1316 |
+
X = WignerSemicircle('x', R)
|
| 1317 |
+
assert pspace(X).domain.set == Interval(-R, R)
|
| 1318 |
+
assert density(X)(x) == 2*sqrt(-x**2 + R**2)/(pi*R**2)
|
| 1319 |
+
assert E(X) == 0
|
| 1320 |
+
|
| 1321 |
+
|
| 1322 |
+
#Tests ChiNoncentralDistribution
|
| 1323 |
+
assert characteristic_function(X)(x) == \
|
| 1324 |
+
Piecewise((2*besselj(1, R*x)/(R*x), Ne(x, 0)), (1, True))
|
| 1325 |
+
|
| 1326 |
+
|
| 1327 |
+
def test_input_value_assertions():
|
| 1328 |
+
a, b = symbols('a b')
|
| 1329 |
+
p, q = symbols('p q', positive=True)
|
| 1330 |
+
m, n = symbols('m n', positive=False, real=True)
|
| 1331 |
+
|
| 1332 |
+
raises(ValueError, lambda: Normal('x', 3, 0))
|
| 1333 |
+
raises(ValueError, lambda: Normal('x', m, n))
|
| 1334 |
+
Normal('X', a, p) # No error raised
|
| 1335 |
+
raises(ValueError, lambda: Exponential('x', m))
|
| 1336 |
+
Exponential('Ex', p) # No error raised
|
| 1337 |
+
for fn in [Pareto, Weibull, Beta, Gamma]:
|
| 1338 |
+
raises(ValueError, lambda: fn('x', m, p))
|
| 1339 |
+
raises(ValueError, lambda: fn('x', p, n))
|
| 1340 |
+
fn('x', p, q) # No error raised
|
| 1341 |
+
|
| 1342 |
+
|
| 1343 |
+
def test_unevaluated():
|
| 1344 |
+
X = Normal('x', 0, 1)
|
| 1345 |
+
k = Dummy('k')
|
| 1346 |
+
expr1 = Integral(sqrt(2)*k*exp(-k**2/2)/(2*sqrt(pi)), (k, -oo, oo))
|
| 1347 |
+
expr2 = Integral(sqrt(2)*exp(-k**2/2)/(2*sqrt(pi)), (k, 0, oo))
|
| 1348 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 1349 |
+
assert E(X, evaluate=False).rewrite(Integral).dummy_eq(expr1)
|
| 1350 |
+
assert E(X + 1, evaluate=False).rewrite(Integral).dummy_eq(expr1 + 1)
|
| 1351 |
+
assert P(X > 0, evaluate=False).rewrite(Integral).dummy_eq(expr2)
|
| 1352 |
+
|
| 1353 |
+
assert P(X > 0, X**2 < 1) == S.Half
|
| 1354 |
+
|
| 1355 |
+
|
| 1356 |
+
def test_probability_unevaluated():
|
| 1357 |
+
T = Normal('T', 30, 3)
|
| 1358 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 1359 |
+
assert type(P(T > 33, evaluate=False)) == Probability
|
| 1360 |
+
|
| 1361 |
+
|
| 1362 |
+
def test_density_unevaluated():
|
| 1363 |
+
X = Normal('X', 0, 1)
|
| 1364 |
+
Y = Normal('Y', 0, 2)
|
| 1365 |
+
assert isinstance(density(X+Y, evaluate=False)(z), Integral)
|
| 1366 |
+
|
| 1367 |
+
|
| 1368 |
+
def test_NormalDistribution():
|
| 1369 |
+
nd = NormalDistribution(0, 1)
|
| 1370 |
+
x = Symbol('x')
|
| 1371 |
+
assert nd.cdf(x) == erf(sqrt(2)*x/2)/2 + S.Half
|
| 1372 |
+
assert nd.expectation(1, x) == 1
|
| 1373 |
+
assert nd.expectation(x, x) == 0
|
| 1374 |
+
assert nd.expectation(x**2, x) == 1
|
| 1375 |
+
#Test issue 10076
|
| 1376 |
+
a = SingleContinuousPSpace(x, NormalDistribution(2, 4))
|
| 1377 |
+
_z = Dummy('_z')
|
| 1378 |
+
|
| 1379 |
+
expected1 = Integral(sqrt(2)*exp(-(_z - 2)**2/32)/(8*sqrt(pi)),(_z, -oo, 1))
|
| 1380 |
+
assert a.probability(x < 1, evaluate=False).dummy_eq(expected1) is True
|
| 1381 |
+
|
| 1382 |
+
expected2 = Integral(sqrt(2)*exp(-(_z - 2)**2/32)/(8*sqrt(pi)),(_z, 1, oo))
|
| 1383 |
+
assert a.probability(x > 1, evaluate=False).dummy_eq(expected2) is True
|
| 1384 |
+
|
| 1385 |
+
b = SingleContinuousPSpace(x, NormalDistribution(1, 9))
|
| 1386 |
+
|
| 1387 |
+
expected3 = Integral(sqrt(2)*exp(-(_z - 1)**2/162)/(18*sqrt(pi)),(_z, 6, oo))
|
| 1388 |
+
assert b.probability(x > 6, evaluate=False).dummy_eq(expected3) is True
|
| 1389 |
+
|
| 1390 |
+
expected4 = Integral(sqrt(2)*exp(-(_z - 1)**2/162)/(18*sqrt(pi)),(_z, -oo, 6))
|
| 1391 |
+
assert b.probability(x < 6, evaluate=False).dummy_eq(expected4) is True
|
| 1392 |
+
|
| 1393 |
+
|
| 1394 |
+
def test_random_parameters():
|
| 1395 |
+
mu = Normal('mu', 2, 3)
|
| 1396 |
+
meas = Normal('T', mu, 1)
|
| 1397 |
+
assert density(meas, evaluate=False)(z)
|
| 1398 |
+
assert isinstance(pspace(meas), CompoundPSpace)
|
| 1399 |
+
X = Normal('x', [1, 2], [[1, 0], [0, 1]])
|
| 1400 |
+
assert isinstance(pspace(X).distribution, MultivariateNormalDistribution)
|
| 1401 |
+
assert density(meas)(z).simplify() == sqrt(5)*exp(-z**2/20 + z/5 - S(1)/5)/(10*sqrt(pi))
|
| 1402 |
+
|
| 1403 |
+
|
| 1404 |
+
def test_random_parameters_given():
|
| 1405 |
+
mu = Normal('mu', 2, 3)
|
| 1406 |
+
meas = Normal('T', mu, 1)
|
| 1407 |
+
assert given(meas, Eq(mu, 5)) == Normal('T', 5, 1)
|
| 1408 |
+
|
| 1409 |
+
|
| 1410 |
+
def test_conjugate_priors():
|
| 1411 |
+
mu = Normal('mu', 2, 3)
|
| 1412 |
+
x = Normal('x', mu, 1)
|
| 1413 |
+
assert isinstance(simplify(density(mu, Eq(x, y), evaluate=False)(z)),
|
| 1414 |
+
Mul)
|
| 1415 |
+
|
| 1416 |
+
|
| 1417 |
+
def test_difficult_univariate():
|
| 1418 |
+
""" Since using solve in place of deltaintegrate we're able to perform
|
| 1419 |
+
substantially more complex density computations on single continuous random
|
| 1420 |
+
variables """
|
| 1421 |
+
x = Normal('x', 0, 1)
|
| 1422 |
+
assert density(x**3)
|
| 1423 |
+
assert density(exp(x**2))
|
| 1424 |
+
assert density(log(x))
|
| 1425 |
+
|
| 1426 |
+
|
| 1427 |
+
def test_issue_10003():
|
| 1428 |
+
X = Exponential('x', 3)
|
| 1429 |
+
G = Gamma('g', 1, 2)
|
| 1430 |
+
assert P(X < -1) is S.Zero
|
| 1431 |
+
assert P(G < -1) is S.Zero
|
| 1432 |
+
|
| 1433 |
+
|
| 1434 |
+
def test_precomputed_cdf():
|
| 1435 |
+
x = symbols("x", real=True)
|
| 1436 |
+
mu = symbols("mu", real=True)
|
| 1437 |
+
sigma, xm, alpha = symbols("sigma xm alpha", positive=True)
|
| 1438 |
+
n = symbols("n", integer=True, positive=True)
|
| 1439 |
+
distribs = [
|
| 1440 |
+
Normal("X", mu, sigma),
|
| 1441 |
+
Pareto("P", xm, alpha),
|
| 1442 |
+
ChiSquared("C", n),
|
| 1443 |
+
Exponential("E", sigma),
|
| 1444 |
+
# LogNormal("L", mu, sigma),
|
| 1445 |
+
]
|
| 1446 |
+
for X in distribs:
|
| 1447 |
+
compdiff = cdf(X)(x) - simplify(X.pspace.density.compute_cdf()(x))
|
| 1448 |
+
compdiff = simplify(compdiff.rewrite(erfc))
|
| 1449 |
+
assert compdiff == 0
|
| 1450 |
+
|
| 1451 |
+
|
| 1452 |
+
@slow
|
| 1453 |
+
def test_precomputed_characteristic_functions():
|
| 1454 |
+
import mpmath
|
| 1455 |
+
|
| 1456 |
+
def test_cf(dist, support_lower_limit, support_upper_limit):
|
| 1457 |
+
pdf = density(dist)
|
| 1458 |
+
t = Symbol('t')
|
| 1459 |
+
|
| 1460 |
+
# first function is the hardcoded CF of the distribution
|
| 1461 |
+
cf1 = lambdify([t], characteristic_function(dist)(t), 'mpmath')
|
| 1462 |
+
|
| 1463 |
+
# second function is the Fourier transform of the density function
|
| 1464 |
+
f = lambdify([x, t], pdf(x)*exp(I*x*t), 'mpmath')
|
| 1465 |
+
cf2 = lambda t: mpmath.quad(lambda x: f(x, t), [support_lower_limit, support_upper_limit], maxdegree=10)
|
| 1466 |
+
|
| 1467 |
+
# compare the two functions at various points
|
| 1468 |
+
for test_point in [2, 5, 8, 11]:
|
| 1469 |
+
n1 = cf1(test_point)
|
| 1470 |
+
n2 = cf2(test_point)
|
| 1471 |
+
|
| 1472 |
+
assert abs(re(n1) - re(n2)) < 1e-12
|
| 1473 |
+
assert abs(im(n1) - im(n2)) < 1e-12
|
| 1474 |
+
|
| 1475 |
+
test_cf(Beta('b', 1, 2), 0, 1)
|
| 1476 |
+
test_cf(Chi('c', 3), 0, mpmath.inf)
|
| 1477 |
+
test_cf(ChiSquared('c', 2), 0, mpmath.inf)
|
| 1478 |
+
test_cf(Exponential('e', 6), 0, mpmath.inf)
|
| 1479 |
+
test_cf(Logistic('l', 1, 2), -mpmath.inf, mpmath.inf)
|
| 1480 |
+
test_cf(Normal('n', -1, 5), -mpmath.inf, mpmath.inf)
|
| 1481 |
+
test_cf(RaisedCosine('r', 3, 1), 2, 4)
|
| 1482 |
+
test_cf(Rayleigh('r', 0.5), 0, mpmath.inf)
|
| 1483 |
+
test_cf(Uniform('u', -1, 1), -1, 1)
|
| 1484 |
+
test_cf(WignerSemicircle('w', 3), -3, 3)
|
| 1485 |
+
|
| 1486 |
+
|
| 1487 |
+
def test_long_precomputed_cdf():
|
| 1488 |
+
x = symbols("x", real=True)
|
| 1489 |
+
distribs = [
|
| 1490 |
+
Arcsin("A", -5, 9),
|
| 1491 |
+
Dagum("D", 4, 10, 3),
|
| 1492 |
+
Erlang("E", 14, 5),
|
| 1493 |
+
Frechet("F", 2, 6, -3),
|
| 1494 |
+
Gamma("G", 2, 7),
|
| 1495 |
+
GammaInverse("GI", 3, 5),
|
| 1496 |
+
Kumaraswamy("K", 6, 8),
|
| 1497 |
+
Laplace("LA", -5, 4),
|
| 1498 |
+
Logistic("L", -6, 7),
|
| 1499 |
+
Nakagami("N", 2, 7),
|
| 1500 |
+
StudentT("S", 4)
|
| 1501 |
+
]
|
| 1502 |
+
for distr in distribs:
|
| 1503 |
+
for _ in range(5):
|
| 1504 |
+
assert tn(diff(cdf(distr)(x), x), density(distr)(x), x, a=0, b=0, c=1, d=0)
|
| 1505 |
+
|
| 1506 |
+
US = UniformSum("US", 5)
|
| 1507 |
+
pdf01 = density(US)(x).subs(floor(x), 0).doit() # pdf on (0, 1)
|
| 1508 |
+
cdf01 = cdf(US, evaluate=False)(x).subs(floor(x), 0).doit() # cdf on (0, 1)
|
| 1509 |
+
assert tn(diff(cdf01, x), pdf01, x, a=0, b=0, c=1, d=0)
|
| 1510 |
+
|
| 1511 |
+
|
| 1512 |
+
def test_issue_13324():
|
| 1513 |
+
X = Uniform('X', 0, 1)
|
| 1514 |
+
assert E(X, X > S.Half) == Rational(3, 4)
|
| 1515 |
+
assert E(X, X > 0) == S.Half
|
| 1516 |
+
|
| 1517 |
+
def test_issue_20756():
|
| 1518 |
+
X = Uniform('X', -1, +1)
|
| 1519 |
+
Y = Uniform('Y', -1, +1)
|
| 1520 |
+
assert E(X * Y) == S.Zero
|
| 1521 |
+
assert E(X * ((Y + 1) - 1)) == S.Zero
|
| 1522 |
+
assert E(Y * (X*(X + 1) - X*X)) == S.Zero
|
| 1523 |
+
|
| 1524 |
+
def test_FiniteSet_prob():
|
| 1525 |
+
E = Exponential('E', 3)
|
| 1526 |
+
N = Normal('N', 5, 7)
|
| 1527 |
+
assert P(Eq(E, 1)) is S.Zero
|
| 1528 |
+
assert P(Eq(N, 2)) is S.Zero
|
| 1529 |
+
assert P(Eq(N, x)) is S.Zero
|
| 1530 |
+
|
| 1531 |
+
def test_prob_neq():
|
| 1532 |
+
E = Exponential('E', 4)
|
| 1533 |
+
X = ChiSquared('X', 4)
|
| 1534 |
+
assert P(Ne(E, 2)) == 1
|
| 1535 |
+
assert P(Ne(X, 4)) == 1
|
| 1536 |
+
assert P(Ne(X, 4)) == 1
|
| 1537 |
+
assert P(Ne(X, 5)) == 1
|
| 1538 |
+
assert P(Ne(E, x)) == 1
|
| 1539 |
+
|
| 1540 |
+
def test_union():
|
| 1541 |
+
N = Normal('N', 3, 2)
|
| 1542 |
+
assert simplify(P(N**2 - N > 2)) == \
|
| 1543 |
+
-erf(sqrt(2))/2 - erfc(sqrt(2)/4)/2 + Rational(3, 2)
|
| 1544 |
+
assert simplify(P(N**2 - 4 > 0)) == \
|
| 1545 |
+
-erf(5*sqrt(2)/4)/2 - erfc(sqrt(2)/4)/2 + Rational(3, 2)
|
| 1546 |
+
|
| 1547 |
+
def test_Or():
|
| 1548 |
+
N = Normal('N', 0, 1)
|
| 1549 |
+
assert simplify(P(Or(N > 2, N < 1))) == \
|
| 1550 |
+
-erf(sqrt(2))/2 - erfc(sqrt(2)/2)/2 + Rational(3, 2)
|
| 1551 |
+
assert P(Or(N < 0, N < 1)) == P(N < 1)
|
| 1552 |
+
assert P(Or(N > 0, N < 0)) == 1
|
| 1553 |
+
|
| 1554 |
+
|
| 1555 |
+
def test_conditional_eq():
|
| 1556 |
+
E = Exponential('E', 1)
|
| 1557 |
+
assert P(Eq(E, 1), Eq(E, 1)) == 1
|
| 1558 |
+
assert P(Eq(E, 1), Eq(E, 2)) == 0
|
| 1559 |
+
assert P(E > 1, Eq(E, 2)) == 1
|
| 1560 |
+
assert P(E < 1, Eq(E, 2)) == 0
|
| 1561 |
+
|
| 1562 |
+
def test_ContinuousDistributionHandmade():
|
| 1563 |
+
x = Symbol('x')
|
| 1564 |
+
z = Dummy('z')
|
| 1565 |
+
dens = Lambda(x, Piecewise((S.Half, (0<=x)&(x<1)), (0, (x>=1)&(x<2)),
|
| 1566 |
+
(S.Half, (x>=2)&(x<3)), (0, True)))
|
| 1567 |
+
dens = ContinuousDistributionHandmade(dens, set=Interval(0, 3))
|
| 1568 |
+
space = SingleContinuousPSpace(z, dens)
|
| 1569 |
+
assert dens.pdf == Lambda(x, Piecewise((S(1)/2, (x >= 0) & (x < 1)),
|
| 1570 |
+
(0, (x >= 1) & (x < 2)), (S(1)/2, (x >= 2) & (x < 3)), (0, True)))
|
| 1571 |
+
assert median(space.value) == Interval(1, 2)
|
| 1572 |
+
assert E(space.value) == Rational(3, 2)
|
| 1573 |
+
assert variance(space.value) == Rational(13, 12)
|
| 1574 |
+
|
| 1575 |
+
|
| 1576 |
+
def test_issue_16318():
|
| 1577 |
+
# test compute_expectation function of the SingleContinuousDomain
|
| 1578 |
+
N = SingleContinuousDomain(x, Interval(0, 1))
|
| 1579 |
+
raises(ValueError, lambda: SingleContinuousDomain.compute_expectation(N, x+1, {x, y}))
|
| 1580 |
+
|
| 1581 |
+
def test_compute_density():
|
| 1582 |
+
X = Normal('X', 0, Symbol("sigma")**2)
|
| 1583 |
+
raises(ValueError, lambda: density(X**5 + X))
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_discrete_rv.py
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.numbers import (I, Rational, oo, pi)
|
| 3 |
+
from sympy.core.singleton import S
|
| 4 |
+
from sympy.core.symbol import Symbol
|
| 5 |
+
from sympy.functions.elementary.complexes import (im, re)
|
| 6 |
+
from sympy.functions.elementary.exponential import log
|
| 7 |
+
from sympy.functions.elementary.integers import floor
|
| 8 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 9 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 10 |
+
from sympy.functions.special.bessel import besseli
|
| 11 |
+
from sympy.functions.special.beta_functions import beta
|
| 12 |
+
from sympy.functions.special.zeta_functions import zeta
|
| 13 |
+
from sympy.sets.sets import FiniteSet
|
| 14 |
+
from sympy.simplify.simplify import simplify
|
| 15 |
+
from sympy.utilities.lambdify import lambdify
|
| 16 |
+
from sympy.core.relational import Eq, Ne
|
| 17 |
+
from sympy.functions.elementary.exponential import exp
|
| 18 |
+
from sympy.logic.boolalg import Or
|
| 19 |
+
from sympy.sets.fancysets import Range
|
| 20 |
+
from sympy.stats import (P, E, variance, density, characteristic_function,
|
| 21 |
+
where, moment_generating_function, skewness, cdf,
|
| 22 |
+
kurtosis, coskewness)
|
| 23 |
+
from sympy.stats.drv_types import (PoissonDistribution, GeometricDistribution,
|
| 24 |
+
FlorySchulz, Poisson, Geometric, Hermite, Logarithmic,
|
| 25 |
+
NegativeBinomial, Skellam, YuleSimon, Zeta,
|
| 26 |
+
DiscreteRV)
|
| 27 |
+
from sympy.testing.pytest import slow, nocache_fail, raises, skip
|
| 28 |
+
from sympy.stats.symbolic_probability import Expectation
|
| 29 |
+
from sympy.functions.combinatorial.factorials import FallingFactorial
|
| 30 |
+
|
| 31 |
+
x = Symbol('x')
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def test_PoissonDistribution():
|
| 35 |
+
l = 3
|
| 36 |
+
p = PoissonDistribution(l)
|
| 37 |
+
assert abs(p.cdf(10).evalf() - 1) < .001
|
| 38 |
+
assert abs(p.cdf(10.4).evalf() - 1) < .001
|
| 39 |
+
assert p.expectation(x, x) == l
|
| 40 |
+
assert p.expectation(x**2, x) - p.expectation(x, x)**2 == l
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def test_Poisson():
|
| 44 |
+
l = 3
|
| 45 |
+
x = Poisson('x', l)
|
| 46 |
+
assert E(x) == l
|
| 47 |
+
assert E(2*x) == 2*l
|
| 48 |
+
assert variance(x) == l
|
| 49 |
+
assert density(x) == PoissonDistribution(l)
|
| 50 |
+
assert isinstance(E(x, evaluate=False), Expectation)
|
| 51 |
+
assert isinstance(E(2*x, evaluate=False), Expectation)
|
| 52 |
+
# issue 8248
|
| 53 |
+
assert x.pspace.compute_expectation(1) == 1
|
| 54 |
+
# issue 27344
|
| 55 |
+
try:
|
| 56 |
+
import numpy as np
|
| 57 |
+
except ImportError:
|
| 58 |
+
skip("numpy not installed")
|
| 59 |
+
y = Poisson('y', np.float64(4.72544290380919e-11))
|
| 60 |
+
assert E(y) == 4.72544290380919e-11
|
| 61 |
+
y = Poisson('y', np.float64(4.725442903809197e-11))
|
| 62 |
+
assert E(y) == 4.725442903809197e-11
|
| 63 |
+
l2 = 5
|
| 64 |
+
z = Poisson('z', l2)
|
| 65 |
+
assert E(z) == l2
|
| 66 |
+
assert E(FallingFactorial(z, 3)) == l2**3
|
| 67 |
+
assert E(z**2) == l2 + l2**2
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_FlorySchulz():
|
| 71 |
+
a = Symbol("a")
|
| 72 |
+
z = Symbol("z")
|
| 73 |
+
x = FlorySchulz('x', a)
|
| 74 |
+
assert E(x) == (2 - a)/a
|
| 75 |
+
assert (variance(x) - 2*(1 - a)/a**2).simplify() == S(0)
|
| 76 |
+
assert density(x)(z) == a**2*z*(1 - a)**(z - 1)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
@slow
|
| 80 |
+
def test_GeometricDistribution():
|
| 81 |
+
p = S.One / 5
|
| 82 |
+
d = GeometricDistribution(p)
|
| 83 |
+
assert d.expectation(x, x) == 1/p
|
| 84 |
+
assert d.expectation(x**2, x) - d.expectation(x, x)**2 == (1-p)/p**2
|
| 85 |
+
assert abs(d.cdf(20000).evalf() - 1) < .001
|
| 86 |
+
assert abs(d.cdf(20000.8).evalf() - 1) < .001
|
| 87 |
+
G = Geometric('G', p=S(1)/4)
|
| 88 |
+
assert cdf(G)(S(7)/2) == P(G <= S(7)/2)
|
| 89 |
+
|
| 90 |
+
X = Geometric('X', Rational(1, 5))
|
| 91 |
+
Y = Geometric('Y', Rational(3, 10))
|
| 92 |
+
assert coskewness(X, X + Y, X + 2*Y).simplify() == sqrt(230)*Rational(81, 1150)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def test_Hermite():
|
| 96 |
+
a1 = Symbol("a1", positive=True)
|
| 97 |
+
a2 = Symbol("a2", negative=True)
|
| 98 |
+
raises(ValueError, lambda: Hermite("H", a1, a2))
|
| 99 |
+
|
| 100 |
+
a1 = Symbol("a1", negative=True)
|
| 101 |
+
a2 = Symbol("a2", positive=True)
|
| 102 |
+
raises(ValueError, lambda: Hermite("H", a1, a2))
|
| 103 |
+
|
| 104 |
+
a1 = Symbol("a1", positive=True)
|
| 105 |
+
x = Symbol("x")
|
| 106 |
+
H = Hermite("H", a1, a2)
|
| 107 |
+
assert moment_generating_function(H)(x) == exp(a1*(exp(x) - 1)
|
| 108 |
+
+ a2*(exp(2*x) - 1))
|
| 109 |
+
assert characteristic_function(H)(x) == exp(a1*(exp(I*x) - 1)
|
| 110 |
+
+ a2*(exp(2*I*x) - 1))
|
| 111 |
+
assert E(H) == a1 + 2*a2
|
| 112 |
+
|
| 113 |
+
H = Hermite("H", a1=5, a2=4)
|
| 114 |
+
assert density(H)(2) == 33*exp(-9)/2
|
| 115 |
+
assert E(H) == 13
|
| 116 |
+
assert variance(H) == 21
|
| 117 |
+
assert kurtosis(H) == Rational(464,147)
|
| 118 |
+
assert skewness(H) == 37*sqrt(21)/441
|
| 119 |
+
|
| 120 |
+
def test_Logarithmic():
|
| 121 |
+
p = S.Half
|
| 122 |
+
x = Logarithmic('x', p)
|
| 123 |
+
assert E(x) == -p / ((1 - p) * log(1 - p))
|
| 124 |
+
assert variance(x) == -1/log(2)**2 + 2/log(2)
|
| 125 |
+
assert E(2*x**2 + 3*x + 4) == 4 + 7 / log(2)
|
| 126 |
+
assert isinstance(E(x, evaluate=False), Expectation)
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@nocache_fail
|
| 130 |
+
def test_negative_binomial():
|
| 131 |
+
r = 5
|
| 132 |
+
p = S.One / 3
|
| 133 |
+
x = NegativeBinomial('x', r, p)
|
| 134 |
+
assert E(x) == r * (1 - p) / p
|
| 135 |
+
# This hangs when run with the cache disabled:
|
| 136 |
+
assert variance(x) == r * (1 - p) / p**2
|
| 137 |
+
assert E(x**5 + 2*x + 3) == E(x**5) + 2*E(x) + 3 == Rational(796473, 1)
|
| 138 |
+
assert isinstance(E(x, evaluate=False), Expectation)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def test_skellam():
|
| 142 |
+
mu1 = Symbol('mu1')
|
| 143 |
+
mu2 = Symbol('mu2')
|
| 144 |
+
z = Symbol('z')
|
| 145 |
+
X = Skellam('x', mu1, mu2)
|
| 146 |
+
|
| 147 |
+
assert density(X)(z) == (mu1/mu2)**(z/2) * \
|
| 148 |
+
exp(-mu1 - mu2)*besseli(z, 2*sqrt(mu1*mu2))
|
| 149 |
+
assert skewness(X).expand() == mu1/(mu1*sqrt(mu1 + mu2) + mu2 *
|
| 150 |
+
sqrt(mu1 + mu2)) - mu2/(mu1*sqrt(mu1 + mu2) + mu2*sqrt(mu1 + mu2))
|
| 151 |
+
assert variance(X).expand() == mu1 + mu2
|
| 152 |
+
assert E(X) == mu1 - mu2
|
| 153 |
+
assert characteristic_function(X)(z) == exp(
|
| 154 |
+
mu1*exp(I*z) - mu1 - mu2 + mu2*exp(-I*z))
|
| 155 |
+
assert moment_generating_function(X)(z) == exp(
|
| 156 |
+
mu1*exp(z) - mu1 - mu2 + mu2*exp(-z))
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_yule_simon():
|
| 160 |
+
from sympy.core.singleton import S
|
| 161 |
+
rho = S(3)
|
| 162 |
+
x = YuleSimon('x', rho)
|
| 163 |
+
assert simplify(E(x)) == rho / (rho - 1)
|
| 164 |
+
assert simplify(variance(x)) == rho**2 / ((rho - 1)**2 * (rho - 2))
|
| 165 |
+
assert isinstance(E(x, evaluate=False), Expectation)
|
| 166 |
+
# To test the cdf function
|
| 167 |
+
assert cdf(x)(x) == Piecewise((-beta(floor(x), 4)*floor(x) + 1, x >= 1), (0, True))
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def test_zeta():
|
| 171 |
+
s = S(5)
|
| 172 |
+
x = Zeta('x', s)
|
| 173 |
+
assert E(x) == zeta(s-1) / zeta(s)
|
| 174 |
+
assert simplify(variance(x)) == (
|
| 175 |
+
zeta(s) * zeta(s-2) - zeta(s-1)**2) / zeta(s)**2
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def test_discrete_probability():
|
| 179 |
+
X = Geometric('X', Rational(1, 5))
|
| 180 |
+
Y = Poisson('Y', 4)
|
| 181 |
+
G = Geometric('e', x)
|
| 182 |
+
assert P(Eq(X, 3)) == Rational(16, 125)
|
| 183 |
+
assert P(X < 3) == Rational(9, 25)
|
| 184 |
+
assert P(X > 3) == Rational(64, 125)
|
| 185 |
+
assert P(X >= 3) == Rational(16, 25)
|
| 186 |
+
assert P(X <= 3) == Rational(61, 125)
|
| 187 |
+
assert P(Ne(X, 3)) == Rational(109, 125)
|
| 188 |
+
assert P(Eq(Y, 3)) == 32*exp(-4)/3
|
| 189 |
+
assert P(Y < 3) == 13*exp(-4)
|
| 190 |
+
assert P(Y > 3).equals(32*(Rational(-71, 32) + 3*exp(4)/32)*exp(-4)/3)
|
| 191 |
+
assert P(Y >= 3).equals(32*(Rational(-39, 32) + 3*exp(4)/32)*exp(-4)/3)
|
| 192 |
+
assert P(Y <= 3) == 71*exp(-4)/3
|
| 193 |
+
assert P(Ne(Y, 3)).equals(
|
| 194 |
+
13*exp(-4) + 32*(Rational(-71, 32) + 3*exp(4)/32)*exp(-4)/3)
|
| 195 |
+
assert P(X < S.Infinity) is S.One
|
| 196 |
+
assert P(X > S.Infinity) is S.Zero
|
| 197 |
+
assert P(G < 3) == x*(2-x)
|
| 198 |
+
assert P(Eq(G, 3)) == x*(-x + 1)**2
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
def test_DiscreteRV():
|
| 202 |
+
p = S(1)/2
|
| 203 |
+
x = Symbol('x', integer=True, positive=True)
|
| 204 |
+
pdf = p*(1 - p)**(x - 1) # pdf of Geometric Distribution
|
| 205 |
+
D = DiscreteRV(x, pdf, set=S.Naturals, check=True)
|
| 206 |
+
assert E(D) == E(Geometric('G', S(1)/2)) == 2
|
| 207 |
+
assert P(D > 3) == S(1)/8
|
| 208 |
+
assert D.pspace.domain.set == S.Naturals
|
| 209 |
+
raises(ValueError, lambda: DiscreteRV(x, x, FiniteSet(*range(4)), check=True))
|
| 210 |
+
|
| 211 |
+
# purposeful invalid pmf but it should not raise since check=False
|
| 212 |
+
# see test_drv_types.test_ContinuousRV for explanation
|
| 213 |
+
X = DiscreteRV(x, 1/x, S.Naturals)
|
| 214 |
+
assert P(X < 2) == 1
|
| 215 |
+
assert E(X) == oo
|
| 216 |
+
|
| 217 |
+
def test_precomputed_characteristic_functions():
|
| 218 |
+
import mpmath
|
| 219 |
+
|
| 220 |
+
def test_cf(dist, support_lower_limit, support_upper_limit):
|
| 221 |
+
pdf = density(dist)
|
| 222 |
+
t = S('t')
|
| 223 |
+
x = S('x')
|
| 224 |
+
|
| 225 |
+
# first function is the hardcoded CF of the distribution
|
| 226 |
+
cf1 = lambdify([t], characteristic_function(dist)(t), 'mpmath')
|
| 227 |
+
|
| 228 |
+
# second function is the Fourier transform of the density function
|
| 229 |
+
f = lambdify([x, t], pdf(x)*exp(I*x*t), 'mpmath')
|
| 230 |
+
cf2 = lambda t: mpmath.nsum(lambda x: f(x, t), [
|
| 231 |
+
support_lower_limit, support_upper_limit], maxdegree=10)
|
| 232 |
+
|
| 233 |
+
# compare the two functions at various points
|
| 234 |
+
for test_point in [2, 5, 8, 11]:
|
| 235 |
+
n1 = cf1(test_point)
|
| 236 |
+
n2 = cf2(test_point)
|
| 237 |
+
|
| 238 |
+
assert abs(re(n1) - re(n2)) < 1e-12
|
| 239 |
+
assert abs(im(n1) - im(n2)) < 1e-12
|
| 240 |
+
|
| 241 |
+
test_cf(Geometric('g', Rational(1, 3)), 1, mpmath.inf)
|
| 242 |
+
test_cf(Logarithmic('l', Rational(1, 5)), 1, mpmath.inf)
|
| 243 |
+
test_cf(NegativeBinomial('n', 5, Rational(1, 7)), 0, mpmath.inf)
|
| 244 |
+
test_cf(Poisson('p', 5), 0, mpmath.inf)
|
| 245 |
+
test_cf(YuleSimon('y', 5), 1, mpmath.inf)
|
| 246 |
+
test_cf(Zeta('z', 5), 1, mpmath.inf)
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def test_moment_generating_functions():
|
| 250 |
+
t = S('t')
|
| 251 |
+
|
| 252 |
+
geometric_mgf = moment_generating_function(Geometric('g', S.Half))(t)
|
| 253 |
+
assert geometric_mgf.diff(t).subs(t, 0) == 2
|
| 254 |
+
|
| 255 |
+
logarithmic_mgf = moment_generating_function(Logarithmic('l', S.Half))(t)
|
| 256 |
+
assert logarithmic_mgf.diff(t).subs(t, 0) == 1/log(2)
|
| 257 |
+
|
| 258 |
+
negative_binomial_mgf = moment_generating_function(
|
| 259 |
+
NegativeBinomial('n', 5, Rational(1, 3)))(t)
|
| 260 |
+
assert negative_binomial_mgf.diff(t).subs(t, 0) == Rational(10, 1)
|
| 261 |
+
|
| 262 |
+
poisson_mgf = moment_generating_function(Poisson('p', 5))(t)
|
| 263 |
+
assert poisson_mgf.diff(t).subs(t, 0) == 5
|
| 264 |
+
|
| 265 |
+
skellam_mgf = moment_generating_function(Skellam('s', 1, 1))(t)
|
| 266 |
+
assert skellam_mgf.diff(t).subs(
|
| 267 |
+
t, 2) == (-exp(-2) + exp(2))*exp(-2 + exp(-2) + exp(2))
|
| 268 |
+
|
| 269 |
+
yule_simon_mgf = moment_generating_function(YuleSimon('y', 3))(t)
|
| 270 |
+
assert simplify(yule_simon_mgf.diff(t).subs(t, 0)) == Rational(3, 2)
|
| 271 |
+
|
| 272 |
+
zeta_mgf = moment_generating_function(Zeta('z', 5))(t)
|
| 273 |
+
assert zeta_mgf.diff(t).subs(t, 0) == pi**4/(90*zeta(5))
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
def test_Or():
|
| 277 |
+
X = Geometric('X', S.Half)
|
| 278 |
+
assert P(Or(X < 3, X > 4)) == Rational(13, 16)
|
| 279 |
+
assert P(Or(X > 2, X > 1)) == P(X > 1)
|
| 280 |
+
assert P(Or(X >= 3, X < 3)) == 1
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
def test_where():
|
| 284 |
+
X = Geometric('X', Rational(1, 5))
|
| 285 |
+
Y = Poisson('Y', 4)
|
| 286 |
+
assert where(X**2 > 4).set == Range(3, S.Infinity, 1)
|
| 287 |
+
assert where(X**2 >= 4).set == Range(2, S.Infinity, 1)
|
| 288 |
+
assert where(Y**2 < 9).set == Range(0, 3, 1)
|
| 289 |
+
assert where(Y**2 <= 9).set == Range(0, 4, 1)
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
def test_conditional():
|
| 293 |
+
X = Geometric('X', Rational(2, 3))
|
| 294 |
+
Y = Poisson('Y', 3)
|
| 295 |
+
assert P(X > 2, X > 3) == 1
|
| 296 |
+
assert P(X > 3, X > 2) == Rational(1, 3)
|
| 297 |
+
assert P(Y > 2, Y < 2) == 0
|
| 298 |
+
assert P(Eq(Y, 3), Y >= 0) == 9*exp(-3)/2
|
| 299 |
+
assert P(Eq(Y, 3), Eq(Y, 2)) == 0
|
| 300 |
+
assert P(X < 2, Eq(X, 2)) == 0
|
| 301 |
+
assert P(X > 2, Eq(X, 3)) == 1
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def test_product_spaces():
|
| 305 |
+
X1 = Geometric('X1', S.Half)
|
| 306 |
+
X2 = Geometric('X2', Rational(1, 3))
|
| 307 |
+
assert str(P(X1 + X2 < 3).rewrite(Sum)) == (
|
| 308 |
+
"Sum(Piecewise((1/(4*2**n), n >= -1), (0, True)), (n, -oo, -1))/3")
|
| 309 |
+
assert str(P(X1 + X2 > 3).rewrite(Sum)) == (
|
| 310 |
+
'Sum(Piecewise((2**(X2 - n - 2)*(2/3)**(X2 - 1)/6, '
|
| 311 |
+
'X2 - n <= 2), (0, True)), (X2, 1, oo), (n, 1, oo))')
|
| 312 |
+
assert P(Eq(X1 + X2, 3)) == Rational(1, 12)
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_error_prop.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.function import Function
|
| 2 |
+
from sympy.core.symbol import symbols
|
| 3 |
+
from sympy.functions.elementary.exponential import exp
|
| 4 |
+
from sympy.stats.error_prop import variance_prop
|
| 5 |
+
from sympy.stats.symbolic_probability import (RandomSymbol, Variance,
|
| 6 |
+
Covariance)
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def test_variance_prop():
|
| 10 |
+
x, y, z = symbols('x y z')
|
| 11 |
+
phi, t = consts = symbols('phi t')
|
| 12 |
+
a = RandomSymbol(x)
|
| 13 |
+
var_x = Variance(a)
|
| 14 |
+
var_y = Variance(RandomSymbol(y))
|
| 15 |
+
var_z = Variance(RandomSymbol(z))
|
| 16 |
+
f = Function('f')(x)
|
| 17 |
+
cases = {
|
| 18 |
+
x + y: var_x + var_y,
|
| 19 |
+
a + y: var_x + var_y,
|
| 20 |
+
x + y + z: var_x + var_y + var_z,
|
| 21 |
+
2*x: 4*var_x,
|
| 22 |
+
x*y: var_x*y**2 + var_y*x**2,
|
| 23 |
+
1/x: var_x/x**4,
|
| 24 |
+
x/y: (var_x*y**2 + var_y*x**2)/y**4,
|
| 25 |
+
exp(x): var_x*exp(2*x),
|
| 26 |
+
exp(2*x): 4*var_x*exp(4*x),
|
| 27 |
+
exp(-x*t): t**2*var_x*exp(-2*t*x),
|
| 28 |
+
f: Variance(f),
|
| 29 |
+
}
|
| 30 |
+
for inp, out in cases.items():
|
| 31 |
+
obs = variance_prop(inp, consts=consts)
|
| 32 |
+
assert out == obs
|
| 33 |
+
|
| 34 |
+
def test_variance_prop_with_covar():
|
| 35 |
+
x, y, z = symbols('x y z')
|
| 36 |
+
phi, t = consts = symbols('phi t')
|
| 37 |
+
a = RandomSymbol(x)
|
| 38 |
+
var_x = Variance(a)
|
| 39 |
+
b = RandomSymbol(y)
|
| 40 |
+
var_y = Variance(b)
|
| 41 |
+
c = RandomSymbol(z)
|
| 42 |
+
var_z = Variance(c)
|
| 43 |
+
covar_x_y = Covariance(a, b)
|
| 44 |
+
covar_x_z = Covariance(a, c)
|
| 45 |
+
covar_y_z = Covariance(b, c)
|
| 46 |
+
cases = {
|
| 47 |
+
x + y: var_x + var_y + 2*covar_x_y,
|
| 48 |
+
a + y: var_x + var_y + 2*covar_x_y,
|
| 49 |
+
x + y + z: var_x + var_y + var_z + \
|
| 50 |
+
2*covar_x_y + 2*covar_x_z + 2*covar_y_z,
|
| 51 |
+
2*x: 4*var_x,
|
| 52 |
+
x*y: var_x*y**2 + var_y*x**2 + 2*covar_x_y/(x*y),
|
| 53 |
+
1/x: var_x/x**4,
|
| 54 |
+
exp(x): var_x*exp(2*x),
|
| 55 |
+
exp(2*x): 4*var_x*exp(4*x),
|
| 56 |
+
exp(-x*t): t**2*var_x*exp(-2*t*x),
|
| 57 |
+
}
|
| 58 |
+
for inp, out in cases.items():
|
| 59 |
+
obs = variance_prop(inp, consts=consts, include_covar=True)
|
| 60 |
+
assert out == obs
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_finite_rv.py
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.containers import (Dict, Tuple)
|
| 3 |
+
from sympy.core.function import Function
|
| 4 |
+
from sympy.core.numbers import (I, Rational, nan)
|
| 5 |
+
from sympy.core.relational import Eq
|
| 6 |
+
from sympy.core.singleton import S
|
| 7 |
+
from sympy.core.symbol import (Dummy, Symbol, symbols)
|
| 8 |
+
from sympy.core.sympify import sympify
|
| 9 |
+
from sympy.functions.combinatorial.factorials import binomial
|
| 10 |
+
from sympy.functions.combinatorial.numbers import harmonic
|
| 11 |
+
from sympy.functions.elementary.exponential import exp
|
| 12 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 13 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 14 |
+
from sympy.functions.elementary.trigonometric import cos
|
| 15 |
+
from sympy.functions.special.beta_functions import beta
|
| 16 |
+
from sympy.logic.boolalg import (And, Or)
|
| 17 |
+
from sympy.polys.polytools import cancel
|
| 18 |
+
from sympy.sets.sets import FiniteSet
|
| 19 |
+
from sympy.simplify.simplify import simplify
|
| 20 |
+
from sympy.matrices import Matrix
|
| 21 |
+
from sympy.stats import (DiscreteUniform, Die, Bernoulli, Coin, Binomial, BetaBinomial,
|
| 22 |
+
Hypergeometric, Rademacher, IdealSoliton, RobustSoliton, P, E, variance,
|
| 23 |
+
covariance, skewness, density, where, FiniteRV, pspace, cdf,
|
| 24 |
+
correlation, moment, cmoment, smoment, characteristic_function,
|
| 25 |
+
moment_generating_function, quantile, kurtosis, median, coskewness)
|
| 26 |
+
from sympy.stats.frv_types import DieDistribution, BinomialDistribution, \
|
| 27 |
+
HypergeometricDistribution
|
| 28 |
+
from sympy.stats.rv import Density
|
| 29 |
+
from sympy.testing.pytest import raises
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def BayesTest(A, B):
|
| 33 |
+
assert P(A, B) == P(And(A, B)) / P(B)
|
| 34 |
+
assert P(A, B) == P(B, A) * P(A) / P(B)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def test_discreteuniform():
|
| 38 |
+
# Symbolic
|
| 39 |
+
a, b, c, t = symbols('a b c t')
|
| 40 |
+
X = DiscreteUniform('X', [a, b, c])
|
| 41 |
+
|
| 42 |
+
assert E(X) == (a + b + c)/3
|
| 43 |
+
assert simplify(variance(X)
|
| 44 |
+
- ((a**2 + b**2 + c**2)/3 - (a/3 + b/3 + c/3)**2)) == 0
|
| 45 |
+
assert P(Eq(X, a)) == P(Eq(X, b)) == P(Eq(X, c)) == S('1/3')
|
| 46 |
+
|
| 47 |
+
Y = DiscreteUniform('Y', range(-5, 5))
|
| 48 |
+
|
| 49 |
+
# Numeric
|
| 50 |
+
assert E(Y) == S('-1/2')
|
| 51 |
+
assert variance(Y) == S('33/4')
|
| 52 |
+
assert median(Y) == FiniteSet(-1, 0)
|
| 53 |
+
|
| 54 |
+
for x in range(-5, 5):
|
| 55 |
+
assert P(Eq(Y, x)) == S('1/10')
|
| 56 |
+
assert P(Y <= x) == S(x + 6)/10
|
| 57 |
+
assert P(Y >= x) == S(5 - x)/10
|
| 58 |
+
|
| 59 |
+
assert dict(density(Die('D', 6)).items()) == \
|
| 60 |
+
dict(density(DiscreteUniform('U', range(1, 7))).items())
|
| 61 |
+
|
| 62 |
+
assert characteristic_function(X)(t) == exp(I*a*t)/3 + exp(I*b*t)/3 + exp(I*c*t)/3
|
| 63 |
+
assert moment_generating_function(X)(t) == exp(a*t)/3 + exp(b*t)/3 + exp(c*t)/3
|
| 64 |
+
# issue 18611
|
| 65 |
+
raises(ValueError, lambda: DiscreteUniform('Z', [a, a, a, b, b, c]))
|
| 66 |
+
|
| 67 |
+
def test_dice():
|
| 68 |
+
# TODO: Make iid method!
|
| 69 |
+
X, Y, Z = Die('X', 6), Die('Y', 6), Die('Z', 6)
|
| 70 |
+
a, b, t, p = symbols('a b t p')
|
| 71 |
+
|
| 72 |
+
assert E(X) == 3 + S.Half
|
| 73 |
+
assert variance(X) == Rational(35, 12)
|
| 74 |
+
assert E(X + Y) == 7
|
| 75 |
+
assert E(X + X) == 7
|
| 76 |
+
assert E(a*X + b) == a*E(X) + b
|
| 77 |
+
assert variance(X + Y) == variance(X) + variance(Y) == cmoment(X + Y, 2)
|
| 78 |
+
assert variance(X + X) == 4 * variance(X) == cmoment(X + X, 2)
|
| 79 |
+
assert cmoment(X, 0) == 1
|
| 80 |
+
assert cmoment(4*X, 3) == 64*cmoment(X, 3)
|
| 81 |
+
assert covariance(X, Y) is S.Zero
|
| 82 |
+
assert covariance(X, X + Y) == variance(X)
|
| 83 |
+
assert density(Eq(cos(X*S.Pi), 1))[True] == S.Half
|
| 84 |
+
assert correlation(X, Y) == 0
|
| 85 |
+
assert correlation(X, Y) == correlation(Y, X)
|
| 86 |
+
assert smoment(X + Y, 3) == skewness(X + Y)
|
| 87 |
+
assert smoment(X + Y, 4) == kurtosis(X + Y)
|
| 88 |
+
assert smoment(X, 0) == 1
|
| 89 |
+
assert P(X > 3) == S.Half
|
| 90 |
+
assert P(2*X > 6) == S.Half
|
| 91 |
+
assert P(X > Y) == Rational(5, 12)
|
| 92 |
+
assert P(Eq(X, Y)) == P(Eq(X, 1))
|
| 93 |
+
|
| 94 |
+
assert E(X, X > 3) == 5 == moment(X, 1, 0, X > 3)
|
| 95 |
+
assert E(X, Y > 3) == E(X) == moment(X, 1, 0, Y > 3)
|
| 96 |
+
assert E(X + Y, Eq(X, Y)) == E(2*X)
|
| 97 |
+
assert moment(X, 0) == 1
|
| 98 |
+
assert moment(5*X, 2) == 25*moment(X, 2)
|
| 99 |
+
assert quantile(X)(p) == Piecewise((nan, (p > 1) | (p < 0)),\
|
| 100 |
+
(S.One, p <= Rational(1, 6)), (S(2), p <= Rational(1, 3)), (S(3), p <= S.Half),\
|
| 101 |
+
(S(4), p <= Rational(2, 3)), (S(5), p <= Rational(5, 6)), (S(6), p <= 1))
|
| 102 |
+
|
| 103 |
+
assert P(X > 3, X > 3) is S.One
|
| 104 |
+
assert P(X > Y, Eq(Y, 6)) is S.Zero
|
| 105 |
+
assert P(Eq(X + Y, 12)) == Rational(1, 36)
|
| 106 |
+
assert P(Eq(X + Y, 12), Eq(X, 6)) == Rational(1, 6)
|
| 107 |
+
|
| 108 |
+
assert density(X + Y) == density(Y + Z) != density(X + X)
|
| 109 |
+
d = density(2*X + Y**Z)
|
| 110 |
+
assert d[S(22)] == Rational(1, 108) and d[S(4100)] == Rational(1, 216) and S(3130) not in d
|
| 111 |
+
|
| 112 |
+
assert pspace(X).domain.as_boolean() == Or(
|
| 113 |
+
*[Eq(X.symbol, i) for i in [1, 2, 3, 4, 5, 6]])
|
| 114 |
+
|
| 115 |
+
assert where(X > 3).set == FiniteSet(4, 5, 6)
|
| 116 |
+
|
| 117 |
+
assert characteristic_function(X)(t) == exp(6*I*t)/6 + exp(5*I*t)/6 + exp(4*I*t)/6 + exp(3*I*t)/6 + exp(2*I*t)/6 + exp(I*t)/6
|
| 118 |
+
assert moment_generating_function(X)(t) == exp(6*t)/6 + exp(5*t)/6 + exp(4*t)/6 + exp(3*t)/6 + exp(2*t)/6 + exp(t)/6
|
| 119 |
+
assert median(X) == FiniteSet(3, 4)
|
| 120 |
+
D = Die('D', 7)
|
| 121 |
+
assert median(D) == FiniteSet(4)
|
| 122 |
+
# Bayes test for die
|
| 123 |
+
BayesTest(X > 3, X + Y < 5)
|
| 124 |
+
BayesTest(Eq(X - Y, Z), Z > Y)
|
| 125 |
+
BayesTest(X > 3, X > 2)
|
| 126 |
+
|
| 127 |
+
# arg test for die
|
| 128 |
+
raises(ValueError, lambda: Die('X', -1)) # issue 8105: negative sides.
|
| 129 |
+
raises(ValueError, lambda: Die('X', 0))
|
| 130 |
+
raises(ValueError, lambda: Die('X', 1.5)) # issue 8103: non integer sides.
|
| 131 |
+
|
| 132 |
+
# symbolic test for die
|
| 133 |
+
n, k = symbols('n, k', positive=True)
|
| 134 |
+
D = Die('D', n)
|
| 135 |
+
dens = density(D).dict
|
| 136 |
+
assert dens == Density(DieDistribution(n))
|
| 137 |
+
assert set(dens.subs(n, 4).doit().keys()) == {1, 2, 3, 4}
|
| 138 |
+
assert set(dens.subs(n, 4).doit().values()) == {Rational(1, 4)}
|
| 139 |
+
k = Dummy('k', integer=True)
|
| 140 |
+
assert E(D).dummy_eq(
|
| 141 |
+
Sum(Piecewise((k/n, k <= n), (0, True)), (k, 1, n)))
|
| 142 |
+
assert variance(D).subs(n, 6).doit() == Rational(35, 12)
|
| 143 |
+
|
| 144 |
+
ki = Dummy('ki')
|
| 145 |
+
cumuf = cdf(D)(k)
|
| 146 |
+
assert cumuf.dummy_eq(
|
| 147 |
+
Sum(Piecewise((1/n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, k)))
|
| 148 |
+
assert cumuf.subs({n: 6, k: 2}).doit() == Rational(1, 3)
|
| 149 |
+
|
| 150 |
+
t = Dummy('t')
|
| 151 |
+
cf = characteristic_function(D)(t)
|
| 152 |
+
assert cf.dummy_eq(
|
| 153 |
+
Sum(Piecewise((exp(ki*I*t)/n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n)))
|
| 154 |
+
assert cf.subs(n, 3).doit() == exp(3*I*t)/3 + exp(2*I*t)/3 + exp(I*t)/3
|
| 155 |
+
mgf = moment_generating_function(D)(t)
|
| 156 |
+
assert mgf.dummy_eq(
|
| 157 |
+
Sum(Piecewise((exp(ki*t)/n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n)))
|
| 158 |
+
assert mgf.subs(n, 3).doit() == exp(3*t)/3 + exp(2*t)/3 + exp(t)/3
|
| 159 |
+
|
| 160 |
+
def test_given():
|
| 161 |
+
X = Die('X', 6)
|
| 162 |
+
assert density(X, X > 5) == {S(6): S.One}
|
| 163 |
+
assert where(X > 2, X > 5).as_boolean() == Eq(X.symbol, 6)
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def test_domains():
|
| 167 |
+
X, Y = Die('x', 6), Die('y', 6)
|
| 168 |
+
x, y = X.symbol, Y.symbol
|
| 169 |
+
# Domains
|
| 170 |
+
d = where(X > Y)
|
| 171 |
+
assert d.condition == (x > y)
|
| 172 |
+
d = where(And(X > Y, Y > 3))
|
| 173 |
+
assert d.as_boolean() == Or(And(Eq(x, 5), Eq(y, 4)), And(Eq(x, 6),
|
| 174 |
+
Eq(y, 5)), And(Eq(x, 6), Eq(y, 4)))
|
| 175 |
+
assert len(d.elements) == 3
|
| 176 |
+
|
| 177 |
+
assert len(pspace(X + Y).domain.elements) == 36
|
| 178 |
+
|
| 179 |
+
Z = Die('x', 4)
|
| 180 |
+
|
| 181 |
+
raises(ValueError, lambda: P(X > Z)) # Two domains with same internal symbol
|
| 182 |
+
|
| 183 |
+
assert pspace(X + Y).domain.set == FiniteSet(1, 2, 3, 4, 5, 6)**2
|
| 184 |
+
|
| 185 |
+
assert where(X > 3).set == FiniteSet(4, 5, 6)
|
| 186 |
+
assert X.pspace.domain.dict == FiniteSet(
|
| 187 |
+
*[Dict({X.symbol: i}) for i in range(1, 7)])
|
| 188 |
+
|
| 189 |
+
assert where(X > Y).dict == FiniteSet(*[Dict({X.symbol: i, Y.symbol: j})
|
| 190 |
+
for i in range(1, 7) for j in range(1, 7) if i > j])
|
| 191 |
+
|
| 192 |
+
def test_bernoulli():
|
| 193 |
+
p, a, b, t = symbols('p a b t')
|
| 194 |
+
X = Bernoulli('B', p, a, b)
|
| 195 |
+
|
| 196 |
+
assert E(X) == a*p + b*(-p + 1)
|
| 197 |
+
assert density(X)[a] == p
|
| 198 |
+
assert density(X)[b] == 1 - p
|
| 199 |
+
assert characteristic_function(X)(t) == p * exp(I * a * t) + (-p + 1) * exp(I * b * t)
|
| 200 |
+
assert moment_generating_function(X)(t) == p * exp(a * t) + (-p + 1) * exp(b * t)
|
| 201 |
+
|
| 202 |
+
X = Bernoulli('B', p, 1, 0)
|
| 203 |
+
z = Symbol("z")
|
| 204 |
+
|
| 205 |
+
assert E(X) == p
|
| 206 |
+
assert simplify(variance(X)) == p*(1 - p)
|
| 207 |
+
assert E(a*X + b) == a*E(X) + b
|
| 208 |
+
assert simplify(variance(a*X + b)) == simplify(a**2 * variance(X))
|
| 209 |
+
assert quantile(X)(z) == Piecewise((nan, (z > 1) | (z < 0)), (0, z <= 1 - p), (1, z <= 1))
|
| 210 |
+
Y = Bernoulli('Y', Rational(1, 2))
|
| 211 |
+
assert median(Y) == FiniteSet(0, 1)
|
| 212 |
+
Z = Bernoulli('Z', Rational(2, 3))
|
| 213 |
+
assert median(Z) == FiniteSet(1)
|
| 214 |
+
raises(ValueError, lambda: Bernoulli('B', 1.5))
|
| 215 |
+
raises(ValueError, lambda: Bernoulli('B', -0.5))
|
| 216 |
+
|
| 217 |
+
#issue 8248
|
| 218 |
+
assert X.pspace.compute_expectation(1) == 1
|
| 219 |
+
|
| 220 |
+
p = Rational(1, 5)
|
| 221 |
+
X = Binomial('X', 5, p)
|
| 222 |
+
Y = Binomial('Y', 7, 2*p)
|
| 223 |
+
Z = Binomial('Z', 9, 3*p)
|
| 224 |
+
assert coskewness(Y + Z, X + Y, X + Z).simplify() == 0
|
| 225 |
+
assert coskewness(Y + 2*X + Z, X + 2*Y + Z, X + 2*Z + Y).simplify() == \
|
| 226 |
+
sqrt(1529)*Rational(12, 16819)
|
| 227 |
+
assert coskewness(Y + 2*X + Z, X + 2*Y + Z, X + 2*Z + Y, X < 2).simplify() \
|
| 228 |
+
== -sqrt(357451121)*Rational(2812, 4646864573)
|
| 229 |
+
|
| 230 |
+
def test_cdf():
|
| 231 |
+
D = Die('D', 6)
|
| 232 |
+
o = S.One
|
| 233 |
+
|
| 234 |
+
assert cdf(
|
| 235 |
+
D) == sympify({1: o/6, 2: o/3, 3: o/2, 4: 2*o/3, 5: 5*o/6, 6: o})
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
def test_coins():
|
| 239 |
+
C, D = Coin('C'), Coin('D')
|
| 240 |
+
H, T = symbols('H, T')
|
| 241 |
+
assert P(Eq(C, D)) == S.Half
|
| 242 |
+
assert density(Tuple(C, D)) == {(H, H): Rational(1, 4), (H, T): Rational(1, 4),
|
| 243 |
+
(T, H): Rational(1, 4), (T, T): Rational(1, 4)}
|
| 244 |
+
assert dict(density(C).items()) == {H: S.Half, T: S.Half}
|
| 245 |
+
|
| 246 |
+
F = Coin('F', Rational(1, 10))
|
| 247 |
+
assert P(Eq(F, H)) == Rational(1, 10)
|
| 248 |
+
|
| 249 |
+
d = pspace(C).domain
|
| 250 |
+
|
| 251 |
+
assert d.as_boolean() == Or(Eq(C.symbol, H), Eq(C.symbol, T))
|
| 252 |
+
|
| 253 |
+
raises(ValueError, lambda: P(C > D)) # Can't intelligently compare H to T
|
| 254 |
+
|
| 255 |
+
def test_binomial_verify_parameters():
|
| 256 |
+
raises(ValueError, lambda: Binomial('b', .2, .5))
|
| 257 |
+
raises(ValueError, lambda: Binomial('b', 3, 1.5))
|
| 258 |
+
|
| 259 |
+
def test_binomial_numeric():
|
| 260 |
+
nvals = range(5)
|
| 261 |
+
pvals = [0, Rational(1, 4), S.Half, Rational(3, 4), 1]
|
| 262 |
+
|
| 263 |
+
for n in nvals:
|
| 264 |
+
for p in pvals:
|
| 265 |
+
X = Binomial('X', n, p)
|
| 266 |
+
assert E(X) == n*p
|
| 267 |
+
assert variance(X) == n*p*(1 - p)
|
| 268 |
+
if n > 0 and 0 < p < 1:
|
| 269 |
+
assert skewness(X) == (1 - 2*p)/sqrt(n*p*(1 - p))
|
| 270 |
+
assert kurtosis(X) == 3 + (1 - 6*p*(1 - p))/(n*p*(1 - p))
|
| 271 |
+
for k in range(n + 1):
|
| 272 |
+
assert P(Eq(X, k)) == binomial(n, k)*p**k*(1 - p)**(n - k)
|
| 273 |
+
|
| 274 |
+
def test_binomial_quantile():
|
| 275 |
+
X = Binomial('X', 50, S.Half)
|
| 276 |
+
assert quantile(X)(0.95) == S(31)
|
| 277 |
+
assert median(X) == FiniteSet(25)
|
| 278 |
+
|
| 279 |
+
X = Binomial('X', 5, S.Half)
|
| 280 |
+
p = Symbol("p", positive=True)
|
| 281 |
+
assert quantile(X)(p) == Piecewise((nan, p > S.One), (S.Zero, p <= Rational(1, 32)),\
|
| 282 |
+
(S.One, p <= Rational(3, 16)), (S(2), p <= S.Half), (S(3), p <= Rational(13, 16)),\
|
| 283 |
+
(S(4), p <= Rational(31, 32)), (S(5), p <= S.One))
|
| 284 |
+
assert median(X) == FiniteSet(2, 3)
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def test_binomial_symbolic():
|
| 288 |
+
n = 2
|
| 289 |
+
p = symbols('p', positive=True)
|
| 290 |
+
X = Binomial('X', n, p)
|
| 291 |
+
t = Symbol('t')
|
| 292 |
+
|
| 293 |
+
assert simplify(E(X)) == n*p == simplify(moment(X, 1))
|
| 294 |
+
assert simplify(variance(X)) == n*p*(1 - p) == simplify(cmoment(X, 2))
|
| 295 |
+
assert cancel(skewness(X) - (1 - 2*p)/sqrt(n*p*(1 - p))) == 0
|
| 296 |
+
assert cancel((kurtosis(X)) - (3 + (1 - 6*p*(1 - p))/(n*p*(1 - p)))) == 0
|
| 297 |
+
assert characteristic_function(X)(t) == p ** 2 * exp(2 * I * t) + 2 * p * (-p + 1) * exp(I * t) + (-p + 1) ** 2
|
| 298 |
+
assert moment_generating_function(X)(t) == p ** 2 * exp(2 * t) + 2 * p * (-p + 1) * exp(t) + (-p + 1) ** 2
|
| 299 |
+
|
| 300 |
+
# Test ability to change success/failure winnings
|
| 301 |
+
H, T = symbols('H T')
|
| 302 |
+
Y = Binomial('Y', n, p, succ=H, fail=T)
|
| 303 |
+
assert simplify(E(Y) - (n*(H*p + T*(1 - p)))) == 0
|
| 304 |
+
|
| 305 |
+
# test symbolic dimensions
|
| 306 |
+
n = symbols('n')
|
| 307 |
+
B = Binomial('B', n, p)
|
| 308 |
+
raises(NotImplementedError, lambda: P(B > 2))
|
| 309 |
+
assert density(B).dict == Density(BinomialDistribution(n, p, 1, 0))
|
| 310 |
+
assert set(density(B).dict.subs(n, 4).doit().keys()) == \
|
| 311 |
+
{S.Zero, S.One, S(2), S(3), S(4)}
|
| 312 |
+
assert set(density(B).dict.subs(n, 4).doit().values()) == \
|
| 313 |
+
{(1 - p)**4, 4*p*(1 - p)**3, 6*p**2*(1 - p)**2, 4*p**3*(1 - p), p**4}
|
| 314 |
+
k = Dummy('k', integer=True)
|
| 315 |
+
assert E(B > 2).dummy_eq(
|
| 316 |
+
Sum(Piecewise((k*p**k*(1 - p)**(-k + n)*binomial(n, k), (k >= 0)
|
| 317 |
+
& (k <= n) & (k > 2)), (0, True)), (k, 0, n)))
|
| 318 |
+
|
| 319 |
+
def test_beta_binomial():
|
| 320 |
+
# verify parameters
|
| 321 |
+
raises(ValueError, lambda: BetaBinomial('b', .2, 1, 2))
|
| 322 |
+
raises(ValueError, lambda: BetaBinomial('b', 2, -1, 2))
|
| 323 |
+
raises(ValueError, lambda: BetaBinomial('b', 2, 1, -2))
|
| 324 |
+
assert BetaBinomial('b', 2, 1, 1)
|
| 325 |
+
|
| 326 |
+
# test numeric values
|
| 327 |
+
nvals = range(1,5)
|
| 328 |
+
alphavals = [Rational(1, 4), S.Half, Rational(3, 4), 1, 10]
|
| 329 |
+
betavals = [Rational(1, 4), S.Half, Rational(3, 4), 1, 10]
|
| 330 |
+
|
| 331 |
+
for n in nvals:
|
| 332 |
+
for a in alphavals:
|
| 333 |
+
for b in betavals:
|
| 334 |
+
X = BetaBinomial('X', n, a, b)
|
| 335 |
+
assert E(X) == moment(X, 1)
|
| 336 |
+
assert variance(X) == cmoment(X, 2)
|
| 337 |
+
|
| 338 |
+
# test symbolic
|
| 339 |
+
n, a, b = symbols('a b n')
|
| 340 |
+
assert BetaBinomial('x', n, a, b)
|
| 341 |
+
n = 2 # Because we're using for loops, can't do symbolic n
|
| 342 |
+
a, b = symbols('a b', positive=True)
|
| 343 |
+
X = BetaBinomial('X', n, a, b)
|
| 344 |
+
t = Symbol('t')
|
| 345 |
+
|
| 346 |
+
assert E(X).expand() == moment(X, 1).expand()
|
| 347 |
+
assert variance(X).expand() == cmoment(X, 2).expand()
|
| 348 |
+
assert skewness(X) == smoment(X, 3)
|
| 349 |
+
assert characteristic_function(X)(t) == exp(2*I*t)*beta(a + 2, b)/beta(a, b) +\
|
| 350 |
+
2*exp(I*t)*beta(a + 1, b + 1)/beta(a, b) + beta(a, b + 2)/beta(a, b)
|
| 351 |
+
assert moment_generating_function(X)(t) == exp(2*t)*beta(a + 2, b)/beta(a, b) +\
|
| 352 |
+
2*exp(t)*beta(a + 1, b + 1)/beta(a, b) + beta(a, b + 2)/beta(a, b)
|
| 353 |
+
|
| 354 |
+
def test_hypergeometric_numeric():
|
| 355 |
+
for N in range(1, 5):
|
| 356 |
+
for m in range(0, N + 1):
|
| 357 |
+
for n in range(1, N + 1):
|
| 358 |
+
X = Hypergeometric('X', N, m, n)
|
| 359 |
+
N, m, n = map(sympify, (N, m, n))
|
| 360 |
+
assert sum(density(X).values()) == 1
|
| 361 |
+
assert E(X) == n * m / N
|
| 362 |
+
if N > 1:
|
| 363 |
+
assert variance(X) == n*(m/N)*(N - m)/N*(N - n)/(N - 1)
|
| 364 |
+
# Only test for skewness when defined
|
| 365 |
+
if N > 2 and 0 < m < N and n < N:
|
| 366 |
+
assert skewness(X) == simplify((N - 2*m)*sqrt(N - 1)*(N - 2*n)
|
| 367 |
+
/ (sqrt(n*m*(N - m)*(N - n))*(N - 2)))
|
| 368 |
+
|
| 369 |
+
def test_hypergeometric_symbolic():
|
| 370 |
+
N, m, n = symbols('N, m, n')
|
| 371 |
+
H = Hypergeometric('H', N, m, n)
|
| 372 |
+
dens = density(H).dict
|
| 373 |
+
expec = E(H > 2)
|
| 374 |
+
assert dens == Density(HypergeometricDistribution(N, m, n))
|
| 375 |
+
assert dens.subs(N, 5).doit() == Density(HypergeometricDistribution(5, m, n))
|
| 376 |
+
assert set(dens.subs({N: 3, m: 2, n: 1}).doit().keys()) == {S.Zero, S.One}
|
| 377 |
+
assert set(dens.subs({N: 3, m: 2, n: 1}).doit().values()) == {Rational(1, 3), Rational(2, 3)}
|
| 378 |
+
k = Dummy('k', integer=True)
|
| 379 |
+
assert expec.dummy_eq(
|
| 380 |
+
Sum(Piecewise((k*binomial(m, k)*binomial(N - m, -k + n)
|
| 381 |
+
/binomial(N, n), k > 2), (0, True)), (k, 0, n)))
|
| 382 |
+
|
| 383 |
+
def test_rademacher():
|
| 384 |
+
X = Rademacher('X')
|
| 385 |
+
t = Symbol('t')
|
| 386 |
+
|
| 387 |
+
assert E(X) == 0
|
| 388 |
+
assert variance(X) == 1
|
| 389 |
+
assert density(X)[-1] == S.Half
|
| 390 |
+
assert density(X)[1] == S.Half
|
| 391 |
+
assert characteristic_function(X)(t) == exp(I*t)/2 + exp(-I*t)/2
|
| 392 |
+
assert moment_generating_function(X)(t) == exp(t) / 2 + exp(-t) / 2
|
| 393 |
+
|
| 394 |
+
def test_ideal_soliton():
|
| 395 |
+
raises(ValueError, lambda : IdealSoliton('sol', -12))
|
| 396 |
+
raises(ValueError, lambda : IdealSoliton('sol', 13.2))
|
| 397 |
+
raises(ValueError, lambda : IdealSoliton('sol', 0))
|
| 398 |
+
f = Function('f')
|
| 399 |
+
raises(ValueError, lambda : density(IdealSoliton('sol', 10)).pmf(f))
|
| 400 |
+
|
| 401 |
+
k = Symbol('k', integer=True, positive=True)
|
| 402 |
+
x = Symbol('x', integer=True, positive=True)
|
| 403 |
+
t = Symbol('t')
|
| 404 |
+
sol = IdealSoliton('sol', k)
|
| 405 |
+
assert density(sol).low == S.One
|
| 406 |
+
assert density(sol).high == k
|
| 407 |
+
assert density(sol).dict == Density(density(sol))
|
| 408 |
+
assert density(sol).pmf(x) == Piecewise((1/k, Eq(x, 1)), (1/(x*(x - 1)), k >= x), (0, True))
|
| 409 |
+
|
| 410 |
+
k_vals = [5, 20, 50, 100, 1000]
|
| 411 |
+
for i in k_vals:
|
| 412 |
+
assert E(sol.subs(k, i)) == harmonic(i) == moment(sol.subs(k, i), 1)
|
| 413 |
+
assert variance(sol.subs(k, i)) == (i - 1) + harmonic(i) - harmonic(i)**2 == cmoment(sol.subs(k, i),2)
|
| 414 |
+
assert skewness(sol.subs(k, i)) == smoment(sol.subs(k, i), 3)
|
| 415 |
+
assert kurtosis(sol.subs(k, i)) == smoment(sol.subs(k, i), 4)
|
| 416 |
+
|
| 417 |
+
assert exp(I*t)/10 + Sum(exp(I*t*x)/(x*x - x), (x, 2, k)).subs(k, 10).doit() == characteristic_function(sol.subs(k, 10))(t)
|
| 418 |
+
assert exp(t)/10 + Sum(exp(t*x)/(x*x - x), (x, 2, k)).subs(k, 10).doit() == moment_generating_function(sol.subs(k, 10))(t)
|
| 419 |
+
|
| 420 |
+
def test_robust_soliton():
|
| 421 |
+
raises(ValueError, lambda : RobustSoliton('robSol', -12, 0.1, 0.02))
|
| 422 |
+
raises(ValueError, lambda : RobustSoliton('robSol', 13, 1.89, 0.1))
|
| 423 |
+
raises(ValueError, lambda : RobustSoliton('robSol', 15, 0.6, -2.31))
|
| 424 |
+
f = Function('f')
|
| 425 |
+
raises(ValueError, lambda : density(RobustSoliton('robSol', 15, 0.6, 0.1)).pmf(f))
|
| 426 |
+
|
| 427 |
+
k = Symbol('k', integer=True, positive=True)
|
| 428 |
+
delta = Symbol('delta', positive=True)
|
| 429 |
+
c = Symbol('c', positive=True)
|
| 430 |
+
robSol = RobustSoliton('robSol', k, delta, c)
|
| 431 |
+
assert density(robSol).low == 1
|
| 432 |
+
assert density(robSol).high == k
|
| 433 |
+
|
| 434 |
+
k_vals = [10, 20, 50]
|
| 435 |
+
delta_vals = [0.2, 0.4, 0.6]
|
| 436 |
+
c_vals = [0.01, 0.03, 0.05]
|
| 437 |
+
for x in k_vals:
|
| 438 |
+
for y in delta_vals:
|
| 439 |
+
for z in c_vals:
|
| 440 |
+
assert E(robSol.subs({k: x, delta: y, c: z})) == moment(robSol.subs({k: x, delta: y, c: z}), 1)
|
| 441 |
+
assert variance(robSol.subs({k: x, delta: y, c: z})) == cmoment(robSol.subs({k: x, delta: y, c: z}), 2)
|
| 442 |
+
assert skewness(robSol.subs({k: x, delta: y, c: z})) == smoment(robSol.subs({k: x, delta: y, c: z}), 3)
|
| 443 |
+
assert kurtosis(robSol.subs({k: x, delta: y, c: z})) == smoment(robSol.subs({k: x, delta: y, c: z}), 4)
|
| 444 |
+
|
| 445 |
+
def test_FiniteRV():
|
| 446 |
+
F = FiniteRV('F', {1: S.Half, 2: Rational(1, 4), 3: Rational(1, 4)}, check=True)
|
| 447 |
+
p = Symbol("p", positive=True)
|
| 448 |
+
|
| 449 |
+
assert dict(density(F).items()) == {S.One: S.Half, S(2): Rational(1, 4), S(3): Rational(1, 4)}
|
| 450 |
+
assert P(F >= 2) == S.Half
|
| 451 |
+
assert quantile(F)(p) == Piecewise((nan, p > S.One), (S.One, p <= S.Half),\
|
| 452 |
+
(S(2), p <= Rational(3, 4)),(S(3), True))
|
| 453 |
+
|
| 454 |
+
assert pspace(F).domain.as_boolean() == Or(
|
| 455 |
+
*[Eq(F.symbol, i) for i in [1, 2, 3]])
|
| 456 |
+
|
| 457 |
+
assert F.pspace.domain.set == FiniteSet(1, 2, 3)
|
| 458 |
+
raises(ValueError, lambda: FiniteRV('F', {1: S.Half, 2: S.Half, 3: S.Half}, check=True))
|
| 459 |
+
raises(ValueError, lambda: FiniteRV('F', {1: S.Half, 2: Rational(-1, 2), 3: S.One}, check=True))
|
| 460 |
+
raises(ValueError, lambda: FiniteRV('F', {1: S.One, 2: Rational(3, 2), 3: S.Zero,\
|
| 461 |
+
4: Rational(-1, 2), 5: Rational(-3, 4), 6: Rational(-1, 4)}, check=True))
|
| 462 |
+
|
| 463 |
+
# purposeful invalid pmf but it should not raise since check=False
|
| 464 |
+
# see test_drv_types.test_ContinuousRV for explanation
|
| 465 |
+
X = FiniteRV('X', {1: 1, 2: 2})
|
| 466 |
+
assert E(X) == 5
|
| 467 |
+
assert P(X <= 2) + P(X > 2) != 1
|
| 468 |
+
|
| 469 |
+
def test_density_call():
|
| 470 |
+
from sympy.abc import p
|
| 471 |
+
x = Bernoulli('x', p)
|
| 472 |
+
d = density(x)
|
| 473 |
+
assert d(0) == 1 - p
|
| 474 |
+
assert d(S.Zero) == 1 - p
|
| 475 |
+
assert d(5) == 0
|
| 476 |
+
|
| 477 |
+
assert 0 in d
|
| 478 |
+
assert 5 not in d
|
| 479 |
+
assert d(S.Zero) == d[S.Zero]
|
| 480 |
+
|
| 481 |
+
|
| 482 |
+
def test_DieDistribution():
|
| 483 |
+
from sympy.abc import x
|
| 484 |
+
X = DieDistribution(6)
|
| 485 |
+
assert X.pmf(S.Half) is S.Zero
|
| 486 |
+
assert X.pmf(x).subs({x: 1}).doit() == Rational(1, 6)
|
| 487 |
+
assert X.pmf(x).subs({x: 7}).doit() == 0
|
| 488 |
+
assert X.pmf(x).subs({x: -1}).doit() == 0
|
| 489 |
+
assert X.pmf(x).subs({x: Rational(1, 3)}).doit() == 0
|
| 490 |
+
raises(ValueError, lambda: X.pmf(Matrix([0, 0])))
|
| 491 |
+
raises(ValueError, lambda: X.pmf(x**2 - 1))
|
| 492 |
+
|
| 493 |
+
def test_FinitePSpace():
|
| 494 |
+
X = Die('X', 6)
|
| 495 |
+
space = pspace(X)
|
| 496 |
+
assert space.density == DieDistribution(6)
|
| 497 |
+
|
| 498 |
+
def test_symbolic_conditions():
|
| 499 |
+
B = Bernoulli('B', Rational(1, 4))
|
| 500 |
+
D = Die('D', 4)
|
| 501 |
+
b, n = symbols('b, n')
|
| 502 |
+
Y = P(Eq(B, b))
|
| 503 |
+
Z = E(D > n)
|
| 504 |
+
assert Y == \
|
| 505 |
+
Piecewise((Rational(1, 4), Eq(b, 1)), (0, True)) + \
|
| 506 |
+
Piecewise((Rational(3, 4), Eq(b, 0)), (0, True))
|
| 507 |
+
assert Z == \
|
| 508 |
+
Piecewise((Rational(1, 4), n < 1), (0, True)) + Piecewise((S.Half, n < 2), (0, True)) + \
|
| 509 |
+
Piecewise((Rational(3, 4), n < 3), (0, True)) + Piecewise((S.One, n < 4), (0, True))
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_joint_rv.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.products import Product
|
| 2 |
+
from sympy.concrete.summations import Sum
|
| 3 |
+
from sympy.core.numbers import (Rational, oo, pi)
|
| 4 |
+
from sympy.core.relational import Eq
|
| 5 |
+
from sympy.core.singleton import S
|
| 6 |
+
from sympy.core.symbol import symbols
|
| 7 |
+
from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial)
|
| 8 |
+
from sympy.functions.elementary.complexes import polar_lift
|
| 9 |
+
from sympy.functions.elementary.exponential import exp
|
| 10 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 11 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 12 |
+
from sympy.functions.special.bessel import besselk
|
| 13 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 14 |
+
from sympy.matrices.dense import eye
|
| 15 |
+
from sympy.matrices.expressions.determinant import Determinant
|
| 16 |
+
from sympy.sets.fancysets import Range
|
| 17 |
+
from sympy.sets.sets import (Interval, ProductSet)
|
| 18 |
+
from sympy.simplify.simplify import simplify
|
| 19 |
+
from sympy.tensor.indexed import (Indexed, IndexedBase)
|
| 20 |
+
from sympy.core.numbers import comp
|
| 21 |
+
from sympy.integrals.integrals import integrate
|
| 22 |
+
from sympy.matrices import Matrix, MatrixSymbol
|
| 23 |
+
from sympy.matrices.expressions.matexpr import MatrixElement
|
| 24 |
+
from sympy.stats import density, median, marginal_distribution, Normal, Laplace, E, sample
|
| 25 |
+
from sympy.stats.joint_rv_types import (JointRV, MultivariateNormalDistribution,
|
| 26 |
+
JointDistributionHandmade, MultivariateT, NormalGamma,
|
| 27 |
+
GeneralizedMultivariateLogGammaOmega as GMVLGO, MultivariateBeta,
|
| 28 |
+
GeneralizedMultivariateLogGamma as GMVLG, MultivariateEwens,
|
| 29 |
+
Multinomial, NegativeMultinomial, MultivariateNormal,
|
| 30 |
+
MultivariateLaplace)
|
| 31 |
+
from sympy.testing.pytest import raises, XFAIL, skip, slow
|
| 32 |
+
from sympy.external import import_module
|
| 33 |
+
|
| 34 |
+
from sympy.abc import x, y
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def test_Normal():
|
| 39 |
+
m = Normal('A', [1, 2], [[1, 0], [0, 1]])
|
| 40 |
+
A = MultivariateNormal('A', [1, 2], [[1, 0], [0, 1]])
|
| 41 |
+
assert m == A
|
| 42 |
+
assert density(m)(1, 2) == 1/(2*pi)
|
| 43 |
+
assert m.pspace.distribution.set == ProductSet(S.Reals, S.Reals)
|
| 44 |
+
raises (ValueError, lambda:m[2])
|
| 45 |
+
n = Normal('B', [1, 2, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
| 46 |
+
p = Normal('C', Matrix([1, 2]), Matrix([[1, 0], [0, 1]]))
|
| 47 |
+
assert density(m)(x, y) == density(p)(x, y)
|
| 48 |
+
assert marginal_distribution(n, 0, 1)(1, 2) == 1/(2*pi)
|
| 49 |
+
raises(ValueError, lambda: marginal_distribution(m))
|
| 50 |
+
assert integrate(density(m)(x, y), (x, -oo, oo), (y, -oo, oo)).evalf() == 1.0
|
| 51 |
+
N = Normal('N', [1, 2], [[x, 0], [0, y]])
|
| 52 |
+
assert density(N)(0, 0) == exp(-((4*x + y)/(2*x*y)))/(2*pi*sqrt(x*y))
|
| 53 |
+
|
| 54 |
+
raises (ValueError, lambda: Normal('M', [1, 2], [[1, 1], [1, -1]]))
|
| 55 |
+
# symbolic
|
| 56 |
+
n = symbols('n', integer=True, positive=True)
|
| 57 |
+
mu = MatrixSymbol('mu', n, 1)
|
| 58 |
+
sigma = MatrixSymbol('sigma', n, n)
|
| 59 |
+
X = Normal('X', mu, sigma)
|
| 60 |
+
assert density(X) == MultivariateNormalDistribution(mu, sigma)
|
| 61 |
+
raises (NotImplementedError, lambda: median(m))
|
| 62 |
+
# Below tests should work after issue #17267 is resolved
|
| 63 |
+
# assert E(X) == mu
|
| 64 |
+
# assert variance(X) == sigma
|
| 65 |
+
|
| 66 |
+
# test symbolic multivariate normal densities
|
| 67 |
+
n = 3
|
| 68 |
+
|
| 69 |
+
Sg = MatrixSymbol('Sg', n, n)
|
| 70 |
+
mu = MatrixSymbol('mu', n, 1)
|
| 71 |
+
obs = MatrixSymbol('obs', n, 1)
|
| 72 |
+
|
| 73 |
+
X = MultivariateNormal('X', mu, Sg)
|
| 74 |
+
density_X = density(X)
|
| 75 |
+
|
| 76 |
+
eval_a = density_X(obs).subs({Sg: eye(3),
|
| 77 |
+
mu: Matrix([0, 0, 0]), obs: Matrix([0, 0, 0])}).doit()
|
| 78 |
+
eval_b = density_X(0, 0, 0).subs({Sg: eye(3), mu: Matrix([0, 0, 0])}).doit()
|
| 79 |
+
|
| 80 |
+
assert eval_a == sqrt(2)/(4*pi**Rational(3/2))
|
| 81 |
+
assert eval_b == sqrt(2)/(4*pi**Rational(3/2))
|
| 82 |
+
|
| 83 |
+
n = symbols('n', integer=True, positive=True)
|
| 84 |
+
|
| 85 |
+
Sg = MatrixSymbol('Sg', n, n)
|
| 86 |
+
mu = MatrixSymbol('mu', n, 1)
|
| 87 |
+
obs = MatrixSymbol('obs', n, 1)
|
| 88 |
+
|
| 89 |
+
X = MultivariateNormal('X', mu, Sg)
|
| 90 |
+
density_X_at_obs = density(X)(obs)
|
| 91 |
+
|
| 92 |
+
expected_density = MatrixElement(
|
| 93 |
+
exp((S(1)/2) * (mu.T - obs.T) * Sg**(-1) * (-mu + obs)) / \
|
| 94 |
+
sqrt((2*pi)**n * Determinant(Sg)), 0, 0)
|
| 95 |
+
|
| 96 |
+
assert density_X_at_obs == expected_density
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def test_MultivariateTDist():
|
| 100 |
+
t1 = MultivariateT('T', [0, 0], [[1, 0], [0, 1]], 2)
|
| 101 |
+
assert(density(t1))(1, 1) == 1/(8*pi)
|
| 102 |
+
assert t1.pspace.distribution.set == ProductSet(S.Reals, S.Reals)
|
| 103 |
+
assert integrate(density(t1)(x, y), (x, -oo, oo), \
|
| 104 |
+
(y, -oo, oo)).evalf() == 1.0
|
| 105 |
+
raises(ValueError, lambda: MultivariateT('T', [1, 2], [[1, 1], [1, -1]], 1))
|
| 106 |
+
t2 = MultivariateT('t2', [1, 2], [[x, 0], [0, y]], 1)
|
| 107 |
+
assert density(t2)(1, 2) == 1/(2*pi*sqrt(x*y))
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def test_multivariate_laplace():
|
| 111 |
+
raises(ValueError, lambda: Laplace('T', [1, 2], [[1, 2], [2, 1]]))
|
| 112 |
+
L = Laplace('L', [1, 0], [[1, 0], [0, 1]])
|
| 113 |
+
L2 = MultivariateLaplace('L2', [1, 0], [[1, 0], [0, 1]])
|
| 114 |
+
assert density(L)(2, 3) == exp(2)*besselk(0, sqrt(39))/pi
|
| 115 |
+
L1 = Laplace('L1', [1, 2], [[x, 0], [0, y]])
|
| 116 |
+
assert density(L1)(0, 1) == \
|
| 117 |
+
exp(2/y)*besselk(0, sqrt((2 + 4/y + 1/x)/y))/(pi*sqrt(x*y))
|
| 118 |
+
assert L.pspace.distribution.set == ProductSet(S.Reals, S.Reals)
|
| 119 |
+
assert L.pspace.distribution == L2.pspace.distribution
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def test_NormalGamma():
|
| 123 |
+
ng = NormalGamma('G', 1, 2, 3, 4)
|
| 124 |
+
assert density(ng)(1, 1) == 32*exp(-4)/sqrt(pi)
|
| 125 |
+
assert ng.pspace.distribution.set == ProductSet(S.Reals, Interval(0, oo))
|
| 126 |
+
raises(ValueError, lambda:NormalGamma('G', 1, 2, 3, -1))
|
| 127 |
+
assert marginal_distribution(ng, 0)(1) == \
|
| 128 |
+
3*sqrt(10)*gamma(Rational(7, 4))/(10*sqrt(pi)*gamma(Rational(5, 4)))
|
| 129 |
+
assert marginal_distribution(ng, y)(1) == exp(Rational(-1, 4))/128
|
| 130 |
+
assert marginal_distribution(ng,[0,1])(x) == x**2*exp(-x/4)/128
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def test_GeneralizedMultivariateLogGammaDistribution():
|
| 134 |
+
h = S.Half
|
| 135 |
+
omega = Matrix([[1, h, h, h],
|
| 136 |
+
[h, 1, h, h],
|
| 137 |
+
[h, h, 1, h],
|
| 138 |
+
[h, h, h, 1]])
|
| 139 |
+
v, l, mu = (4, [1, 2, 3, 4], [1, 2, 3, 4])
|
| 140 |
+
y_1, y_2, y_3, y_4 = symbols('y_1:5', real=True)
|
| 141 |
+
delta = symbols('d', positive=True)
|
| 142 |
+
G = GMVLGO('G', omega, v, l, mu)
|
| 143 |
+
Gd = GMVLG('Gd', delta, v, l, mu)
|
| 144 |
+
dend = ("d**4*Sum(4*24**(-n - 4)*(1 - d)**n*exp((n + 4)*(y_1 + 2*y_2 + 3*y_3 "
|
| 145 |
+
"+ 4*y_4) - exp(y_1) - exp(2*y_2)/2 - exp(3*y_3)/3 - exp(4*y_4)/4)/"
|
| 146 |
+
"(gamma(n + 1)*gamma(n + 4)**3), (n, 0, oo))")
|
| 147 |
+
assert str(density(Gd)(y_1, y_2, y_3, y_4)) == dend
|
| 148 |
+
den = ("5*2**(2/3)*5**(1/3)*Sum(4*24**(-n - 4)*(-2**(2/3)*5**(1/3)/4 + 1)**n*"
|
| 149 |
+
"exp((n + 4)*(y_1 + 2*y_2 + 3*y_3 + 4*y_4) - exp(y_1) - exp(2*y_2)/2 - "
|
| 150 |
+
"exp(3*y_3)/3 - exp(4*y_4)/4)/(gamma(n + 1)*gamma(n + 4)**3), (n, 0, oo))/64")
|
| 151 |
+
assert str(density(G)(y_1, y_2, y_3, y_4)) == den
|
| 152 |
+
marg = ("5*2**(2/3)*5**(1/3)*exp(4*y_1)*exp(-exp(y_1))*Integral(exp(-exp(4*G[3])"
|
| 153 |
+
"/4)*exp(16*G[3])*Integral(exp(-exp(3*G[2])/3)*exp(12*G[2])*Integral(exp("
|
| 154 |
+
"-exp(2*G[1])/2)*exp(8*G[1])*Sum((-1/4)**n*(-4 + 2**(2/3)*5**(1/3"
|
| 155 |
+
"))**n*exp(n*y_1)*exp(2*n*G[1])*exp(3*n*G[2])*exp(4*n*G[3])/(24**n*gamma(n + 1)"
|
| 156 |
+
"*gamma(n + 4)**3), (n, 0, oo)), (G[1], -oo, oo)), (G[2], -oo, oo)), (G[3]"
|
| 157 |
+
", -oo, oo))/5308416")
|
| 158 |
+
assert str(marginal_distribution(G, G[0])(y_1)) == marg
|
| 159 |
+
omega_f1 = Matrix([[1, h, h]])
|
| 160 |
+
omega_f2 = Matrix([[1, h, h, h],
|
| 161 |
+
[h, 1, 2, h],
|
| 162 |
+
[h, h, 1, h],
|
| 163 |
+
[h, h, h, 1]])
|
| 164 |
+
omega_f3 = Matrix([[6, h, h, h],
|
| 165 |
+
[h, 1, 2, h],
|
| 166 |
+
[h, h, 1, h],
|
| 167 |
+
[h, h, h, 1]])
|
| 168 |
+
v_f = symbols("v_f", positive=False, real=True)
|
| 169 |
+
l_f = [1, 2, v_f, 4]
|
| 170 |
+
m_f = [v_f, 2, 3, 4]
|
| 171 |
+
omega_f4 = Matrix([[1, h, h, h, h],
|
| 172 |
+
[h, 1, h, h, h],
|
| 173 |
+
[h, h, 1, h, h],
|
| 174 |
+
[h, h, h, 1, h],
|
| 175 |
+
[h, h, h, h, 1]])
|
| 176 |
+
l_f1 = [1, 2, 3, 4, 5]
|
| 177 |
+
omega_f5 = Matrix([[1]])
|
| 178 |
+
mu_f5 = l_f5 = [1]
|
| 179 |
+
|
| 180 |
+
raises(ValueError, lambda: GMVLGO('G', omega_f1, v, l, mu))
|
| 181 |
+
raises(ValueError, lambda: GMVLGO('G', omega_f2, v, l, mu))
|
| 182 |
+
raises(ValueError, lambda: GMVLGO('G', omega_f3, v, l, mu))
|
| 183 |
+
raises(ValueError, lambda: GMVLGO('G', omega, v_f, l, mu))
|
| 184 |
+
raises(ValueError, lambda: GMVLGO('G', omega, v, l_f, mu))
|
| 185 |
+
raises(ValueError, lambda: GMVLGO('G', omega, v, l, m_f))
|
| 186 |
+
raises(ValueError, lambda: GMVLGO('G', omega_f4, v, l, mu))
|
| 187 |
+
raises(ValueError, lambda: GMVLGO('G', omega, v, l_f1, mu))
|
| 188 |
+
raises(ValueError, lambda: GMVLGO('G', omega_f5, v, l_f5, mu_f5))
|
| 189 |
+
raises(ValueError, lambda: GMVLG('G', Rational(3, 2), v, l, mu))
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def test_MultivariateBeta():
|
| 193 |
+
a1, a2 = symbols('a1, a2', positive=True)
|
| 194 |
+
a1_f, a2_f = symbols('a1, a2', positive=False, real=True)
|
| 195 |
+
mb = MultivariateBeta('B', [a1, a2])
|
| 196 |
+
mb_c = MultivariateBeta('C', a1, a2)
|
| 197 |
+
assert density(mb)(1, 2) == S(2)**(a2 - 1)*gamma(a1 + a2)/\
|
| 198 |
+
(gamma(a1)*gamma(a2))
|
| 199 |
+
assert marginal_distribution(mb_c, 0)(3) == S(3)**(a1 - 1)*gamma(a1 + a2)/\
|
| 200 |
+
(a2*gamma(a1)*gamma(a2))
|
| 201 |
+
raises(ValueError, lambda: MultivariateBeta('b1', [a1_f, a2]))
|
| 202 |
+
raises(ValueError, lambda: MultivariateBeta('b2', [a1, a2_f]))
|
| 203 |
+
raises(ValueError, lambda: MultivariateBeta('b3', [0, 0]))
|
| 204 |
+
raises(ValueError, lambda: MultivariateBeta('b4', [a1_f, a2_f]))
|
| 205 |
+
assert mb.pspace.distribution.set == ProductSet(Interval(0, 1), Interval(0, 1))
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
def test_MultivariateEwens():
|
| 209 |
+
n, theta, i = symbols('n theta i', positive=True)
|
| 210 |
+
|
| 211 |
+
# tests for integer dimensions
|
| 212 |
+
theta_f = symbols('t_f', negative=True)
|
| 213 |
+
a = symbols('a_1:4', positive = True, integer = True)
|
| 214 |
+
ed = MultivariateEwens('E', 3, theta)
|
| 215 |
+
assert density(ed)(a[0], a[1], a[2]) == Piecewise((6*2**(-a[1])*3**(-a[2])*
|
| 216 |
+
theta**a[0]*theta**a[1]*theta**a[2]/
|
| 217 |
+
(theta*(theta + 1)*(theta + 2)*
|
| 218 |
+
factorial(a[0])*factorial(a[1])*
|
| 219 |
+
factorial(a[2])), Eq(a[0] + 2*a[1] +
|
| 220 |
+
3*a[2], 3)), (0, True))
|
| 221 |
+
assert marginal_distribution(ed, ed[1])(a[1]) == Piecewise((6*2**(-a[1])*
|
| 222 |
+
theta**a[1]/((theta + 1)*
|
| 223 |
+
(theta + 2)*factorial(a[1])),
|
| 224 |
+
Eq(2*a[1] + 1, 3)), (0, True))
|
| 225 |
+
raises(ValueError, lambda: MultivariateEwens('e1', 5, theta_f))
|
| 226 |
+
assert ed.pspace.distribution.set == ProductSet(Range(0, 4, 1),
|
| 227 |
+
Range(0, 2, 1), Range(0, 2, 1))
|
| 228 |
+
|
| 229 |
+
# tests for symbolic dimensions
|
| 230 |
+
eds = MultivariateEwens('E', n, theta)
|
| 231 |
+
a = IndexedBase('a')
|
| 232 |
+
j, k = symbols('j, k')
|
| 233 |
+
den = Piecewise((factorial(n)*Product(theta**a[j]*(j + 1)**(-a[j])/
|
| 234 |
+
factorial(a[j]), (j, 0, n - 1))/RisingFactorial(theta, n),
|
| 235 |
+
Eq(n, Sum((k + 1)*a[k], (k, 0, n - 1)))), (0, True))
|
| 236 |
+
assert density(eds)(a).dummy_eq(den)
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def test_Multinomial():
|
| 240 |
+
n, x1, x2, x3, x4 = symbols('n, x1, x2, x3, x4', nonnegative=True, integer=True)
|
| 241 |
+
p1, p2, p3, p4 = symbols('p1, p2, p3, p4', positive=True)
|
| 242 |
+
p1_f, n_f = symbols('p1_f, n_f', negative=True)
|
| 243 |
+
M = Multinomial('M', n, [p1, p2, p3, p4])
|
| 244 |
+
C = Multinomial('C', 3, p1, p2, p3)
|
| 245 |
+
f = factorial
|
| 246 |
+
assert density(M)(x1, x2, x3, x4) == Piecewise((p1**x1*p2**x2*p3**x3*p4**x4*
|
| 247 |
+
f(n)/(f(x1)*f(x2)*f(x3)*f(x4)),
|
| 248 |
+
Eq(n, x1 + x2 + x3 + x4)), (0, True))
|
| 249 |
+
assert marginal_distribution(C, C[0])(x1).subs(x1, 1) ==\
|
| 250 |
+
3*p1*p2**2 +\
|
| 251 |
+
6*p1*p2*p3 +\
|
| 252 |
+
3*p1*p3**2
|
| 253 |
+
raises(ValueError, lambda: Multinomial('b1', 5, [p1, p2, p3, p1_f]))
|
| 254 |
+
raises(ValueError, lambda: Multinomial('b2', n_f, [p1, p2, p3, p4]))
|
| 255 |
+
raises(ValueError, lambda: Multinomial('b3', n, 0.5, 0.4, 0.3, 0.1))
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
def test_NegativeMultinomial():
|
| 259 |
+
k0, x1, x2, x3, x4 = symbols('k0, x1, x2, x3, x4', nonnegative=True, integer=True)
|
| 260 |
+
p1, p2, p3, p4 = symbols('p1, p2, p3, p4', positive=True)
|
| 261 |
+
p1_f = symbols('p1_f', negative=True)
|
| 262 |
+
N = NegativeMultinomial('N', 4, [p1, p2, p3, p4])
|
| 263 |
+
C = NegativeMultinomial('C', 4, 0.1, 0.2, 0.3)
|
| 264 |
+
g = gamma
|
| 265 |
+
f = factorial
|
| 266 |
+
assert simplify(density(N)(x1, x2, x3, x4) -
|
| 267 |
+
p1**x1*p2**x2*p3**x3*p4**x4*(-p1 - p2 - p3 - p4 + 1)**4*g(x1 + x2 +
|
| 268 |
+
x3 + x4 + 4)/(6*f(x1)*f(x2)*f(x3)*f(x4))) is S.Zero
|
| 269 |
+
assert comp(marginal_distribution(C, C[0])(1).evalf(), 0.33, .01)
|
| 270 |
+
raises(ValueError, lambda: NegativeMultinomial('b1', 5, [p1, p2, p3, p1_f]))
|
| 271 |
+
raises(ValueError, lambda: NegativeMultinomial('b2', k0, 0.5, 0.4, 0.3, 0.4))
|
| 272 |
+
assert N.pspace.distribution.set == ProductSet(Range(0, oo, 1),
|
| 273 |
+
Range(0, oo, 1), Range(0, oo, 1), Range(0, oo, 1))
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
@slow
|
| 277 |
+
def test_JointPSpace_marginal_distribution():
|
| 278 |
+
T = MultivariateT('T', [0, 0], [[1, 0], [0, 1]], 2)
|
| 279 |
+
got = marginal_distribution(T, T[1])(x)
|
| 280 |
+
ans = sqrt(2)*(x**2/2 + 1)/(4*polar_lift(x**2/2 + 1)**(S(5)/2))
|
| 281 |
+
assert got == ans, got
|
| 282 |
+
assert integrate(marginal_distribution(T, 1)(x), (x, -oo, oo)) == 1
|
| 283 |
+
|
| 284 |
+
t = MultivariateT('T', [0, 0, 0], [[1, 0, 0], [0, 1, 0], [0, 0, 1]], 3)
|
| 285 |
+
assert comp(marginal_distribution(t, 0)(1).evalf(), 0.2, .01)
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
def test_JointRV():
|
| 289 |
+
x1, x2 = (Indexed('x', i) for i in (1, 2))
|
| 290 |
+
pdf = exp(-x1**2/2 + x1 - x2**2/2 - S.Half)/(2*pi)
|
| 291 |
+
X = JointRV('x', pdf)
|
| 292 |
+
assert density(X)(1, 2) == exp(-2)/(2*pi)
|
| 293 |
+
assert isinstance(X.pspace.distribution, JointDistributionHandmade)
|
| 294 |
+
assert marginal_distribution(X, 0)(2) == sqrt(2)*exp(Rational(-1, 2))/(2*sqrt(pi))
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
def test_expectation():
|
| 298 |
+
m = Normal('A', [x, y], [[1, 0], [0, 1]])
|
| 299 |
+
assert simplify(E(m[1])) == y
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
@XFAIL
|
| 303 |
+
def test_joint_vector_expectation():
|
| 304 |
+
m = Normal('A', [x, y], [[1, 0], [0, 1]])
|
| 305 |
+
assert E(m) == (x, y)
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
def test_sample_numpy():
|
| 309 |
+
distribs_numpy = [
|
| 310 |
+
MultivariateNormal("M", [3, 4], [[2, 1], [1, 2]]),
|
| 311 |
+
MultivariateBeta("B", [0.4, 5, 15, 50, 203]),
|
| 312 |
+
Multinomial("N", 50, [0.3, 0.2, 0.1, 0.25, 0.15])
|
| 313 |
+
]
|
| 314 |
+
size = 3
|
| 315 |
+
numpy = import_module('numpy')
|
| 316 |
+
if not numpy:
|
| 317 |
+
skip('Numpy is not installed. Abort tests for _sample_numpy.')
|
| 318 |
+
else:
|
| 319 |
+
for X in distribs_numpy:
|
| 320 |
+
samps = sample(X, size=size, library='numpy')
|
| 321 |
+
for sam in samps:
|
| 322 |
+
assert tuple(sam) in X.pspace.distribution.set
|
| 323 |
+
N_c = NegativeMultinomial('N', 3, 0.1, 0.1, 0.1)
|
| 324 |
+
raises(NotImplementedError, lambda: sample(N_c, library='numpy'))
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
def test_sample_scipy():
|
| 328 |
+
distribs_scipy = [
|
| 329 |
+
MultivariateNormal("M", [0, 0], [[0.1, 0.025], [0.025, 0.1]]),
|
| 330 |
+
MultivariateBeta("B", [0.4, 5, 15]),
|
| 331 |
+
Multinomial("N", 8, [0.3, 0.2, 0.1, 0.4])
|
| 332 |
+
]
|
| 333 |
+
|
| 334 |
+
size = 3
|
| 335 |
+
scipy = import_module('scipy')
|
| 336 |
+
if not scipy:
|
| 337 |
+
skip('Scipy not installed. Abort tests for _sample_scipy.')
|
| 338 |
+
else:
|
| 339 |
+
for X in distribs_scipy:
|
| 340 |
+
samps = sample(X, size=size)
|
| 341 |
+
samps2 = sample(X, size=(2, 2))
|
| 342 |
+
for sam in samps:
|
| 343 |
+
assert tuple(sam) in X.pspace.distribution.set
|
| 344 |
+
for i in range(2):
|
| 345 |
+
for j in range(2):
|
| 346 |
+
assert tuple(samps2[i][j]) in X.pspace.distribution.set
|
| 347 |
+
N_c = NegativeMultinomial('N', 3, 0.1, 0.1, 0.1)
|
| 348 |
+
raises(NotImplementedError, lambda: sample(N_c))
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def test_sample_pymc():
|
| 352 |
+
distribs_pymc = [
|
| 353 |
+
MultivariateNormal("M", [5, 2], [[1, 0], [0, 1]]),
|
| 354 |
+
MultivariateBeta("B", [0.4, 5, 15]),
|
| 355 |
+
Multinomial("N", 4, [0.3, 0.2, 0.1, 0.4])
|
| 356 |
+
]
|
| 357 |
+
size = 3
|
| 358 |
+
pymc = import_module('pymc')
|
| 359 |
+
if not pymc:
|
| 360 |
+
skip('PyMC is not installed. Abort tests for _sample_pymc.')
|
| 361 |
+
else:
|
| 362 |
+
for X in distribs_pymc:
|
| 363 |
+
samps = sample(X, size=size, library='pymc')
|
| 364 |
+
for sam in samps:
|
| 365 |
+
assert tuple(sam.flatten()) in X.pspace.distribution.set
|
| 366 |
+
N_c = NegativeMultinomial('N', 3, 0.1, 0.1, 0.1)
|
| 367 |
+
raises(NotImplementedError, lambda: sample(N_c, library='pymc'))
|
| 368 |
+
|
| 369 |
+
|
| 370 |
+
def test_sample_seed():
|
| 371 |
+
x1, x2 = (Indexed('x', i) for i in (1, 2))
|
| 372 |
+
pdf = exp(-x1**2/2 + x1 - x2**2/2 - S.Half)/(2*pi)
|
| 373 |
+
X = JointRV('x', pdf)
|
| 374 |
+
|
| 375 |
+
libraries = ['scipy', 'numpy', 'pymc']
|
| 376 |
+
for lib in libraries:
|
| 377 |
+
try:
|
| 378 |
+
imported_lib = import_module(lib)
|
| 379 |
+
if imported_lib:
|
| 380 |
+
s0, s1, s2 = [], [], []
|
| 381 |
+
s0 = sample(X, size=10, library=lib, seed=0)
|
| 382 |
+
s1 = sample(X, size=10, library=lib, seed=0)
|
| 383 |
+
s2 = sample(X, size=10, library=lib, seed=1)
|
| 384 |
+
assert all(s0 == s1)
|
| 385 |
+
assert all(s1 != s2)
|
| 386 |
+
except NotImplementedError:
|
| 387 |
+
continue
|
| 388 |
+
|
| 389 |
+
#
|
| 390 |
+
# XXX: This fails for pymc. Previously the test appeared to pass but that is
|
| 391 |
+
# just because the library argument was not passed so the test always used
|
| 392 |
+
# scipy.
|
| 393 |
+
#
|
| 394 |
+
def test_issue_21057():
|
| 395 |
+
m = Normal("x", [0, 0], [[0, 0], [0, 0]])
|
| 396 |
+
n = MultivariateNormal("x", [0, 0], [[0, 0], [0, 0]])
|
| 397 |
+
p = Normal("x", [0, 0], [[0, 0], [0, 1]])
|
| 398 |
+
assert m == n
|
| 399 |
+
libraries = ('scipy', 'numpy') # , 'pymc') # <-- pymc fails
|
| 400 |
+
for library in libraries:
|
| 401 |
+
try:
|
| 402 |
+
imported_lib = import_module(library)
|
| 403 |
+
if imported_lib:
|
| 404 |
+
s1 = sample(m, size=8, library=library)
|
| 405 |
+
s2 = sample(n, size=8, library=library)
|
| 406 |
+
s3 = sample(p, size=8, library=library)
|
| 407 |
+
assert tuple(s1.flatten()) == tuple(s2.flatten())
|
| 408 |
+
for s in s3:
|
| 409 |
+
assert tuple(s.flatten()) in p.pspace.distribution.set
|
| 410 |
+
except NotImplementedError:
|
| 411 |
+
continue
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
#
|
| 415 |
+
# When this passes the pymc part can be uncommented in test_issue_21057 above
|
| 416 |
+
# and this can be deleted.
|
| 417 |
+
#
|
| 418 |
+
@XFAIL
|
| 419 |
+
def test_issue_21057_pymc():
|
| 420 |
+
m = Normal("x", [0, 0], [[0, 0], [0, 0]])
|
| 421 |
+
n = MultivariateNormal("x", [0, 0], [[0, 0], [0, 0]])
|
| 422 |
+
p = Normal("x", [0, 0], [[0, 0], [0, 1]])
|
| 423 |
+
assert m == n
|
| 424 |
+
libraries = ('pymc',)
|
| 425 |
+
for library in libraries:
|
| 426 |
+
try:
|
| 427 |
+
imported_lib = import_module(library)
|
| 428 |
+
if imported_lib:
|
| 429 |
+
s1 = sample(m, size=8, library=library)
|
| 430 |
+
s2 = sample(n, size=8, library=library)
|
| 431 |
+
s3 = sample(p, size=8, library=library)
|
| 432 |
+
assert tuple(s1.flatten()) == tuple(s2.flatten())
|
| 433 |
+
for s in s3:
|
| 434 |
+
assert tuple(s.flatten()) in p.pspace.distribution.set
|
| 435 |
+
except NotImplementedError:
|
| 436 |
+
continue
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_matrix_distributions.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.products import Product
|
| 2 |
+
from sympy.core.numbers import pi
|
| 3 |
+
from sympy.core.singleton import S
|
| 4 |
+
from sympy.core.symbol import (Dummy, symbols)
|
| 5 |
+
from sympy.functions.elementary.exponential import exp
|
| 6 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 7 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 8 |
+
from sympy.matrices import Determinant, Matrix, Trace, MatrixSymbol, MatrixSet
|
| 9 |
+
from sympy.stats import density, sample
|
| 10 |
+
from sympy.stats.matrix_distributions import (MatrixGammaDistribution,
|
| 11 |
+
MatrixGamma, MatrixPSpace, Wishart, MatrixNormal, MatrixStudentT)
|
| 12 |
+
from sympy.testing.pytest import raises, skip
|
| 13 |
+
from sympy.external import import_module
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_MatrixPSpace():
|
| 17 |
+
M = MatrixGammaDistribution(1, 2, [[2, 1], [1, 2]])
|
| 18 |
+
MP = MatrixPSpace('M', M, 2, 2)
|
| 19 |
+
assert MP.distribution == M
|
| 20 |
+
raises(ValueError, lambda: MatrixPSpace('M', M, 1.2, 2))
|
| 21 |
+
|
| 22 |
+
def test_MatrixGamma():
|
| 23 |
+
M = MatrixGamma('M', 1, 2, [[1, 0], [0, 1]])
|
| 24 |
+
assert M.pspace.distribution.set == MatrixSet(2, 2, S.Reals)
|
| 25 |
+
assert isinstance(density(M), MatrixGammaDistribution)
|
| 26 |
+
X = MatrixSymbol('X', 2, 2)
|
| 27 |
+
num = exp(Trace(Matrix([[-S(1)/2, 0], [0, -S(1)/2]])*X))
|
| 28 |
+
assert density(M)(X).doit() == num/(4*pi*sqrt(Determinant(X)))
|
| 29 |
+
assert density(M)([[2, 1], [1, 2]]).doit() == sqrt(3)*exp(-2)/(12*pi)
|
| 30 |
+
X = MatrixSymbol('X', 1, 2)
|
| 31 |
+
Y = MatrixSymbol('Y', 1, 2)
|
| 32 |
+
assert density(M)([X, Y]).doit() == exp(-X[0, 0]/2 - Y[0, 1]/2)/(4*pi*sqrt(
|
| 33 |
+
X[0, 0]*Y[0, 1] - X[0, 1]*Y[0, 0]))
|
| 34 |
+
# symbolic
|
| 35 |
+
a, b = symbols('a b', positive=True)
|
| 36 |
+
d = symbols('d', positive=True, integer=True)
|
| 37 |
+
Y = MatrixSymbol('Y', d, d)
|
| 38 |
+
Z = MatrixSymbol('Z', 2, 2)
|
| 39 |
+
SM = MatrixSymbol('SM', d, d)
|
| 40 |
+
M2 = MatrixGamma('M2', a, b, SM)
|
| 41 |
+
M3 = MatrixGamma('M3', 2, 3, [[2, 1], [1, 2]])
|
| 42 |
+
k = Dummy('k')
|
| 43 |
+
exprd = pi**(-d*(d - 1)/4)*b**(-a*d)*exp(Trace((-1/b)*SM**(-1)*Y)
|
| 44 |
+
)*Determinant(SM)**(-a)*Determinant(Y)**(a - d/2 - S(1)/2)/Product(
|
| 45 |
+
gamma(-k/2 + a + S(1)/2), (k, 1, d))
|
| 46 |
+
assert density(M2)(Y).dummy_eq(exprd)
|
| 47 |
+
raises(NotImplementedError, lambda: density(M3 + M)(Z))
|
| 48 |
+
raises(ValueError, lambda: density(M)(1))
|
| 49 |
+
raises(ValueError, lambda: MatrixGamma('M', -1, 2, [[1, 0], [0, 1]]))
|
| 50 |
+
raises(ValueError, lambda: MatrixGamma('M', -1, -2, [[1, 0], [0, 1]]))
|
| 51 |
+
raises(ValueError, lambda: MatrixGamma('M', -1, 2, [[1, 0], [2, 1]]))
|
| 52 |
+
raises(ValueError, lambda: MatrixGamma('M', -1, 2, [[1, 0], [0]]))
|
| 53 |
+
|
| 54 |
+
def test_Wishart():
|
| 55 |
+
W = Wishart('W', 5, [[1, 0], [0, 1]])
|
| 56 |
+
assert W.pspace.distribution.set == MatrixSet(2, 2, S.Reals)
|
| 57 |
+
X = MatrixSymbol('X', 2, 2)
|
| 58 |
+
term1 = exp(Trace(Matrix([[-S(1)/2, 0], [0, -S(1)/2]])*X))
|
| 59 |
+
assert density(W)(X).doit() == term1 * Determinant(X)/(24*pi)
|
| 60 |
+
assert density(W)([[2, 1], [1, 2]]).doit() == exp(-2)/(8*pi)
|
| 61 |
+
n = symbols('n', positive=True)
|
| 62 |
+
d = symbols('d', positive=True, integer=True)
|
| 63 |
+
Y = MatrixSymbol('Y', d, d)
|
| 64 |
+
SM = MatrixSymbol('SM', d, d)
|
| 65 |
+
W = Wishart('W', n, SM)
|
| 66 |
+
k = Dummy('k')
|
| 67 |
+
exprd = 2**(-d*n/2)*pi**(-d*(d - 1)/4)*exp(Trace(-(S(1)/2)*SM**(-1)*Y)
|
| 68 |
+
)*Determinant(SM)**(-n/2)*Determinant(Y)**(
|
| 69 |
+
-d/2 + n/2 - S(1)/2)/Product(gamma(-k/2 + n/2 + S(1)/2), (k, 1, d))
|
| 70 |
+
assert density(W)(Y).dummy_eq(exprd)
|
| 71 |
+
raises(ValueError, lambda: density(W)(1))
|
| 72 |
+
raises(ValueError, lambda: Wishart('W', -1, [[1, 0], [0, 1]]))
|
| 73 |
+
raises(ValueError, lambda: Wishart('W', -1, [[1, 0], [2, 1]]))
|
| 74 |
+
raises(ValueError, lambda: Wishart('W', 2, [[1, 0], [0]]))
|
| 75 |
+
|
| 76 |
+
def test_MatrixNormal():
|
| 77 |
+
M = MatrixNormal('M', [[5, 6]], [4], [[2, 1], [1, 2]])
|
| 78 |
+
assert M.pspace.distribution.set == MatrixSet(1, 2, S.Reals)
|
| 79 |
+
X = MatrixSymbol('X', 1, 2)
|
| 80 |
+
term1 = exp(-Trace(Matrix([[ S(2)/3, -S(1)/3], [-S(1)/3, S(2)/3]])*(
|
| 81 |
+
Matrix([[-5], [-6]]) + X.T)*Matrix([[S(1)/4]])*(Matrix([[-5, -6]]) + X))/2)
|
| 82 |
+
assert density(M)(X).doit() == (sqrt(3)) * term1/(24*pi)
|
| 83 |
+
assert density(M)([[7, 8]]).doit() == sqrt(3)*exp(-S(1)/3)/(24*pi)
|
| 84 |
+
d, n = symbols('d n', positive=True, integer=True)
|
| 85 |
+
SM2 = MatrixSymbol('SM2', d, d)
|
| 86 |
+
SM1 = MatrixSymbol('SM1', n, n)
|
| 87 |
+
LM = MatrixSymbol('LM', n, d)
|
| 88 |
+
Y = MatrixSymbol('Y', n, d)
|
| 89 |
+
M = MatrixNormal('M', LM, SM1, SM2)
|
| 90 |
+
exprd = (2*pi)**(-d*n/2)*exp(-Trace(SM2**(-1)*(-LM.T + Y.T)*SM1**(-1)*(-LM + Y)
|
| 91 |
+
)/2)*Determinant(SM1)**(-d/2)*Determinant(SM2)**(-n/2)
|
| 92 |
+
assert density(M)(Y).doit() == exprd
|
| 93 |
+
raises(ValueError, lambda: density(M)(1))
|
| 94 |
+
raises(ValueError, lambda: MatrixNormal('M', [1, 2], [[1, 0], [0, 1]], [[1, 0], [2, 1]]))
|
| 95 |
+
raises(ValueError, lambda: MatrixNormal('M', [1, 2], [[1, 0], [2, 1]], [[1, 0], [0, 1]]))
|
| 96 |
+
raises(ValueError, lambda: MatrixNormal('M', [1, 2], [[1, 0], [0, 1]], [[1, 0], [0, 1]]))
|
| 97 |
+
raises(ValueError, lambda: MatrixNormal('M', [1, 2], [[1, 0], [2]], [[1, 0], [0, 1]]))
|
| 98 |
+
raises(ValueError, lambda: MatrixNormal('M', [1, 2], [[1, 0], [2, 1]], [[1, 0], [0]]))
|
| 99 |
+
raises(ValueError, lambda: MatrixNormal('M', [[1, 2]], [[1, 0], [0, 1]], [[1, 0]]))
|
| 100 |
+
raises(ValueError, lambda: MatrixNormal('M', [[1, 2]], [1], [[1, 0]]))
|
| 101 |
+
|
| 102 |
+
def test_MatrixStudentT():
|
| 103 |
+
M = MatrixStudentT('M', 2, [[5, 6]], [[2, 1], [1, 2]], [4])
|
| 104 |
+
assert M.pspace.distribution.set == MatrixSet(1, 2, S.Reals)
|
| 105 |
+
X = MatrixSymbol('X', 1, 2)
|
| 106 |
+
D = pi ** (-1.0) * Determinant(Matrix([[4]])) ** (-1.0) * Determinant(Matrix([[2, 1], [1, 2]])) \
|
| 107 |
+
** (-0.5) / Determinant(Matrix([[S(1) / 4]]) * (Matrix([[-5, -6]]) + X)
|
| 108 |
+
* Matrix([[S(2) / 3, -S(1) / 3], [-S(1) / 3, S(2) / 3]]) * (
|
| 109 |
+
Matrix([[-5], [-6]]) + X.T) + Matrix([[1]])) ** 2
|
| 110 |
+
assert density(M)(X) == D
|
| 111 |
+
|
| 112 |
+
v = symbols('v', positive=True)
|
| 113 |
+
n, p = 1, 2
|
| 114 |
+
Omega = MatrixSymbol('Omega', p, p)
|
| 115 |
+
Sigma = MatrixSymbol('Sigma', n, n)
|
| 116 |
+
Location = MatrixSymbol('Location', n, p)
|
| 117 |
+
Y = MatrixSymbol('Y', n, p)
|
| 118 |
+
M = MatrixStudentT('M', v, Location, Omega, Sigma)
|
| 119 |
+
|
| 120 |
+
exprd = gamma(v/2 + 1)*Determinant(Matrix([[1]]) + Sigma**(-1)*(-Location + Y)*Omega**(-1)*(-Location.T + Y.T))**(-v/2 - 1) / \
|
| 121 |
+
(pi*gamma(v/2)*sqrt(Determinant(Omega))*Determinant(Sigma))
|
| 122 |
+
|
| 123 |
+
assert density(M)(Y) == exprd
|
| 124 |
+
raises(ValueError, lambda: density(M)(1))
|
| 125 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [1, 2], [[1, 0], [0, 1]], [[1, 0], [2, 1]]))
|
| 126 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [1, 2], [[1, 0], [2, 1]], [[1, 0], [0, 1]]))
|
| 127 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [1, 2], [[1, 0], [0, 1]], [[1, 0], [0, 1]]))
|
| 128 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [1, 2], [[1, 0], [2]], [[1, 0], [0, 1]]))
|
| 129 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [1, 2], [[1, 0], [2, 1]], [[1], [2]]))
|
| 130 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [[1, 2]], [[1, 0], [0, 1]], [[1, 0]]))
|
| 131 |
+
raises(ValueError, lambda: MatrixStudentT('M', 1, [[1, 2]], [1], [[1, 0]]))
|
| 132 |
+
raises(ValueError, lambda: MatrixStudentT('M', -1, [1, 2], [[1, 0], [0, 1]], [4]))
|
| 133 |
+
|
| 134 |
+
def test_sample_scipy():
|
| 135 |
+
distribs_scipy = [
|
| 136 |
+
MatrixNormal('M', [[5, 6]], [4], [[2, 1], [1, 2]]),
|
| 137 |
+
Wishart('W', 5, [[1, 0], [0, 1]])
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
+
size = 5
|
| 141 |
+
scipy = import_module('scipy')
|
| 142 |
+
if not scipy:
|
| 143 |
+
skip('Scipy not installed. Abort tests for _sample_scipy.')
|
| 144 |
+
else:
|
| 145 |
+
for X in distribs_scipy:
|
| 146 |
+
samps = sample(X, size=size)
|
| 147 |
+
for sam in samps:
|
| 148 |
+
assert Matrix(sam) in X.pspace.distribution.set
|
| 149 |
+
M = MatrixGamma('M', 1, 2, [[1, 0], [0, 1]])
|
| 150 |
+
raises(NotImplementedError, lambda: sample(M, size=3))
|
| 151 |
+
|
| 152 |
+
def test_sample_pymc():
|
| 153 |
+
distribs_pymc = [
|
| 154 |
+
MatrixNormal('M', [[5, 6], [3, 4]], [[1, 0], [0, 1]], [[2, 1], [1, 2]]),
|
| 155 |
+
Wishart('W', 7, [[2, 1], [1, 2]])
|
| 156 |
+
]
|
| 157 |
+
size = 3
|
| 158 |
+
pymc = import_module('pymc')
|
| 159 |
+
if not pymc:
|
| 160 |
+
skip('PyMC is not installed. Abort tests for _sample_pymc.')
|
| 161 |
+
else:
|
| 162 |
+
for X in distribs_pymc:
|
| 163 |
+
samps = sample(X, size=size, library='pymc')
|
| 164 |
+
for sam in samps:
|
| 165 |
+
assert Matrix(sam) in X.pspace.distribution.set
|
| 166 |
+
M = MatrixGamma('M', 1, 2, [[1, 0], [0, 1]])
|
| 167 |
+
raises(NotImplementedError, lambda: sample(M, size=3))
|
| 168 |
+
|
| 169 |
+
def test_sample_seed():
|
| 170 |
+
X = MatrixNormal('M', [[5, 6], [3, 4]], [[1, 0], [0, 1]], [[2, 1], [1, 2]])
|
| 171 |
+
|
| 172 |
+
libraries = ['scipy', 'numpy', 'pymc']
|
| 173 |
+
for lib in libraries:
|
| 174 |
+
try:
|
| 175 |
+
imported_lib = import_module(lib)
|
| 176 |
+
if imported_lib:
|
| 177 |
+
s0, s1, s2 = [], [], []
|
| 178 |
+
s0 = sample(X, size=10, library=lib, seed=0)
|
| 179 |
+
s1 = sample(X, size=10, library=lib, seed=0)
|
| 180 |
+
s2 = sample(X, size=10, library=lib, seed=1)
|
| 181 |
+
for i in range(10):
|
| 182 |
+
assert (s0[i] == s1[i]).all()
|
| 183 |
+
assert (s1[i] != s2[i]).all()
|
| 184 |
+
|
| 185 |
+
except NotImplementedError:
|
| 186 |
+
continue
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_mix.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.add import Add
|
| 3 |
+
from sympy.core.mul import Mul
|
| 4 |
+
from sympy.core.numbers import (Integer, oo, pi)
|
| 5 |
+
from sympy.core.power import Pow
|
| 6 |
+
from sympy.core.relational import (Eq, Ne)
|
| 7 |
+
from sympy.core.symbol import (Dummy, Symbol, symbols)
|
| 8 |
+
from sympy.functions.combinatorial.factorials import factorial
|
| 9 |
+
from sympy.functions.elementary.exponential import exp
|
| 10 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 11 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 12 |
+
from sympy.functions.special.delta_functions import DiracDelta
|
| 13 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 14 |
+
from sympy.integrals.integrals import Integral
|
| 15 |
+
from sympy.simplify.simplify import simplify
|
| 16 |
+
from sympy.tensor.indexed import (Indexed, IndexedBase)
|
| 17 |
+
from sympy.functions.elementary.piecewise import ExprCondPair
|
| 18 |
+
from sympy.stats import (Poisson, Beta, Exponential, P,
|
| 19 |
+
Multinomial, MultivariateBeta)
|
| 20 |
+
from sympy.stats.crv_types import Normal
|
| 21 |
+
from sympy.stats.drv_types import PoissonDistribution
|
| 22 |
+
from sympy.stats.compound_rv import CompoundPSpace, CompoundDistribution
|
| 23 |
+
from sympy.stats.joint_rv import MarginalDistribution
|
| 24 |
+
from sympy.stats.rv import pspace, density
|
| 25 |
+
from sympy.testing.pytest import ignore_warnings
|
| 26 |
+
|
| 27 |
+
def test_density():
|
| 28 |
+
x = Symbol('x')
|
| 29 |
+
l = Symbol('l', positive=True)
|
| 30 |
+
rate = Beta(l, 2, 3)
|
| 31 |
+
X = Poisson(x, rate)
|
| 32 |
+
assert isinstance(pspace(X), CompoundPSpace)
|
| 33 |
+
assert density(X, Eq(rate, rate.symbol)) == PoissonDistribution(l)
|
| 34 |
+
N1 = Normal('N1', 0, 1)
|
| 35 |
+
N2 = Normal('N2', N1, 2)
|
| 36 |
+
assert density(N2)(0).doit() == sqrt(10)/(10*sqrt(pi))
|
| 37 |
+
assert simplify(density(N2, Eq(N1, 1))(x)) == \
|
| 38 |
+
sqrt(2)*exp(-(x - 1)**2/8)/(4*sqrt(pi))
|
| 39 |
+
assert simplify(density(N2)(x)) == sqrt(10)*exp(-x**2/10)/(10*sqrt(pi))
|
| 40 |
+
|
| 41 |
+
def test_MarginalDistribution():
|
| 42 |
+
a1, p1, p2 = symbols('a1 p1 p2', positive=True)
|
| 43 |
+
C = Multinomial('C', 2, p1, p2)
|
| 44 |
+
B = MultivariateBeta('B', a1, C[0])
|
| 45 |
+
MGR = MarginalDistribution(B, (C[0],))
|
| 46 |
+
mgrc = Mul(Symbol('B'), Piecewise(ExprCondPair(Mul(Integer(2),
|
| 47 |
+
Pow(Symbol('p1', positive=True), Indexed(IndexedBase(Symbol('C')),
|
| 48 |
+
Integer(0))), Pow(Symbol('p2', positive=True),
|
| 49 |
+
Indexed(IndexedBase(Symbol('C')), Integer(1))),
|
| 50 |
+
Pow(factorial(Indexed(IndexedBase(Symbol('C')), Integer(0))), Integer(-1)),
|
| 51 |
+
Pow(factorial(Indexed(IndexedBase(Symbol('C')), Integer(1))), Integer(-1))),
|
| 52 |
+
Eq(Add(Indexed(IndexedBase(Symbol('C')), Integer(0)),
|
| 53 |
+
Indexed(IndexedBase(Symbol('C')), Integer(1))), Integer(2))),
|
| 54 |
+
ExprCondPair(Integer(0), True)), Pow(gamma(Symbol('a1', positive=True)),
|
| 55 |
+
Integer(-1)), gamma(Add(Symbol('a1', positive=True),
|
| 56 |
+
Indexed(IndexedBase(Symbol('C')), Integer(0)))),
|
| 57 |
+
Pow(gamma(Indexed(IndexedBase(Symbol('C')), Integer(0))), Integer(-1)),
|
| 58 |
+
Pow(Indexed(IndexedBase(Symbol('B')), Integer(0)),
|
| 59 |
+
Add(Symbol('a1', positive=True), Integer(-1))),
|
| 60 |
+
Pow(Indexed(IndexedBase(Symbol('B')), Integer(1)),
|
| 61 |
+
Add(Indexed(IndexedBase(Symbol('C')), Integer(0)), Integer(-1))))
|
| 62 |
+
assert MGR(C) == mgrc
|
| 63 |
+
|
| 64 |
+
def test_compound_distribution():
|
| 65 |
+
Y = Poisson('Y', 1)
|
| 66 |
+
Z = Poisson('Z', Y)
|
| 67 |
+
assert isinstance(pspace(Z), CompoundPSpace)
|
| 68 |
+
assert isinstance(pspace(Z).distribution, CompoundDistribution)
|
| 69 |
+
assert Z.pspace.distribution.pdf(1).doit() == exp(-2)*exp(exp(-1))
|
| 70 |
+
|
| 71 |
+
def test_mix_expression():
|
| 72 |
+
Y, E = Poisson('Y', 1), Exponential('E', 1)
|
| 73 |
+
k = Dummy('k')
|
| 74 |
+
expr1 = Integral(Sum(exp(-1)*Integral(exp(-k)*DiracDelta(k - 2), (k, 0, oo)
|
| 75 |
+
)/factorial(k), (k, 0, oo)), (k, -oo, 0))
|
| 76 |
+
expr2 = Integral(Sum(exp(-1)*Integral(exp(-k)*DiracDelta(k - 2), (k, 0, oo)
|
| 77 |
+
)/factorial(k), (k, 0, oo)), (k, 0, oo))
|
| 78 |
+
assert P(Eq(Y + E, 1)) == 0
|
| 79 |
+
assert P(Ne(Y + E, 2)) == 1
|
| 80 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 81 |
+
assert P(E + Y < 2, evaluate=False).rewrite(Integral).dummy_eq(expr1)
|
| 82 |
+
assert P(E + Y > 2, evaluate=False).rewrite(Integral).dummy_eq(expr2)
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_random_matrix.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.products import Product
|
| 2 |
+
from sympy.core.function import Lambda
|
| 3 |
+
from sympy.core.numbers import (I, Rational, pi)
|
| 4 |
+
from sympy.core.singleton import S
|
| 5 |
+
from sympy.core.symbol import Dummy
|
| 6 |
+
from sympy.functions.elementary.complexes import Abs
|
| 7 |
+
from sympy.functions.elementary.exponential import exp
|
| 8 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 9 |
+
from sympy.integrals.integrals import Integral
|
| 10 |
+
from sympy.matrices.dense import Matrix
|
| 11 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 12 |
+
from sympy.matrices.expressions.trace import Trace
|
| 13 |
+
from sympy.tensor.indexed import IndexedBase
|
| 14 |
+
from sympy.stats import (GaussianUnitaryEnsemble as GUE, density,
|
| 15 |
+
GaussianOrthogonalEnsemble as GOE,
|
| 16 |
+
GaussianSymplecticEnsemble as GSE,
|
| 17 |
+
joint_eigen_distribution,
|
| 18 |
+
CircularUnitaryEnsemble as CUE,
|
| 19 |
+
CircularOrthogonalEnsemble as COE,
|
| 20 |
+
CircularSymplecticEnsemble as CSE,
|
| 21 |
+
JointEigenDistribution,
|
| 22 |
+
level_spacing_distribution,
|
| 23 |
+
Normal, Beta)
|
| 24 |
+
from sympy.stats.joint_rv_types import JointDistributionHandmade
|
| 25 |
+
from sympy.stats.rv import RandomMatrixSymbol
|
| 26 |
+
from sympy.stats.random_matrix_models import GaussianEnsemble, RandomMatrixPSpace
|
| 27 |
+
from sympy.testing.pytest import raises
|
| 28 |
+
|
| 29 |
+
def test_GaussianEnsemble():
|
| 30 |
+
G = GaussianEnsemble('G', 3)
|
| 31 |
+
assert density(G) == G.pspace.model
|
| 32 |
+
raises(ValueError, lambda: GaussianEnsemble('G', 3.5))
|
| 33 |
+
|
| 34 |
+
def test_GaussianUnitaryEnsemble():
|
| 35 |
+
H = RandomMatrixSymbol('H', 3, 3)
|
| 36 |
+
G = GUE('U', 3)
|
| 37 |
+
assert density(G)(H) == sqrt(2)*exp(-3*Trace(H**2)/2)/(4*pi**Rational(9, 2))
|
| 38 |
+
i, j = (Dummy('i', integer=True, positive=True),
|
| 39 |
+
Dummy('j', integer=True, positive=True))
|
| 40 |
+
l = IndexedBase('l')
|
| 41 |
+
assert joint_eigen_distribution(G).dummy_eq(
|
| 42 |
+
Lambda((l[1], l[2], l[3]),
|
| 43 |
+
27*sqrt(6)*exp(-3*(l[1]**2)/2 - 3*(l[2]**2)/2 - 3*(l[3]**2)/2)*
|
| 44 |
+
Product(Abs(l[i] - l[j])**2, (j, i + 1, 3), (i, 1, 2))/(16*pi**Rational(3, 2))))
|
| 45 |
+
s = Dummy('s')
|
| 46 |
+
assert level_spacing_distribution(G).dummy_eq(Lambda(s, 32*s**2*exp(-4*s**2/pi)/pi**2))
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def test_GaussianOrthogonalEnsemble():
|
| 50 |
+
H = RandomMatrixSymbol('H', 3, 3)
|
| 51 |
+
_H = MatrixSymbol('_H', 3, 3)
|
| 52 |
+
G = GOE('O', 3)
|
| 53 |
+
assert density(G)(H) == exp(-3*Trace(H**2)/4)/Integral(exp(-3*Trace(_H**2)/4), _H)
|
| 54 |
+
i, j = (Dummy('i', integer=True, positive=True),
|
| 55 |
+
Dummy('j', integer=True, positive=True))
|
| 56 |
+
l = IndexedBase('l')
|
| 57 |
+
assert joint_eigen_distribution(G).dummy_eq(
|
| 58 |
+
Lambda((l[1], l[2], l[3]),
|
| 59 |
+
9*sqrt(2)*exp(-3*l[1]**2/2 - 3*l[2]**2/2 - 3*l[3]**2/2)*
|
| 60 |
+
Product(Abs(l[i] - l[j]), (j, i + 1, 3), (i, 1, 2))/(32*pi)))
|
| 61 |
+
s = Dummy('s')
|
| 62 |
+
assert level_spacing_distribution(G).dummy_eq(Lambda(s, s*pi*exp(-s**2*pi/4)/2))
|
| 63 |
+
|
| 64 |
+
def test_GaussianSymplecticEnsemble():
|
| 65 |
+
H = RandomMatrixSymbol('H', 3, 3)
|
| 66 |
+
_H = MatrixSymbol('_H', 3, 3)
|
| 67 |
+
G = GSE('O', 3)
|
| 68 |
+
assert density(G)(H) == exp(-3*Trace(H**2))/Integral(exp(-3*Trace(_H**2)), _H)
|
| 69 |
+
i, j = (Dummy('i', integer=True, positive=True),
|
| 70 |
+
Dummy('j', integer=True, positive=True))
|
| 71 |
+
l = IndexedBase('l')
|
| 72 |
+
assert joint_eigen_distribution(G).dummy_eq(
|
| 73 |
+
Lambda((l[1], l[2], l[3]),
|
| 74 |
+
162*sqrt(3)*exp(-3*l[1]**2/2 - 3*l[2]**2/2 - 3*l[3]**2/2)*
|
| 75 |
+
Product(Abs(l[i] - l[j])**4, (j, i + 1, 3), (i, 1, 2))/(5*pi**Rational(3, 2))))
|
| 76 |
+
s = Dummy('s')
|
| 77 |
+
assert level_spacing_distribution(G).dummy_eq(Lambda(s, S(262144)*s**4*exp(-64*s**2/(9*pi))/(729*pi**3)))
|
| 78 |
+
|
| 79 |
+
def test_CircularUnitaryEnsemble():
|
| 80 |
+
CU = CUE('U', 3)
|
| 81 |
+
j, k = (Dummy('j', integer=True, positive=True),
|
| 82 |
+
Dummy('k', integer=True, positive=True))
|
| 83 |
+
t = IndexedBase('t')
|
| 84 |
+
assert joint_eigen_distribution(CU).dummy_eq(
|
| 85 |
+
Lambda((t[1], t[2], t[3]),
|
| 86 |
+
Product(Abs(exp(I*t[j]) - exp(I*t[k]))**2,
|
| 87 |
+
(j, k + 1, 3), (k, 1, 2))/(48*pi**3))
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
def test_CircularOrthogonalEnsemble():
|
| 91 |
+
CO = COE('U', 3)
|
| 92 |
+
j, k = (Dummy('j', integer=True, positive=True),
|
| 93 |
+
Dummy('k', integer=True, positive=True))
|
| 94 |
+
t = IndexedBase('t')
|
| 95 |
+
assert joint_eigen_distribution(CO).dummy_eq(
|
| 96 |
+
Lambda((t[1], t[2], t[3]),
|
| 97 |
+
Product(Abs(exp(I*t[j]) - exp(I*t[k])),
|
| 98 |
+
(j, k + 1, 3), (k, 1, 2))/(48*pi**2))
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
def test_CircularSymplecticEnsemble():
|
| 102 |
+
CS = CSE('U', 3)
|
| 103 |
+
j, k = (Dummy('j', integer=True, positive=True),
|
| 104 |
+
Dummy('k', integer=True, positive=True))
|
| 105 |
+
t = IndexedBase('t')
|
| 106 |
+
assert joint_eigen_distribution(CS).dummy_eq(
|
| 107 |
+
Lambda((t[1], t[2], t[3]),
|
| 108 |
+
Product(Abs(exp(I*t[j]) - exp(I*t[k]))**4,
|
| 109 |
+
(j, k + 1, 3), (k, 1, 2))/(720*pi**3))
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
def test_JointEigenDistribution():
|
| 113 |
+
A = Matrix([[Normal('A00', 0, 1), Normal('A01', 1, 1)],
|
| 114 |
+
[Beta('A10', 1, 1), Beta('A11', 1, 1)]])
|
| 115 |
+
assert JointEigenDistribution(A) == \
|
| 116 |
+
JointDistributionHandmade(-sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + A[1, 1]**2)/2 +
|
| 117 |
+
A[0, 0]/2 + A[1, 1]/2, sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + A[1, 1]**2)/2 + A[0, 0]/2 + A[1, 1]/2)
|
| 118 |
+
raises(ValueError, lambda: JointEigenDistribution(Matrix([[1, 0], [2, 1]])))
|
| 119 |
+
|
| 120 |
+
def test_issue_19841():
|
| 121 |
+
G1 = GUE('U', 2)
|
| 122 |
+
G2 = G1.xreplace({2: 2})
|
| 123 |
+
assert G1.args == G2.args
|
| 124 |
+
|
| 125 |
+
X = MatrixSymbol('X', 2, 2)
|
| 126 |
+
G = GSE('U', 2)
|
| 127 |
+
h_pspace = RandomMatrixPSpace('P', model=density(G))
|
| 128 |
+
H = RandomMatrixSymbol('H', 2, 2, pspace=h_pspace)
|
| 129 |
+
H2 = RandomMatrixSymbol('H', 2, 2, pspace=None)
|
| 130 |
+
assert H.doit() == H
|
| 131 |
+
|
| 132 |
+
assert (2*H).xreplace({H: X}) == 2*X
|
| 133 |
+
assert (2*H).xreplace({H2: X}) == 2*H
|
| 134 |
+
assert (2*H2).xreplace({H: X}) == 2*H2
|
| 135 |
+
assert (2*H2).xreplace({H2: X}) == 2*X
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_rv.py
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.basic import Basic
|
| 3 |
+
from sympy.core.containers import Tuple
|
| 4 |
+
from sympy.core.function import Lambda
|
| 5 |
+
from sympy.core.numbers import (Rational, nan, oo, pi)
|
| 6 |
+
from sympy.core.relational import Eq
|
| 7 |
+
from sympy.core.singleton import S
|
| 8 |
+
from sympy.core.symbol import (Symbol, symbols)
|
| 9 |
+
from sympy.functions.combinatorial.factorials import (FallingFactorial, binomial)
|
| 10 |
+
from sympy.functions.elementary.exponential import (exp, log)
|
| 11 |
+
from sympy.functions.elementary.trigonometric import (cos, sin)
|
| 12 |
+
from sympy.functions.special.delta_functions import DiracDelta
|
| 13 |
+
from sympy.integrals.integrals import integrate
|
| 14 |
+
from sympy.logic.boolalg import (And, Or)
|
| 15 |
+
from sympy.matrices.dense import Matrix
|
| 16 |
+
from sympy.sets.sets import Interval
|
| 17 |
+
from sympy.tensor.indexed import Indexed
|
| 18 |
+
from sympy.stats import (Die, Normal, Exponential, FiniteRV, P, E, H, variance,
|
| 19 |
+
density, given, independent, dependent, where, pspace, GaussianUnitaryEnsemble,
|
| 20 |
+
random_symbols, sample, Geometric, factorial_moment, Binomial, Hypergeometric,
|
| 21 |
+
DiscreteUniform, Poisson, characteristic_function, moment_generating_function,
|
| 22 |
+
BernoulliProcess, Variance, Expectation, Probability, Covariance, covariance, cmoment,
|
| 23 |
+
moment, median)
|
| 24 |
+
from sympy.stats.rv import (IndependentProductPSpace, rs_swap, Density, NamedArgsMixin,
|
| 25 |
+
RandomSymbol, sample_iter, PSpace, is_random, RandomIndexedSymbol, RandomMatrixSymbol)
|
| 26 |
+
from sympy.testing.pytest import raises, skip, XFAIL, warns_deprecated_sympy
|
| 27 |
+
from sympy.external import import_module
|
| 28 |
+
from sympy.core.numbers import comp
|
| 29 |
+
from sympy.stats.frv_types import BernoulliDistribution
|
| 30 |
+
from sympy.core.symbol import Dummy
|
| 31 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 32 |
+
|
| 33 |
+
def test_where():
|
| 34 |
+
X, Y = Die('X'), Die('Y')
|
| 35 |
+
Z = Normal('Z', 0, 1)
|
| 36 |
+
|
| 37 |
+
assert where(Z**2 <= 1).set == Interval(-1, 1)
|
| 38 |
+
assert where(Z**2 <= 1).as_boolean() == Interval(-1, 1).as_relational(Z.symbol)
|
| 39 |
+
assert where(And(X > Y, Y > 4)).as_boolean() == And(
|
| 40 |
+
Eq(X.symbol, 6), Eq(Y.symbol, 5))
|
| 41 |
+
|
| 42 |
+
assert len(where(X < 3).set) == 2
|
| 43 |
+
assert 1 in where(X < 3).set
|
| 44 |
+
|
| 45 |
+
X, Y = Normal('X', 0, 1), Normal('Y', 0, 1)
|
| 46 |
+
assert where(And(X**2 <= 1, X >= 0)).set == Interval(0, 1)
|
| 47 |
+
XX = given(X, And(X**2 <= 1, X >= 0))
|
| 48 |
+
assert XX.pspace.domain.set == Interval(0, 1)
|
| 49 |
+
assert XX.pspace.domain.as_boolean() == \
|
| 50 |
+
And(0 <= X.symbol, X.symbol**2 <= 1, -oo < X.symbol, X.symbol < oo)
|
| 51 |
+
|
| 52 |
+
with raises(TypeError):
|
| 53 |
+
XX = given(X, X + 3)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def test_random_symbols():
|
| 57 |
+
X, Y = Normal('X', 0, 1), Normal('Y', 0, 1)
|
| 58 |
+
|
| 59 |
+
assert set(random_symbols(2*X + 1)) == {X}
|
| 60 |
+
assert set(random_symbols(2*X + Y)) == {X, Y}
|
| 61 |
+
assert set(random_symbols(2*X + Y.symbol)) == {X}
|
| 62 |
+
assert set(random_symbols(2)) == set()
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def test_characteristic_function():
|
| 66 |
+
# Imports I from sympy
|
| 67 |
+
from sympy.core.numbers import I
|
| 68 |
+
X = Normal('X',0,1)
|
| 69 |
+
Y = DiscreteUniform('Y', [1,2,7])
|
| 70 |
+
Z = Poisson('Z', 2)
|
| 71 |
+
t = symbols('_t')
|
| 72 |
+
P = Lambda(t, exp(-t**2/2))
|
| 73 |
+
Q = Lambda(t, exp(7*t*I)/3 + exp(2*t*I)/3 + exp(t*I)/3)
|
| 74 |
+
R = Lambda(t, exp(2 * exp(t*I) - 2))
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
assert characteristic_function(X).dummy_eq(P)
|
| 78 |
+
assert characteristic_function(Y).dummy_eq(Q)
|
| 79 |
+
assert characteristic_function(Z).dummy_eq(R)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def test_moment_generating_function():
|
| 83 |
+
|
| 84 |
+
X = Normal('X',0,1)
|
| 85 |
+
Y = DiscreteUniform('Y', [1,2,7])
|
| 86 |
+
Z = Poisson('Z', 2)
|
| 87 |
+
t = symbols('_t')
|
| 88 |
+
P = Lambda(t, exp(t**2/2))
|
| 89 |
+
Q = Lambda(t, (exp(7*t)/3 + exp(2*t)/3 + exp(t)/3))
|
| 90 |
+
R = Lambda(t, exp(2 * exp(t) - 2))
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
assert moment_generating_function(X).dummy_eq(P)
|
| 94 |
+
assert moment_generating_function(Y).dummy_eq(Q)
|
| 95 |
+
assert moment_generating_function(Z).dummy_eq(R)
|
| 96 |
+
|
| 97 |
+
def test_sample_iter():
|
| 98 |
+
|
| 99 |
+
X = Normal('X',0,1)
|
| 100 |
+
Y = DiscreteUniform('Y', [1, 2, 7])
|
| 101 |
+
Z = Poisson('Z', 2)
|
| 102 |
+
|
| 103 |
+
scipy = import_module('scipy')
|
| 104 |
+
if not scipy:
|
| 105 |
+
skip('Scipy is not installed. Abort tests')
|
| 106 |
+
expr = X**2 + 3
|
| 107 |
+
iterator = sample_iter(expr)
|
| 108 |
+
|
| 109 |
+
expr2 = Y**2 + 5*Y + 4
|
| 110 |
+
iterator2 = sample_iter(expr2)
|
| 111 |
+
|
| 112 |
+
expr3 = Z**3 + 4
|
| 113 |
+
iterator3 = sample_iter(expr3)
|
| 114 |
+
|
| 115 |
+
def is_iterator(obj):
|
| 116 |
+
if (
|
| 117 |
+
hasattr(obj, '__iter__') and
|
| 118 |
+
(hasattr(obj, 'next') or
|
| 119 |
+
hasattr(obj, '__next__')) and
|
| 120 |
+
callable(obj.__iter__) and
|
| 121 |
+
obj.__iter__() is obj
|
| 122 |
+
):
|
| 123 |
+
return True
|
| 124 |
+
else:
|
| 125 |
+
return False
|
| 126 |
+
assert is_iterator(iterator)
|
| 127 |
+
assert is_iterator(iterator2)
|
| 128 |
+
assert is_iterator(iterator3)
|
| 129 |
+
|
| 130 |
+
def test_pspace():
|
| 131 |
+
X, Y = Normal('X', 0, 1), Normal('Y', 0, 1)
|
| 132 |
+
x = Symbol('x')
|
| 133 |
+
|
| 134 |
+
raises(ValueError, lambda: pspace(5 + 3))
|
| 135 |
+
raises(ValueError, lambda: pspace(x < 1))
|
| 136 |
+
assert pspace(X) == X.pspace
|
| 137 |
+
assert pspace(2*X + 1) == X.pspace
|
| 138 |
+
assert pspace(2*X + Y) == IndependentProductPSpace(Y.pspace, X.pspace)
|
| 139 |
+
|
| 140 |
+
def test_rs_swap():
|
| 141 |
+
X = Normal('x', 0, 1)
|
| 142 |
+
Y = Exponential('y', 1)
|
| 143 |
+
|
| 144 |
+
XX = Normal('x', 0, 2)
|
| 145 |
+
YY = Normal('y', 0, 3)
|
| 146 |
+
|
| 147 |
+
expr = 2*X + Y
|
| 148 |
+
assert expr.subs(rs_swap((X, Y), (YY, XX))) == 2*XX + YY
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def test_RandomSymbol():
|
| 152 |
+
|
| 153 |
+
X = Normal('x', 0, 1)
|
| 154 |
+
Y = Normal('x', 0, 2)
|
| 155 |
+
assert X.symbol == Y.symbol
|
| 156 |
+
assert X != Y
|
| 157 |
+
|
| 158 |
+
assert X.name == X.symbol.name
|
| 159 |
+
|
| 160 |
+
X = Normal('lambda', 0, 1) # make sure we can use protected terms
|
| 161 |
+
X = Normal('Lambda', 0, 1) # make sure we can use SymPy terms
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def test_RandomSymbol_diff():
|
| 165 |
+
X = Normal('x', 0, 1)
|
| 166 |
+
assert (2*X).diff(X)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def test_random_symbol_no_pspace():
|
| 170 |
+
x = RandomSymbol(Symbol('x'))
|
| 171 |
+
assert x.pspace == PSpace()
|
| 172 |
+
|
| 173 |
+
def test_overlap():
|
| 174 |
+
X = Normal('x', 0, 1)
|
| 175 |
+
Y = Normal('x', 0, 2)
|
| 176 |
+
|
| 177 |
+
raises(ValueError, lambda: P(X > Y))
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def test_IndependentProductPSpace():
|
| 181 |
+
X = Normal('X', 0, 1)
|
| 182 |
+
Y = Normal('Y', 0, 1)
|
| 183 |
+
px = X.pspace
|
| 184 |
+
py = Y.pspace
|
| 185 |
+
assert pspace(X + Y) == IndependentProductPSpace(px, py)
|
| 186 |
+
assert pspace(X + Y) == IndependentProductPSpace(py, px)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
def test_E():
|
| 190 |
+
assert E(5) == 5
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def test_H():
|
| 194 |
+
X = Normal('X', 0, 1)
|
| 195 |
+
D = Die('D', sides = 4)
|
| 196 |
+
G = Geometric('G', 0.5)
|
| 197 |
+
assert H(X, X > 0) == -log(2)/2 + S.Half + log(pi)/2
|
| 198 |
+
assert H(D, D > 2) == log(2)
|
| 199 |
+
assert comp(H(G).evalf().round(2), 1.39)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def test_Sample():
|
| 203 |
+
X = Die('X', 6)
|
| 204 |
+
Y = Normal('Y', 0, 1)
|
| 205 |
+
z = Symbol('z', integer=True)
|
| 206 |
+
|
| 207 |
+
scipy = import_module('scipy')
|
| 208 |
+
if not scipy:
|
| 209 |
+
skip('Scipy is not installed. Abort tests')
|
| 210 |
+
assert sample(X) in [1, 2, 3, 4, 5, 6]
|
| 211 |
+
assert isinstance(sample(X + Y), float)
|
| 212 |
+
|
| 213 |
+
assert P(X + Y > 0, Y < 0, numsamples=10).is_number
|
| 214 |
+
assert E(X + Y, numsamples=10).is_number
|
| 215 |
+
assert E(X**2 + Y, numsamples=10).is_number
|
| 216 |
+
assert E((X + Y)**2, numsamples=10).is_number
|
| 217 |
+
assert variance(X + Y, numsamples=10).is_number
|
| 218 |
+
|
| 219 |
+
raises(TypeError, lambda: P(Y > z, numsamples=5))
|
| 220 |
+
|
| 221 |
+
assert P(sin(Y) <= 1, numsamples=10) == 1.0
|
| 222 |
+
assert P(sin(Y) <= 1, cos(Y) < 1, numsamples=10) == 1.0
|
| 223 |
+
|
| 224 |
+
assert all(i in range(1, 7) for i in density(X, numsamples=10))
|
| 225 |
+
assert all(i in range(4, 7) for i in density(X, X>3, numsamples=10))
|
| 226 |
+
|
| 227 |
+
numpy = import_module('numpy')
|
| 228 |
+
if not numpy:
|
| 229 |
+
skip('Numpy is not installed. Abort tests')
|
| 230 |
+
#Test Issue #21563: Output of sample must be a float or array
|
| 231 |
+
assert isinstance(sample(X), (numpy.int32, numpy.int64))
|
| 232 |
+
assert isinstance(sample(Y), numpy.float64)
|
| 233 |
+
assert isinstance(sample(X, size=2), numpy.ndarray)
|
| 234 |
+
|
| 235 |
+
with warns_deprecated_sympy():
|
| 236 |
+
sample(X, numsamples=2)
|
| 237 |
+
|
| 238 |
+
@XFAIL
|
| 239 |
+
def test_samplingE():
|
| 240 |
+
scipy = import_module('scipy')
|
| 241 |
+
if not scipy:
|
| 242 |
+
skip('Scipy is not installed. Abort tests')
|
| 243 |
+
Y = Normal('Y', 0, 1)
|
| 244 |
+
z = Symbol('z', integer=True)
|
| 245 |
+
assert E(Sum(1/z**Y, (z, 1, oo)), Y > 2, numsamples=3).is_number
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def test_given():
|
| 249 |
+
X = Normal('X', 0, 1)
|
| 250 |
+
Y = Normal('Y', 0, 1)
|
| 251 |
+
A = given(X, True)
|
| 252 |
+
B = given(X, Y > 2)
|
| 253 |
+
|
| 254 |
+
assert X == A == B
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def test_factorial_moment():
|
| 258 |
+
X = Poisson('X', 2)
|
| 259 |
+
Y = Binomial('Y', 2, S.Half)
|
| 260 |
+
Z = Hypergeometric('Z', 4, 2, 2)
|
| 261 |
+
assert factorial_moment(X, 2) == 4
|
| 262 |
+
assert factorial_moment(Y, 2) == S.Half
|
| 263 |
+
assert factorial_moment(Z, 2) == Rational(1, 3)
|
| 264 |
+
|
| 265 |
+
x, y, z, l = symbols('x y z l')
|
| 266 |
+
Y = Binomial('Y', 2, y)
|
| 267 |
+
Z = Hypergeometric('Z', 10, 2, 3)
|
| 268 |
+
assert factorial_moment(Y, l) == y**2*FallingFactorial(
|
| 269 |
+
2, l) + 2*y*(1 - y)*FallingFactorial(1, l) + (1 - y)**2*\
|
| 270 |
+
FallingFactorial(0, l)
|
| 271 |
+
assert factorial_moment(Z, l) == 7*FallingFactorial(0, l)/\
|
| 272 |
+
15 + 7*FallingFactorial(1, l)/15 + FallingFactorial(2, l)/15
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def test_dependence():
|
| 276 |
+
X, Y = Die('X'), Die('Y')
|
| 277 |
+
assert independent(X, 2*Y)
|
| 278 |
+
assert not dependent(X, 2*Y)
|
| 279 |
+
|
| 280 |
+
X, Y = Normal('X', 0, 1), Normal('Y', 0, 1)
|
| 281 |
+
assert independent(X, Y)
|
| 282 |
+
assert dependent(X, 2*X)
|
| 283 |
+
|
| 284 |
+
# Create a dependency
|
| 285 |
+
XX, YY = given(Tuple(X, Y), Eq(X + Y, 3))
|
| 286 |
+
assert dependent(XX, YY)
|
| 287 |
+
|
| 288 |
+
def test_dependent_finite():
|
| 289 |
+
X, Y = Die('X'), Die('Y')
|
| 290 |
+
# Dependence testing requires symbolic conditions which currently break
|
| 291 |
+
# finite random variables
|
| 292 |
+
assert dependent(X, Y + X)
|
| 293 |
+
|
| 294 |
+
XX, YY = given(Tuple(X, Y), X + Y > 5) # Create a dependency
|
| 295 |
+
assert dependent(XX, YY)
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
def test_normality():
|
| 299 |
+
X, Y = Normal('X', 0, 1), Normal('Y', 0, 1)
|
| 300 |
+
x = Symbol('x', real=True)
|
| 301 |
+
z = Symbol('z', real=True)
|
| 302 |
+
dens = density(X - Y, Eq(X + Y, z))
|
| 303 |
+
|
| 304 |
+
assert integrate(dens(x), (x, -oo, oo)) == 1
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def test_Density():
|
| 308 |
+
X = Die('X', 6)
|
| 309 |
+
d = Density(X)
|
| 310 |
+
assert d.doit() == density(X)
|
| 311 |
+
|
| 312 |
+
def test_NamedArgsMixin():
|
| 313 |
+
class Foo(Basic, NamedArgsMixin):
|
| 314 |
+
_argnames = 'foo', 'bar'
|
| 315 |
+
|
| 316 |
+
a = Foo(S(1), S(2))
|
| 317 |
+
|
| 318 |
+
assert a.foo == 1
|
| 319 |
+
assert a.bar == 2
|
| 320 |
+
|
| 321 |
+
raises(AttributeError, lambda: a.baz)
|
| 322 |
+
|
| 323 |
+
class Bar(Basic, NamedArgsMixin):
|
| 324 |
+
pass
|
| 325 |
+
|
| 326 |
+
raises(AttributeError, lambda: Bar(S(1), S(2)).foo)
|
| 327 |
+
|
| 328 |
+
def test_density_constant():
|
| 329 |
+
assert density(3)(2) == 0
|
| 330 |
+
assert density(3)(3) == DiracDelta(0)
|
| 331 |
+
|
| 332 |
+
def test_cmoment_constant():
|
| 333 |
+
assert variance(3) == 0
|
| 334 |
+
assert cmoment(3, 3) == 0
|
| 335 |
+
assert cmoment(3, 4) == 0
|
| 336 |
+
x = Symbol('x')
|
| 337 |
+
assert variance(x) == 0
|
| 338 |
+
assert cmoment(x, 15) == 0
|
| 339 |
+
assert cmoment(x, 0) == 1
|
| 340 |
+
|
| 341 |
+
def test_moment_constant():
|
| 342 |
+
assert moment(3, 0) == 1
|
| 343 |
+
assert moment(3, 1) == 3
|
| 344 |
+
assert moment(3, 2) == 9
|
| 345 |
+
x = Symbol('x')
|
| 346 |
+
assert moment(x, 2) == x**2
|
| 347 |
+
|
| 348 |
+
def test_median_constant():
|
| 349 |
+
assert median(3) == 3
|
| 350 |
+
x = Symbol('x')
|
| 351 |
+
assert median(x) == x
|
| 352 |
+
|
| 353 |
+
def test_real():
|
| 354 |
+
x = Normal('x', 0, 1)
|
| 355 |
+
assert x.is_real
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
def test_issue_10052():
|
| 359 |
+
X = Exponential('X', 3)
|
| 360 |
+
assert P(X < oo) == 1
|
| 361 |
+
assert P(X > oo) == 0
|
| 362 |
+
assert P(X < 2, X > oo) == 0
|
| 363 |
+
assert P(X < oo, X > oo) == 0
|
| 364 |
+
assert P(X < oo, X > 2) == 1
|
| 365 |
+
assert P(X < 3, X == 2) == 0
|
| 366 |
+
raises(ValueError, lambda: P(1))
|
| 367 |
+
raises(ValueError, lambda: P(X < 1, 2))
|
| 368 |
+
|
| 369 |
+
def test_issue_11934():
|
| 370 |
+
density = {0: .5, 1: .5}
|
| 371 |
+
X = FiniteRV('X', density)
|
| 372 |
+
assert E(X) == 0.5
|
| 373 |
+
assert P( X>= 2) == 0
|
| 374 |
+
|
| 375 |
+
def test_issue_8129():
|
| 376 |
+
X = Exponential('X', 4)
|
| 377 |
+
assert P(X >= X) == 1
|
| 378 |
+
assert P(X > X) == 0
|
| 379 |
+
assert P(X > X+1) == 0
|
| 380 |
+
|
| 381 |
+
def test_issue_12237():
|
| 382 |
+
X = Normal('X', 0, 1)
|
| 383 |
+
Y = Normal('Y', 0, 1)
|
| 384 |
+
U = P(X > 0, X)
|
| 385 |
+
V = P(Y < 0, X)
|
| 386 |
+
W = P(X + Y > 0, X)
|
| 387 |
+
assert W == P(X + Y > 0, X)
|
| 388 |
+
assert U == BernoulliDistribution(S.Half, S.Zero, S.One)
|
| 389 |
+
assert V == S.Half
|
| 390 |
+
|
| 391 |
+
def test_is_random():
|
| 392 |
+
X = Normal('X', 0, 1)
|
| 393 |
+
Y = Normal('Y', 0, 1)
|
| 394 |
+
a, b = symbols('a, b')
|
| 395 |
+
G = GaussianUnitaryEnsemble('U', 2)
|
| 396 |
+
B = BernoulliProcess('B', 0.9)
|
| 397 |
+
assert not is_random(a)
|
| 398 |
+
assert not is_random(a + b)
|
| 399 |
+
assert not is_random(a * b)
|
| 400 |
+
assert not is_random(Matrix([a**2, b**2]))
|
| 401 |
+
assert is_random(X)
|
| 402 |
+
assert is_random(X**2 + Y)
|
| 403 |
+
assert is_random(Y + b**2)
|
| 404 |
+
assert is_random(Y > 5)
|
| 405 |
+
assert is_random(B[3] < 1)
|
| 406 |
+
assert is_random(G)
|
| 407 |
+
assert is_random(X * Y * B[1])
|
| 408 |
+
assert is_random(Matrix([[X, B[2]], [G, Y]]))
|
| 409 |
+
assert is_random(Eq(X, 4))
|
| 410 |
+
|
| 411 |
+
def test_issue_12283():
|
| 412 |
+
x = symbols('x')
|
| 413 |
+
X = RandomSymbol(x)
|
| 414 |
+
Y = RandomSymbol('Y')
|
| 415 |
+
Z = RandomMatrixSymbol('Z', 2, 1)
|
| 416 |
+
W = RandomMatrixSymbol('W', 2, 1)
|
| 417 |
+
RI = RandomIndexedSymbol(Indexed('RI', 3))
|
| 418 |
+
assert pspace(Z) == PSpace()
|
| 419 |
+
assert pspace(RI) == PSpace()
|
| 420 |
+
assert pspace(X) == PSpace()
|
| 421 |
+
assert E(X) == Expectation(X)
|
| 422 |
+
assert P(Y > 3) == Probability(Y > 3)
|
| 423 |
+
assert variance(X) == Variance(X)
|
| 424 |
+
assert variance(RI) == Variance(RI)
|
| 425 |
+
assert covariance(X, Y) == Covariance(X, Y)
|
| 426 |
+
assert covariance(W, Z) == Covariance(W, Z)
|
| 427 |
+
|
| 428 |
+
def test_issue_6810():
|
| 429 |
+
X = Die('X', 6)
|
| 430 |
+
Y = Normal('Y', 0, 1)
|
| 431 |
+
assert P(Eq(X, 2)) == S(1)/6
|
| 432 |
+
assert P(Eq(Y, 0)) == 0
|
| 433 |
+
assert P(Or(X > 2, X < 3)) == 1
|
| 434 |
+
assert P(And(X > 3, X > 2)) == S(1)/2
|
| 435 |
+
|
| 436 |
+
def test_issue_20286():
|
| 437 |
+
n, p = symbols('n p')
|
| 438 |
+
B = Binomial('B', n, p)
|
| 439 |
+
k = Dummy('k', integer = True)
|
| 440 |
+
eq = Sum(Piecewise((-p**k*(1 - p)**(-k + n)*log(p**k*(1 - p)**(-k + n)*binomial(n, k))*binomial(n, k), (k >= 0) & (k <= n)), (nan, True)), (k, 0, n))
|
| 441 |
+
assert eq.dummy_eq(H(B))
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_stochastic_process.py
ADDED
|
@@ -0,0 +1,763 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.containers import Tuple
|
| 3 |
+
from sympy.core.function import Lambda
|
| 4 |
+
from sympy.core.numbers import (Float, Rational, oo, pi)
|
| 5 |
+
from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne)
|
| 6 |
+
from sympy.core.singleton import S
|
| 7 |
+
from sympy.core.symbol import (Symbol, symbols)
|
| 8 |
+
from sympy.functions.combinatorial.factorials import factorial
|
| 9 |
+
from sympy.functions.elementary.exponential import exp
|
| 10 |
+
from sympy.functions.elementary.integers import ceiling
|
| 11 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 12 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 13 |
+
from sympy.functions.special.error_functions import erf
|
| 14 |
+
from sympy.functions.special.gamma_functions import (gamma, lowergamma)
|
| 15 |
+
from sympy.logic.boolalg import (And, Not)
|
| 16 |
+
from sympy.matrices.dense import Matrix
|
| 17 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 18 |
+
from sympy.matrices.immutable import ImmutableMatrix
|
| 19 |
+
from sympy.sets.contains import Contains
|
| 20 |
+
from sympy.sets.fancysets import Range
|
| 21 |
+
from sympy.sets.sets import (FiniteSet, Interval)
|
| 22 |
+
from sympy.stats import (DiscreteMarkovChain, P, TransitionMatrixOf, E,
|
| 23 |
+
StochasticStateSpaceOf, variance, ContinuousMarkovChain,
|
| 24 |
+
BernoulliProcess, PoissonProcess, WienerProcess,
|
| 25 |
+
GammaProcess, sample_stochastic_process)
|
| 26 |
+
from sympy.stats.joint_rv import JointDistribution
|
| 27 |
+
from sympy.stats.joint_rv_types import JointDistributionHandmade
|
| 28 |
+
from sympy.stats.rv import RandomIndexedSymbol
|
| 29 |
+
from sympy.stats.symbolic_probability import Probability, Expectation
|
| 30 |
+
from sympy.testing.pytest import (raises, skip, ignore_warnings,
|
| 31 |
+
warns_deprecated_sympy)
|
| 32 |
+
from sympy.external import import_module
|
| 33 |
+
from sympy.stats.frv_types import BernoulliDistribution
|
| 34 |
+
from sympy.stats.drv_types import PoissonDistribution
|
| 35 |
+
from sympy.stats.crv_types import NormalDistribution, GammaDistribution
|
| 36 |
+
from sympy.core.symbol import Str
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_DiscreteMarkovChain():
|
| 40 |
+
|
| 41 |
+
# pass only the name
|
| 42 |
+
X = DiscreteMarkovChain("X")
|
| 43 |
+
assert isinstance(X.state_space, Range)
|
| 44 |
+
assert X.index_set == S.Naturals0
|
| 45 |
+
assert isinstance(X.transition_probabilities, MatrixSymbol)
|
| 46 |
+
t = symbols('t', positive=True, integer=True)
|
| 47 |
+
assert isinstance(X[t], RandomIndexedSymbol)
|
| 48 |
+
assert E(X[0]) == Expectation(X[0])
|
| 49 |
+
raises(TypeError, lambda: DiscreteMarkovChain(1))
|
| 50 |
+
raises(NotImplementedError, lambda: X(t))
|
| 51 |
+
raises(NotImplementedError, lambda: X.communication_classes())
|
| 52 |
+
raises(NotImplementedError, lambda: X.canonical_form())
|
| 53 |
+
raises(NotImplementedError, lambda: X.decompose())
|
| 54 |
+
|
| 55 |
+
nz = Symbol('n', integer=True)
|
| 56 |
+
TZ = MatrixSymbol('M', nz, nz)
|
| 57 |
+
SZ = Range(nz)
|
| 58 |
+
YZ = DiscreteMarkovChain('Y', SZ, TZ)
|
| 59 |
+
assert P(Eq(YZ[2], 1), Eq(YZ[1], 0)) == TZ[0, 1]
|
| 60 |
+
|
| 61 |
+
raises(ValueError, lambda: sample_stochastic_process(t))
|
| 62 |
+
raises(ValueError, lambda: next(sample_stochastic_process(X)))
|
| 63 |
+
# pass name and state_space
|
| 64 |
+
# any hashable object should be a valid state
|
| 65 |
+
# states should be valid as a tuple/set/list/Tuple/Range
|
| 66 |
+
sym, rainy, cloudy, sunny = symbols('a Rainy Cloudy Sunny', real=True)
|
| 67 |
+
state_spaces = [(1, 2, 3), [Str('Hello'), sym, DiscreteMarkovChain("Y", (1,2,3))],
|
| 68 |
+
Tuple(S(1), exp(sym), Str('World'), sympify=False), Range(-1, 5, 2),
|
| 69 |
+
[rainy, cloudy, sunny]]
|
| 70 |
+
chains = [DiscreteMarkovChain("Y", state_space) for state_space in state_spaces]
|
| 71 |
+
|
| 72 |
+
for i, Y in enumerate(chains):
|
| 73 |
+
assert isinstance(Y.transition_probabilities, MatrixSymbol)
|
| 74 |
+
assert Y.state_space == state_spaces[i] or Y.state_space == FiniteSet(*state_spaces[i])
|
| 75 |
+
assert Y.number_of_states == 3
|
| 76 |
+
|
| 77 |
+
with ignore_warnings(UserWarning): # TODO: Restore tests once warnings are removed
|
| 78 |
+
assert P(Eq(Y[2], 1), Eq(Y[0], 2), evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2))
|
| 79 |
+
assert E(Y[0]) == Expectation(Y[0])
|
| 80 |
+
|
| 81 |
+
raises(ValueError, lambda: next(sample_stochastic_process(Y)))
|
| 82 |
+
|
| 83 |
+
raises(TypeError, lambda: DiscreteMarkovChain("Y", {1: 1}))
|
| 84 |
+
Y = DiscreteMarkovChain("Y", Range(1, t, 2))
|
| 85 |
+
assert Y.number_of_states == ceiling((t-1)/2)
|
| 86 |
+
|
| 87 |
+
# pass name and transition_probabilities
|
| 88 |
+
chains = [DiscreteMarkovChain("Y", trans_probs=Matrix([])),
|
| 89 |
+
DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])),
|
| 90 |
+
DiscreteMarkovChain("Y", trans_probs=Matrix([[pi, 1-pi], [sym, 1-sym]]))]
|
| 91 |
+
for Z in chains:
|
| 92 |
+
assert Z.number_of_states == Z.transition_probabilities.shape[0]
|
| 93 |
+
assert isinstance(Z.transition_probabilities, ImmutableMatrix)
|
| 94 |
+
|
| 95 |
+
# pass name, state_space and transition_probabilities
|
| 96 |
+
T = Matrix([[0.5, 0.2, 0.3],[0.2, 0.5, 0.3],[0.2, 0.3, 0.5]])
|
| 97 |
+
TS = MatrixSymbol('T', 3, 3)
|
| 98 |
+
Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 99 |
+
YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS)
|
| 100 |
+
assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3])
|
| 101 |
+
raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol))
|
| 102 |
+
assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2)
|
| 103 |
+
assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) -
|
| 104 |
+
(TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2])).simplify() == 0
|
| 105 |
+
assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1))
|
| 106 |
+
assert P(Eq(YS[3], 3), Eq(YS[1], 1)) == TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2]
|
| 107 |
+
TO = Matrix([[0.25, 0.75, 0],[0, 0.25, 0.75],[0.75, 0, 0.25]])
|
| 108 |
+
assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float(0.375, 3)
|
| 109 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 110 |
+
assert E(Y[3], evaluate=False) == Expectation(Y[3])
|
| 111 |
+
assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3)
|
| 112 |
+
TSO = MatrixSymbol('T', 4, 4)
|
| 113 |
+
raises(ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO))))
|
| 114 |
+
raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M')))
|
| 115 |
+
raises(ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4)))
|
| 116 |
+
raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6)))
|
| 117 |
+
raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1)))
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
# extended tests for probability queries
|
| 121 |
+
TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]])
|
| 122 |
+
assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)),
|
| 123 |
+
Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16)
|
| 124 |
+
assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \
|
| 125 |
+
Probability(Eq(Y[0], 0))/4
|
| 126 |
+
assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) &
|
| 127 |
+
StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4)
|
| 128 |
+
assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) &
|
| 129 |
+
StochasticStateSpaceOf(X, [S(0), '0', 1]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4)
|
| 130 |
+
assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) &
|
| 131 |
+
StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero
|
| 132 |
+
assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) &
|
| 133 |
+
StochasticStateSpaceOf(X, [S(0), '0', 1]) & TransitionMatrixOf(X, TO1)) is S.Zero
|
| 134 |
+
assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1*Probability(Eq(Y[0], 0))
|
| 135 |
+
|
| 136 |
+
# testing properties of Markov chain
|
| 137 |
+
TO2 = Matrix([[S.One, 0, 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]])
|
| 138 |
+
TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]])
|
| 139 |
+
Y2 = DiscreteMarkovChain('Y', trans_probs=TO2)
|
| 140 |
+
Y3 = DiscreteMarkovChain('Y', trans_probs=TO3)
|
| 141 |
+
assert Y3.fundamental_matrix() == ImmutableMatrix([[176, 81, -132], [36, 141, -52], [-44, -39, 208]])/125
|
| 142 |
+
assert Y2.is_absorbing_chain() == True
|
| 143 |
+
assert Y3.is_absorbing_chain() == False
|
| 144 |
+
assert Y2.canonical_form() == ([0, 1, 2], TO2)
|
| 145 |
+
assert Y3.canonical_form() == ([0, 1, 2], TO3)
|
| 146 |
+
assert Y2.decompose() == ([0, 1, 2], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3])
|
| 147 |
+
assert Y3.decompose() == ([0, 1, 2], TO3, Matrix(0, 3, []), Matrix(0, 0, []))
|
| 148 |
+
TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]])
|
| 149 |
+
Y4 = DiscreteMarkovChain('Y', trans_probs=TO4)
|
| 150 |
+
w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]])
|
| 151 |
+
assert Y4.limiting_distribution == w
|
| 152 |
+
assert Y4.is_regular() == True
|
| 153 |
+
assert Y4.is_ergodic() == True
|
| 154 |
+
TS1 = MatrixSymbol('T', 3, 3)
|
| 155 |
+
Y5 = DiscreteMarkovChain('Y', trans_probs=TS1)
|
| 156 |
+
assert Y5.limiting_distribution(w, TO4).doit() == True
|
| 157 |
+
assert Y5.stationary_distribution(condition_set=True).subs(TS1, TO4).contains(w).doit() == S.true
|
| 158 |
+
TO6 = Matrix([[S.One, 0, 0, 0, 0],[S.Half, 0, S.Half, 0, 0],[0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]])
|
| 159 |
+
Y6 = DiscreteMarkovChain('Y', trans_probs=TO6)
|
| 160 |
+
assert Y6.fundamental_matrix() == ImmutableMatrix([[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]])
|
| 161 |
+
assert Y6.absorbing_probabilities() == ImmutableMatrix([[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]])
|
| 162 |
+
with warns_deprecated_sympy():
|
| 163 |
+
Y6.absorbing_probabilites()
|
| 164 |
+
TO7 = Matrix([[Rational(1, 2), Rational(1, 4), Rational(1, 4)], [Rational(1, 2), 0, Rational(1, 2)], [Rational(1, 4), Rational(1, 4), Rational(1, 2)]])
|
| 165 |
+
Y7 = DiscreteMarkovChain('Y', trans_probs=TO7)
|
| 166 |
+
assert Y7.is_absorbing_chain() == False
|
| 167 |
+
assert Y7.fundamental_matrix() == ImmutableMatrix([[Rational(86, 75), Rational(1, 25), Rational(-14, 75)],
|
| 168 |
+
[Rational(2, 25), Rational(21, 25), Rational(2, 25)],
|
| 169 |
+
[Rational(-14, 75), Rational(1, 25), Rational(86, 75)]])
|
| 170 |
+
|
| 171 |
+
# test for zero-sized matrix functionality
|
| 172 |
+
X = DiscreteMarkovChain('X', trans_probs=Matrix([]))
|
| 173 |
+
assert X.number_of_states == 0
|
| 174 |
+
assert X.stationary_distribution() == Matrix([[]])
|
| 175 |
+
assert X.communication_classes() == []
|
| 176 |
+
assert X.canonical_form() == ([], Matrix([]))
|
| 177 |
+
assert X.decompose() == ([], Matrix([]), Matrix([]), Matrix([]))
|
| 178 |
+
assert X.is_regular() == False
|
| 179 |
+
assert X.is_ergodic() == False
|
| 180 |
+
|
| 181 |
+
# test communication_class
|
| 182 |
+
# see https://drive.google.com/drive/folders/1HbxLlwwn2b3U8Lj7eb_ASIUb5vYaNIjg?usp=sharing
|
| 183 |
+
# tutorial 2.pdf
|
| 184 |
+
TO7 = Matrix([[0, 5, 5, 0, 0],
|
| 185 |
+
[0, 0, 0, 10, 0],
|
| 186 |
+
[5, 0, 5, 0, 0],
|
| 187 |
+
[0, 10, 0, 0, 0],
|
| 188 |
+
[0, 3, 0, 3, 4]])/10
|
| 189 |
+
Y7 = DiscreteMarkovChain('Y', trans_probs=TO7)
|
| 190 |
+
tuples = Y7.communication_classes()
|
| 191 |
+
classes, recurrence, periods = list(zip(*tuples))
|
| 192 |
+
assert classes == ([1, 3], [0, 2], [4])
|
| 193 |
+
assert recurrence == (True, False, False)
|
| 194 |
+
assert periods == (2, 1, 1)
|
| 195 |
+
|
| 196 |
+
TO8 = Matrix([[0, 0, 0, 10, 0, 0],
|
| 197 |
+
[5, 0, 5, 0, 0, 0],
|
| 198 |
+
[0, 4, 0, 0, 0, 6],
|
| 199 |
+
[10, 0, 0, 0, 0, 0],
|
| 200 |
+
[0, 10, 0, 0, 0, 0],
|
| 201 |
+
[0, 0, 0, 5, 5, 0]])/10
|
| 202 |
+
Y8 = DiscreteMarkovChain('Y', trans_probs=TO8)
|
| 203 |
+
tuples = Y8.communication_classes()
|
| 204 |
+
classes, recurrence, periods = list(zip(*tuples))
|
| 205 |
+
assert classes == ([0, 3], [1, 2, 5, 4])
|
| 206 |
+
assert recurrence == (True, False)
|
| 207 |
+
assert periods == (2, 2)
|
| 208 |
+
|
| 209 |
+
TO9 = Matrix([[2, 0, 0, 3, 0, 0, 3, 2, 0, 0],
|
| 210 |
+
[0, 10, 0, 0, 0, 0, 0, 0, 0, 0],
|
| 211 |
+
[0, 2, 2, 0, 0, 0, 0, 0, 3, 3],
|
| 212 |
+
[0, 0, 0, 3, 0, 0, 6, 1, 0, 0],
|
| 213 |
+
[0, 0, 0, 0, 5, 5, 0, 0, 0, 0],
|
| 214 |
+
[0, 0, 0, 0, 0, 10, 0, 0, 0, 0],
|
| 215 |
+
[4, 0, 0, 5, 0, 0, 1, 0, 0, 0],
|
| 216 |
+
[2, 0, 0, 4, 0, 0, 2, 2, 0, 0],
|
| 217 |
+
[3, 0, 1, 0, 0, 0, 0, 0, 4, 2],
|
| 218 |
+
[0, 0, 4, 0, 0, 0, 0, 0, 3, 3]])/10
|
| 219 |
+
Y9 = DiscreteMarkovChain('Y', trans_probs=TO9)
|
| 220 |
+
tuples = Y9.communication_classes()
|
| 221 |
+
classes, recurrence, periods = list(zip(*tuples))
|
| 222 |
+
assert classes == ([0, 3, 6, 7], [1], [2, 8, 9], [5], [4])
|
| 223 |
+
assert recurrence == (True, True, False, True, False)
|
| 224 |
+
assert periods == (1, 1, 1, 1, 1)
|
| 225 |
+
|
| 226 |
+
# test canonical form
|
| 227 |
+
# see https://web.archive.org/web/20201230182007/https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
|
| 228 |
+
# example 11.13
|
| 229 |
+
T = Matrix([[1, 0, 0, 0, 0],
|
| 230 |
+
[S(1) / 2, 0, S(1) / 2, 0, 0],
|
| 231 |
+
[0, S(1) / 2, 0, S(1) / 2, 0],
|
| 232 |
+
[0, 0, S(1) / 2, 0, S(1) / 2],
|
| 233 |
+
[0, 0, 0, 0, S(1)]])
|
| 234 |
+
DW = DiscreteMarkovChain('DW', [0, 1, 2, 3, 4], T)
|
| 235 |
+
states, A, B, C = DW.decompose()
|
| 236 |
+
assert states == [0, 4, 1, 2, 3]
|
| 237 |
+
assert A == Matrix([[1, 0], [0, 1]])
|
| 238 |
+
assert B == Matrix([[S(1)/2, 0], [0, 0], [0, S(1)/2]])
|
| 239 |
+
assert C == Matrix([[0, S(1)/2, 0], [S(1)/2, 0, S(1)/2], [0, S(1)/2, 0]])
|
| 240 |
+
states, new_matrix = DW.canonical_form()
|
| 241 |
+
assert states == [0, 4, 1, 2, 3]
|
| 242 |
+
assert new_matrix == Matrix([[1, 0, 0, 0, 0],
|
| 243 |
+
[0, 1, 0, 0, 0],
|
| 244 |
+
[S(1)/2, 0, 0, S(1)/2, 0],
|
| 245 |
+
[0, 0, S(1)/2, 0, S(1)/2],
|
| 246 |
+
[0, S(1)/2, 0, S(1)/2, 0]])
|
| 247 |
+
|
| 248 |
+
# test regular and ergodic
|
| 249 |
+
# https://web.archive.org/web/20201230182007/https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
|
| 250 |
+
T = Matrix([[0, 4, 0, 0, 0],
|
| 251 |
+
[1, 0, 3, 0, 0],
|
| 252 |
+
[0, 2, 0, 2, 0],
|
| 253 |
+
[0, 0, 3, 0, 1],
|
| 254 |
+
[0, 0, 0, 4, 0]])/4
|
| 255 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 256 |
+
assert not X.is_regular()
|
| 257 |
+
assert X.is_ergodic()
|
| 258 |
+
T = Matrix([[0, 1], [1, 0]])
|
| 259 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 260 |
+
assert not X.is_regular()
|
| 261 |
+
assert X.is_ergodic()
|
| 262 |
+
# http://www.math.wisc.edu/~valko/courses/331/MC2.pdf
|
| 263 |
+
T = Matrix([[2, 1, 1],
|
| 264 |
+
[2, 0, 2],
|
| 265 |
+
[1, 1, 2]])/4
|
| 266 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 267 |
+
assert X.is_regular()
|
| 268 |
+
assert X.is_ergodic()
|
| 269 |
+
# https://docs.ufpr.br/~lucambio/CE222/1S2014/Kemeny-Snell1976.pdf
|
| 270 |
+
T = Matrix([[1, 1], [1, 1]])/2
|
| 271 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 272 |
+
assert X.is_regular()
|
| 273 |
+
assert X.is_ergodic()
|
| 274 |
+
|
| 275 |
+
# test is_absorbing_chain
|
| 276 |
+
T = Matrix([[0, 1, 0],
|
| 277 |
+
[1, 0, 0],
|
| 278 |
+
[0, 0, 1]])
|
| 279 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 280 |
+
assert not X.is_absorbing_chain()
|
| 281 |
+
# https://en.wikipedia.org/wiki/Absorbing_Markov_chain
|
| 282 |
+
T = Matrix([[1, 1, 0, 0],
|
| 283 |
+
[0, 1, 1, 0],
|
| 284 |
+
[1, 0, 0, 1],
|
| 285 |
+
[0, 0, 0, 2]])/2
|
| 286 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 287 |
+
assert X.is_absorbing_chain()
|
| 288 |
+
T = Matrix([[2, 0, 0, 0, 0],
|
| 289 |
+
[1, 0, 1, 0, 0],
|
| 290 |
+
[0, 1, 0, 1, 0],
|
| 291 |
+
[0, 0, 1, 0, 1],
|
| 292 |
+
[0, 0, 0, 0, 2]])/2
|
| 293 |
+
X = DiscreteMarkovChain('X', trans_probs=T)
|
| 294 |
+
assert X.is_absorbing_chain()
|
| 295 |
+
|
| 296 |
+
# test custom state space
|
| 297 |
+
Y10 = DiscreteMarkovChain('Y', [1, 2, 3], TO2)
|
| 298 |
+
tuples = Y10.communication_classes()
|
| 299 |
+
classes, recurrence, periods = list(zip(*tuples))
|
| 300 |
+
assert classes == ([1], [2, 3])
|
| 301 |
+
assert recurrence == (True, False)
|
| 302 |
+
assert periods == (1, 1)
|
| 303 |
+
assert Y10.canonical_form() == ([1, 2, 3], TO2)
|
| 304 |
+
assert Y10.decompose() == ([1, 2, 3], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3])
|
| 305 |
+
|
| 306 |
+
# testing miscellaneous queries
|
| 307 |
+
T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)],
|
| 308 |
+
[Rational(1, 3), 0, Rational(2, 3)],
|
| 309 |
+
[S.Half, S.Half, 0]])
|
| 310 |
+
X = DiscreteMarkovChain('X', [0, 1, 2], T)
|
| 311 |
+
assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0),
|
| 312 |
+
Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12)
|
| 313 |
+
assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3)
|
| 314 |
+
assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero
|
| 315 |
+
assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3)
|
| 316 |
+
assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3)
|
| 317 |
+
assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9)
|
| 318 |
+
raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
|
| 319 |
+
raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T))
|
| 320 |
+
|
| 321 |
+
# testing miscellaneous queries with different state space
|
| 322 |
+
X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T)
|
| 323 |
+
assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0),
|
| 324 |
+
Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12)
|
| 325 |
+
assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3)
|
| 326 |
+
assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero
|
| 327 |
+
assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3)
|
| 328 |
+
a = X.state_space.args[0]
|
| 329 |
+
c = X.state_space.args[2]
|
| 330 |
+
assert (E(X[1] ** 2, Eq(X[0], 1)) - (a**2/3 + 2*c**2/3)).simplify() == 0
|
| 331 |
+
assert (variance(X[1], Eq(X[0], 1)) - (2*(-a/3 + c/3)**2/3 + (2*a/3 - 2*c/3)**2/3)).simplify() == 0
|
| 332 |
+
raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
|
| 333 |
+
|
| 334 |
+
#testing queries with multiple RandomIndexedSymbols
|
| 335 |
+
T = Matrix([[Rational(5, 10), Rational(3, 10), Rational(2, 10)], [Rational(2, 10), Rational(7, 10), Rational(1, 10)], [Rational(3, 10), Rational(3, 10), Rational(4, 10)]])
|
| 336 |
+
Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 337 |
+
assert P(Eq(Y[7], Y[5]), Eq(Y[2], 0)).round(5) == Float(0.44428, 5)
|
| 338 |
+
assert P(Gt(Y[3], Y[1]), Eq(Y[0], 0)).round(2) == Float(0.36, 2)
|
| 339 |
+
assert P(Le(Y[5], Y[10]), Eq(Y[4], 2)).round(6) == Float(0.583120, 6)
|
| 340 |
+
assert Float(P(Eq(Y[10], Y[5]), Eq(Y[4], 1)), 14) == Float(1 - P(Ne(Y[10], Y[5]), Eq(Y[4], 1)), 14)
|
| 341 |
+
assert Float(P(Gt(Y[8], Y[9]), Eq(Y[3], 2)), 14) == Float(1 - P(Le(Y[8], Y[9]), Eq(Y[3], 2)), 14)
|
| 342 |
+
assert Float(P(Lt(Y[1], Y[4]), Eq(Y[0], 0)), 14) == Float(1 - P(Ge(Y[1], Y[4]), Eq(Y[0], 0)), 14)
|
| 343 |
+
assert P(Eq(Y[5], Y[10]), Eq(Y[2], 1)) == P(Eq(Y[10], Y[5]), Eq(Y[2], 1))
|
| 344 |
+
assert P(Gt(Y[1], Y[2]), Eq(Y[0], 1)) == P(Lt(Y[2], Y[1]), Eq(Y[0], 1))
|
| 345 |
+
assert P(Ge(Y[7], Y[6]), Eq(Y[4], 1)) == P(Le(Y[6], Y[7]), Eq(Y[4], 1))
|
| 346 |
+
|
| 347 |
+
#test symbolic queries
|
| 348 |
+
a, b, c, d = symbols('a b c d')
|
| 349 |
+
T = Matrix([[Rational(1, 10), Rational(4, 10), Rational(5, 10)], [Rational(3, 10), Rational(4, 10), Rational(3, 10)], [Rational(7, 10), Rational(2, 10), Rational(1, 10)]])
|
| 350 |
+
Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 351 |
+
query = P(Eq(Y[a], b), Eq(Y[c], d))
|
| 352 |
+
assert query.subs({a:10, b:2, c:5, d:1}).evalf().round(4) == P(Eq(Y[10], 2), Eq(Y[5], 1)).round(4)
|
| 353 |
+
assert query.subs({a:15, b:0, c:10, d:1}).evalf().round(4) == P(Eq(Y[15], 0), Eq(Y[10], 1)).round(4)
|
| 354 |
+
query_gt = P(Gt(Y[a], b), Eq(Y[c], d))
|
| 355 |
+
query_le = P(Le(Y[a], b), Eq(Y[c], d))
|
| 356 |
+
assert query_gt.subs({a:5, b:2, c:1, d:0}).evalf() + query_le.subs({a:5, b:2, c:1, d:0}).evalf() == 1.0
|
| 357 |
+
query_ge = P(Ge(Y[a], b), Eq(Y[c], d))
|
| 358 |
+
query_lt = P(Lt(Y[a], b), Eq(Y[c], d))
|
| 359 |
+
assert query_ge.subs({a:4, b:1, c:0, d:2}).evalf() + query_lt.subs({a:4, b:1, c:0, d:2}).evalf() == 1.0
|
| 360 |
+
|
| 361 |
+
#test issue 20078
|
| 362 |
+
assert (2*Y[1] + 3*Y[1]).simplify() == 5*Y[1]
|
| 363 |
+
assert (2*Y[1] - 3*Y[1]).simplify() == -Y[1]
|
| 364 |
+
assert (2*(0.25*Y[1])).simplify() == 0.5*Y[1]
|
| 365 |
+
assert ((2*Y[1]) * (0.25*Y[1])).simplify() == 0.5*Y[1]**2
|
| 366 |
+
assert (Y[1]**2 + Y[1]**3).simplify() == (Y[1] + 1)*Y[1]**2
|
| 367 |
+
|
| 368 |
+
def test_sample_stochastic_process():
|
| 369 |
+
if not import_module('scipy'):
|
| 370 |
+
skip('SciPy Not installed. Skip sampling tests')
|
| 371 |
+
import random
|
| 372 |
+
random.seed(0)
|
| 373 |
+
numpy = import_module('numpy')
|
| 374 |
+
if numpy:
|
| 375 |
+
numpy.random.seed(0) # scipy uses numpy to sample so to set its seed
|
| 376 |
+
T = Matrix([[0.5, 0.2, 0.3],[0.2, 0.5, 0.3],[0.2, 0.3, 0.5]])
|
| 377 |
+
Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
|
| 378 |
+
for samps in range(10):
|
| 379 |
+
assert next(sample_stochastic_process(Y)) in Y.state_space
|
| 380 |
+
Z = DiscreteMarkovChain("Z", ['1', 1, 0], T)
|
| 381 |
+
for samps in range(10):
|
| 382 |
+
assert next(sample_stochastic_process(Z)) in Z.state_space
|
| 383 |
+
|
| 384 |
+
T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)],
|
| 385 |
+
[Rational(1, 3), 0, Rational(2, 3)],
|
| 386 |
+
[S.Half, S.Half, 0]])
|
| 387 |
+
X = DiscreteMarkovChain('X', [0, 1, 2], T)
|
| 388 |
+
for samps in range(10):
|
| 389 |
+
assert next(sample_stochastic_process(X)) in X.state_space
|
| 390 |
+
W = DiscreteMarkovChain('W', [1, pi, oo], T)
|
| 391 |
+
for samps in range(10):
|
| 392 |
+
assert next(sample_stochastic_process(W)) in W.state_space
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
def test_ContinuousMarkovChain():
|
| 396 |
+
T1 = Matrix([[S(-2), S(2), S.Zero],
|
| 397 |
+
[S.Zero, S.NegativeOne, S.One],
|
| 398 |
+
[Rational(3, 2), Rational(3, 2), S(-3)]])
|
| 399 |
+
C1 = ContinuousMarkovChain('C', [0, 1, 2], T1)
|
| 400 |
+
assert C1.limiting_distribution() == ImmutableMatrix([[Rational(3, 19), Rational(12, 19), Rational(4, 19)]])
|
| 401 |
+
|
| 402 |
+
T2 = Matrix([[-S.One, S.One, S.Zero], [S.One, -S.One, S.Zero], [S.Zero, S.One, -S.One]])
|
| 403 |
+
C2 = ContinuousMarkovChain('C', [0, 1, 2], T2)
|
| 404 |
+
A, t = C2.generator_matrix, symbols('t', positive=True)
|
| 405 |
+
assert C2.transition_probabilities(A)(t) == Matrix([[S.Half + exp(-2*t)/2, S.Half - exp(-2*t)/2, 0],
|
| 406 |
+
[S.Half - exp(-2*t)/2, S.Half + exp(-2*t)/2, 0],
|
| 407 |
+
[S.Half - exp(-t) + exp(-2*t)/2, S.Half - exp(-2*t)/2, exp(-t)]])
|
| 408 |
+
with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed
|
| 409 |
+
assert P(Eq(C2(1), 1), Eq(C2(0), 1), evaluate=False) == Probability(Eq(C2(1), 1), Eq(C2(0), 1))
|
| 410 |
+
assert P(Eq(C2(1), 1), Eq(C2(0), 1)) == exp(-2)/2 + S.Half
|
| 411 |
+
assert P(Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 1),
|
| 412 |
+
Eq(P(Eq(C2(1), 0)), S.Half)) == (Rational(1, 4) - exp(-2)/4)*(exp(-2)/2 + S.Half)
|
| 413 |
+
assert P(Not(Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)) |
|
| 414 |
+
(Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)),
|
| 415 |
+
Eq(P(Eq(C2(1), 0)), Rational(1, 4)) & Eq(P(Eq(C2(1), 1)), Rational(1, 4))) is S.One
|
| 416 |
+
assert E(C2(Rational(3, 2)), Eq(C2(0), 2)) == -exp(-3)/2 + 2*exp(Rational(-3, 2)) + S.Half
|
| 417 |
+
assert variance(C2(Rational(3, 2)), Eq(C2(0), 1)) == ((S.Half - exp(-3)/2)**2*(exp(-3)/2 + S.Half)
|
| 418 |
+
+ (Rational(-1, 2) - exp(-3)/2)**2*(S.Half - exp(-3)/2))
|
| 419 |
+
raises(KeyError, lambda: P(Eq(C2(1), 0), Eq(P(Eq(C2(1), 1)), S.Half)))
|
| 420 |
+
assert P(Eq(C2(1), 0), Eq(P(Eq(C2(5), 1)), S.Half)) == Probability(Eq(C2(1), 0))
|
| 421 |
+
TS1 = MatrixSymbol('G', 3, 3)
|
| 422 |
+
CS1 = ContinuousMarkovChain('C', [0, 1, 2], TS1)
|
| 423 |
+
A = CS1.generator_matrix
|
| 424 |
+
assert CS1.transition_probabilities(A)(t) == exp(t*A)
|
| 425 |
+
|
| 426 |
+
C3 = ContinuousMarkovChain('C', [Symbol('0'), Symbol('1'), Symbol('2')], T2)
|
| 427 |
+
assert P(Eq(C3(1), 1), Eq(C3(0), 1)) == exp(-2)/2 + S.Half
|
| 428 |
+
assert P(Eq(C3(1), Symbol('1')), Eq(C3(0), Symbol('1'))) == exp(-2)/2 + S.Half
|
| 429 |
+
|
| 430 |
+
#test probability queries
|
| 431 |
+
G = Matrix([[-S(1), Rational(1, 10), Rational(9, 10)], [Rational(2, 5), -S(1), Rational(3, 5)], [Rational(1, 2), Rational(1, 2), -S(1)]])
|
| 432 |
+
C = ContinuousMarkovChain('C', state_space=[0, 1, 2], gen_mat=G)
|
| 433 |
+
assert P(Eq(C(7.385), C(3.19)), Eq(C(0.862), 0)).round(5) == Float(0.35469, 5)
|
| 434 |
+
assert P(Gt(C(98.715), C(19.807)), Eq(C(11.314), 2)).round(5) == Float(0.32452, 5)
|
| 435 |
+
assert P(Le(C(5.9), C(10.112)), Eq(C(4), 1)).round(6) == Float(0.675214, 6)
|
| 436 |
+
assert Float(P(Eq(C(7.32), C(2.91)), Eq(C(2.63), 1)), 14) == Float(1 - P(Ne(C(7.32), C(2.91)), Eq(C(2.63), 1)), 14)
|
| 437 |
+
assert Float(P(Gt(C(3.36), C(1.101)), Eq(C(0.8), 2)), 14) == Float(1 - P(Le(C(3.36), C(1.101)), Eq(C(0.8), 2)), 14)
|
| 438 |
+
assert Float(P(Lt(C(4.9), C(2.79)), Eq(C(1.61), 0)), 14) == Float(1 - P(Ge(C(4.9), C(2.79)), Eq(C(1.61), 0)), 14)
|
| 439 |
+
assert P(Eq(C(5.243), C(10.912)), Eq(C(2.174), 1)) == P(Eq(C(10.912), C(5.243)), Eq(C(2.174), 1))
|
| 440 |
+
assert P(Gt(C(2.344), C(9.9)), Eq(C(1.102), 1)) == P(Lt(C(9.9), C(2.344)), Eq(C(1.102), 1))
|
| 441 |
+
assert P(Ge(C(7.87), C(1.008)), Eq(C(0.153), 1)) == P(Le(C(1.008), C(7.87)), Eq(C(0.153), 1))
|
| 442 |
+
|
| 443 |
+
#test symbolic queries
|
| 444 |
+
a, b, c, d = symbols('a b c d')
|
| 445 |
+
query = P(Eq(C(a), b), Eq(C(c), d))
|
| 446 |
+
assert query.subs({a:3.65, b:2, c:1.78, d:1}).evalf().round(10) == P(Eq(C(3.65), 2), Eq(C(1.78), 1)).round(10)
|
| 447 |
+
query_gt = P(Gt(C(a), b), Eq(C(c), d))
|
| 448 |
+
query_le = P(Le(C(a), b), Eq(C(c), d))
|
| 449 |
+
assert query_gt.subs({a:13.2, b:0, c:3.29, d:2}).evalf() + query_le.subs({a:13.2, b:0, c:3.29, d:2}).evalf() == 1.0
|
| 450 |
+
query_ge = P(Ge(C(a), b), Eq(C(c), d))
|
| 451 |
+
query_lt = P(Lt(C(a), b), Eq(C(c), d))
|
| 452 |
+
assert query_ge.subs({a:7.43, b:1, c:1.45, d:0}).evalf() + query_lt.subs({a:7.43, b:1, c:1.45, d:0}).evalf() == 1.0
|
| 453 |
+
|
| 454 |
+
#test issue 20078
|
| 455 |
+
assert (2*C(1) + 3*C(1)).simplify() == 5*C(1)
|
| 456 |
+
assert (2*C(1) - 3*C(1)).simplify() == -C(1)
|
| 457 |
+
assert (2*(0.25*C(1))).simplify() == 0.5*C(1)
|
| 458 |
+
assert (2*C(1) * 0.25*C(1)).simplify() == 0.5*C(1)**2
|
| 459 |
+
assert (C(1)**2 + C(1)**3).simplify() == (C(1) + 1)*C(1)**2
|
| 460 |
+
|
| 461 |
+
def test_BernoulliProcess():
|
| 462 |
+
|
| 463 |
+
B = BernoulliProcess("B", p=0.6, success=1, failure=0)
|
| 464 |
+
assert B.state_space == FiniteSet(0, 1)
|
| 465 |
+
assert B.index_set == S.Naturals0
|
| 466 |
+
assert B.success == 1
|
| 467 |
+
assert B.failure == 0
|
| 468 |
+
|
| 469 |
+
X = BernoulliProcess("X", p=Rational(1,3), success='H', failure='T')
|
| 470 |
+
assert X.state_space == FiniteSet('H', 'T')
|
| 471 |
+
H, T = symbols("H,T")
|
| 472 |
+
assert E(X[1]+X[2]*X[3]) == H**2/9 + 4*H*T/9 + H/3 + 4*T**2/9 + 2*T/3
|
| 473 |
+
|
| 474 |
+
t, x = symbols('t, x', positive=True, integer=True)
|
| 475 |
+
assert isinstance(B[t], RandomIndexedSymbol)
|
| 476 |
+
|
| 477 |
+
raises(ValueError, lambda: BernoulliProcess("X", p=1.1, success=1, failure=0))
|
| 478 |
+
raises(NotImplementedError, lambda: B(t))
|
| 479 |
+
|
| 480 |
+
raises(IndexError, lambda: B[-3])
|
| 481 |
+
assert B.joint_distribution(B[3], B[9]) == JointDistributionHandmade(Lambda((B[3], B[9]),
|
| 482 |
+
Piecewise((0.6, Eq(B[3], 1)), (0.4, Eq(B[3], 0)), (0, True))
|
| 483 |
+
*Piecewise((0.6, Eq(B[9], 1)), (0.4, Eq(B[9], 0)), (0, True))))
|
| 484 |
+
|
| 485 |
+
assert B.joint_distribution(2, B[4]) == JointDistributionHandmade(Lambda((B[2], B[4]),
|
| 486 |
+
Piecewise((0.6, Eq(B[2], 1)), (0.4, Eq(B[2], 0)), (0, True))
|
| 487 |
+
*Piecewise((0.6, Eq(B[4], 1)), (0.4, Eq(B[4], 0)), (0, True))))
|
| 488 |
+
|
| 489 |
+
# Test for the sum distribution of Bernoulli Process RVs
|
| 490 |
+
Y = B[1] + B[2] + B[3]
|
| 491 |
+
assert P(Eq(Y, 0)).round(2) == Float(0.06, 1)
|
| 492 |
+
assert P(Eq(Y, 2)).round(2) == Float(0.43, 2)
|
| 493 |
+
assert P(Eq(Y, 4)).round(2) == 0
|
| 494 |
+
assert P(Gt(Y, 1)).round(2) == Float(0.65, 2)
|
| 495 |
+
# Test for independency of each Random Indexed variable
|
| 496 |
+
assert P(Eq(B[1], 0) & Eq(B[2], 1) & Eq(B[3], 0) & Eq(B[4], 1)).round(2) == Float(0.06, 1)
|
| 497 |
+
|
| 498 |
+
assert E(2 * B[1] + B[2]).round(2) == Float(1.80, 3)
|
| 499 |
+
assert E(2 * B[1] + B[2] + 5).round(2) == Float(6.80, 3)
|
| 500 |
+
assert E(B[2] * B[4] + B[10]).round(2) == Float(0.96, 2)
|
| 501 |
+
assert E(B[2] > 0, Eq(B[1],1) & Eq(B[2],1)).round(2) == Float(0.60,2)
|
| 502 |
+
assert E(B[1]) == 0.6
|
| 503 |
+
assert P(B[1] > 0).round(2) == Float(0.60, 2)
|
| 504 |
+
assert P(B[1] < 1).round(2) == Float(0.40, 2)
|
| 505 |
+
assert P(B[1] > 0, B[2] <= 1).round(2) == Float(0.60, 2)
|
| 506 |
+
assert P(B[12] * B[5] > 0).round(2) == Float(0.36, 2)
|
| 507 |
+
assert P(B[12] * B[5] > 0, B[4] < 1).round(2) == Float(0.36, 2)
|
| 508 |
+
assert P(Eq(B[2], 1), B[2] > 0) == 1.0
|
| 509 |
+
assert P(Eq(B[5], 3)) == 0
|
| 510 |
+
assert P(Eq(B[1], 1), B[1] < 0) == 0
|
| 511 |
+
assert P(B[2] > 0, Eq(B[2], 1)) == 1
|
| 512 |
+
assert P(B[2] < 0, Eq(B[2], 1)) == 0
|
| 513 |
+
assert P(B[2] > 0, B[2]==7) == 0
|
| 514 |
+
assert P(B[5] > 0, B[5]) == BernoulliDistribution(0.6, 0, 1)
|
| 515 |
+
raises(ValueError, lambda: P(3))
|
| 516 |
+
raises(ValueError, lambda: P(B[3] > 0, 3))
|
| 517 |
+
|
| 518 |
+
# test issue 19456
|
| 519 |
+
expr = Sum(B[t], (t, 0, 4))
|
| 520 |
+
expr2 = Sum(B[t], (t, 1, 3))
|
| 521 |
+
expr3 = Sum(B[t]**2, (t, 1, 3))
|
| 522 |
+
assert expr.doit() == B[0] + B[1] + B[2] + B[3] + B[4]
|
| 523 |
+
assert expr2.doit() == Y
|
| 524 |
+
assert expr3.doit() == B[1]**2 + B[2]**2 + B[3]**2
|
| 525 |
+
assert B[2*t].free_symbols == {B[2*t], t}
|
| 526 |
+
assert B[4].free_symbols == {B[4]}
|
| 527 |
+
assert B[x*t].free_symbols == {B[x*t], x, t}
|
| 528 |
+
|
| 529 |
+
#test issue 20078
|
| 530 |
+
assert (2*B[t] + 3*B[t]).simplify() == 5*B[t]
|
| 531 |
+
assert (2*B[t] - 3*B[t]).simplify() == -B[t]
|
| 532 |
+
assert (2*(0.25*B[t])).simplify() == 0.5*B[t]
|
| 533 |
+
assert (2*B[t] * 0.25*B[t]).simplify() == 0.5*B[t]**2
|
| 534 |
+
assert (B[t]**2 + B[t]**3).simplify() == (B[t] + 1)*B[t]**2
|
| 535 |
+
|
| 536 |
+
def test_PoissonProcess():
|
| 537 |
+
X = PoissonProcess("X", 3)
|
| 538 |
+
assert X.state_space == S.Naturals0
|
| 539 |
+
assert X.index_set == Interval(0, oo)
|
| 540 |
+
assert X.lamda == 3
|
| 541 |
+
|
| 542 |
+
t, d, x, y = symbols('t d x y', positive=True)
|
| 543 |
+
assert isinstance(X(t), RandomIndexedSymbol)
|
| 544 |
+
assert X.distribution(t) == PoissonDistribution(3*t)
|
| 545 |
+
with warns_deprecated_sympy():
|
| 546 |
+
X.distribution(X(t))
|
| 547 |
+
raises(ValueError, lambda: PoissonProcess("X", -1))
|
| 548 |
+
raises(NotImplementedError, lambda: X[t])
|
| 549 |
+
raises(IndexError, lambda: X(-5))
|
| 550 |
+
|
| 551 |
+
assert X.joint_distribution(X(2), X(3)) == JointDistributionHandmade(Lambda((X(2), X(3)),
|
| 552 |
+
6**X(2)*9**X(3)*exp(-15)/(factorial(X(2))*factorial(X(3)))))
|
| 553 |
+
|
| 554 |
+
assert X.joint_distribution(4, 6) == JointDistributionHandmade(Lambda((X(4), X(6)),
|
| 555 |
+
12**X(4)*18**X(6)*exp(-30)/(factorial(X(4))*factorial(X(6)))))
|
| 556 |
+
|
| 557 |
+
assert P(X(t) < 1) == exp(-3*t)
|
| 558 |
+
assert P(Eq(X(t), 0), Contains(t, Interval.Lopen(3, 5))) == exp(-6) # exp(-2*lamda)
|
| 559 |
+
res = P(Eq(X(t), 1), Contains(t, Interval.Lopen(3, 4)))
|
| 560 |
+
assert res == 3*exp(-3)
|
| 561 |
+
|
| 562 |
+
# Equivalent to P(Eq(X(t), 1))**4 because of non-overlapping intervals
|
| 563 |
+
assert P(Eq(X(t), 1) & Eq(X(d), 1) & Eq(X(x), 1) & Eq(X(y), 1), Contains(t, Interval.Lopen(0, 1))
|
| 564 |
+
& Contains(d, Interval.Lopen(1, 2)) & Contains(x, Interval.Lopen(2, 3))
|
| 565 |
+
& Contains(y, Interval.Lopen(3, 4))) == res**4
|
| 566 |
+
|
| 567 |
+
# Return Probability because of overlapping intervals
|
| 568 |
+
assert P(Eq(X(t), 2) & Eq(X(d), 3), Contains(t, Interval.Lopen(0, 2))
|
| 569 |
+
& Contains(d, Interval.Ropen(2, 4))) == \
|
| 570 |
+
Probability(Eq(X(d), 3) & Eq(X(t), 2), Contains(t, Interval.Lopen(0, 2))
|
| 571 |
+
& Contains(d, Interval.Ropen(2, 4)))
|
| 572 |
+
|
| 573 |
+
raises(ValueError, lambda: P(Eq(X(t), 2) & Eq(X(d), 3),
|
| 574 |
+
Contains(t, Interval.Lopen(0, 4)) & Contains(d, Interval.Lopen(3, oo)))) # no bound on d
|
| 575 |
+
assert P(Eq(X(3), 2)) == 81*exp(-9)/2
|
| 576 |
+
assert P(Eq(X(t), 2), Contains(t, Interval.Lopen(0, 5))) == 225*exp(-15)/2
|
| 577 |
+
|
| 578 |
+
# Check that probability works correctly by adding it to 1
|
| 579 |
+
res1 = P(X(t) <= 3, Contains(t, Interval.Lopen(0, 5)))
|
| 580 |
+
res2 = P(X(t) > 3, Contains(t, Interval.Lopen(0, 5)))
|
| 581 |
+
assert res1 == 691*exp(-15)
|
| 582 |
+
assert (res1 + res2).simplify() == 1
|
| 583 |
+
|
| 584 |
+
# Check Not and Or
|
| 585 |
+
assert P(Not(Eq(X(t), 2) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) & \
|
| 586 |
+
Contains(d, Interval.Lopen(7, 8))).simplify() == -18*exp(-6) + 234*exp(-9) + 1
|
| 587 |
+
assert P(Eq(X(t), 2) | Ne(X(t), 4), Contains(t, Interval.Ropen(2, 4))) == 1 - 36*exp(-6)
|
| 588 |
+
raises(ValueError, lambda: P(X(t) > 2, X(t) + X(d)))
|
| 589 |
+
assert E(X(t)) == 3*t # property of the distribution at a given timestamp
|
| 590 |
+
assert E(X(t)**2 + X(d)*2 + X(y)**3, Contains(t, Interval.Lopen(0, 1))
|
| 591 |
+
& Contains(d, Interval.Lopen(1, 2)) & Contains(y, Interval.Ropen(3, 4))) == 75
|
| 592 |
+
assert E(X(t)**2, Contains(t, Interval.Lopen(0, 1))) == 12
|
| 593 |
+
assert E(x*(X(t) + X(d))*(X(t)**2+X(d)**2), Contains(t, Interval.Lopen(0, 1))
|
| 594 |
+
& Contains(d, Interval.Ropen(1, 2))) == \
|
| 595 |
+
Expectation(x*(X(d) + X(t))*(X(d)**2 + X(t)**2), Contains(t, Interval.Lopen(0, 1))
|
| 596 |
+
& Contains(d, Interval.Ropen(1, 2)))
|
| 597 |
+
|
| 598 |
+
# Value Error because of infinite time bound
|
| 599 |
+
raises(ValueError, lambda: E(X(t)**3, Contains(t, Interval.Lopen(1, oo))))
|
| 600 |
+
|
| 601 |
+
# Equivalent to E(X(t)**2) - E(X(d)**2) == E(X(1)**2) - E(X(1)**2) == 0
|
| 602 |
+
assert E((X(t) + X(d))*(X(t) - X(d)), Contains(t, Interval.Lopen(0, 1))
|
| 603 |
+
& Contains(d, Interval.Lopen(1, 2))) == 0
|
| 604 |
+
assert E(X(2) + x*E(X(5))) == 15*x + 6
|
| 605 |
+
assert E(x*X(1) + y) == 3*x + y
|
| 606 |
+
assert P(Eq(X(1), 2) & Eq(X(t), 3), Contains(t, Interval.Lopen(1, 2))) == 81*exp(-6)/4
|
| 607 |
+
Y = PoissonProcess("Y", 6)
|
| 608 |
+
Z = X + Y
|
| 609 |
+
assert Z.lamda == X.lamda + Y.lamda == 9
|
| 610 |
+
raises(ValueError, lambda: X + 5) # should be added be only PoissonProcess instance
|
| 611 |
+
N, M = Z.split(4, 5)
|
| 612 |
+
assert N.lamda == 4
|
| 613 |
+
assert M.lamda == 5
|
| 614 |
+
raises(ValueError, lambda: Z.split(3, 2)) # 2+3 != 9
|
| 615 |
+
|
| 616 |
+
raises(ValueError, lambda :P(Eq(X(t), 0), Contains(t, Interval.Lopen(1, 3)) & Eq(X(1), 0)))
|
| 617 |
+
# check if it handles queries with two random variables in one args
|
| 618 |
+
res1 = P(Eq(N(3), N(5)))
|
| 619 |
+
assert res1 == P(Eq(N(t), 0), Contains(t, Interval(3, 5)))
|
| 620 |
+
res2 = P(N(3) > N(1))
|
| 621 |
+
assert res2 == P((N(t) > 0), Contains(t, Interval(1, 3)))
|
| 622 |
+
assert P(N(3) < N(1)) == 0 # condition is not possible
|
| 623 |
+
res3 = P(N(3) <= N(1)) # holds only for Eq(N(3), N(1))
|
| 624 |
+
assert res3 == P(Eq(N(t), 0), Contains(t, Interval(1, 3)))
|
| 625 |
+
|
| 626 |
+
# tests from https://www.probabilitycourse.com/chapter11/11_1_2_basic_concepts_of_the_poisson_process.php
|
| 627 |
+
X = PoissonProcess('X', 10) # 11.1
|
| 628 |
+
assert P(Eq(X(S(1)/3), 3) & Eq(X(1), 10)) == exp(-10)*Rational(8000000000, 11160261)
|
| 629 |
+
assert P(Eq(X(1), 1), Eq(X(S(1)/3), 3)) == 0
|
| 630 |
+
assert P(Eq(X(1), 10), Eq(X(S(1)/3), 3)) == P(Eq(X(S(2)/3), 7))
|
| 631 |
+
|
| 632 |
+
X = PoissonProcess('X', 2) # 11.2
|
| 633 |
+
assert P(X(S(1)/2) < 1) == exp(-1)
|
| 634 |
+
assert P(X(3) < 1, Eq(X(1), 0)) == exp(-4)
|
| 635 |
+
assert P(Eq(X(4), 3), Eq(X(2), 3)) == exp(-4)
|
| 636 |
+
|
| 637 |
+
X = PoissonProcess('X', 3)
|
| 638 |
+
assert P(Eq(X(2), 5) & Eq(X(1), 2)) == Rational(81, 4)*exp(-6)
|
| 639 |
+
|
| 640 |
+
# check few properties
|
| 641 |
+
assert P(X(2) <= 3, X(1)>=1) == 3*P(Eq(X(1), 0)) + 2*P(Eq(X(1), 1)) + P(Eq(X(1), 2))
|
| 642 |
+
assert P(X(2) <= 3, X(1) > 1) == 2*P(Eq(X(1), 0)) + 1*P(Eq(X(1), 1))
|
| 643 |
+
assert P(Eq(X(2), 5) & Eq(X(1), 2)) == P(Eq(X(1), 3))*P(Eq(X(1), 2))
|
| 644 |
+
assert P(Eq(X(3), 4), Eq(X(1), 3)) == P(Eq(X(2), 1))
|
| 645 |
+
|
| 646 |
+
#test issue 20078
|
| 647 |
+
assert (2*X(t) + 3*X(t)).simplify() == 5*X(t)
|
| 648 |
+
assert (2*X(t) - 3*X(t)).simplify() == -X(t)
|
| 649 |
+
assert (2*(0.25*X(t))).simplify() == 0.5*X(t)
|
| 650 |
+
assert (2*X(t) * 0.25*X(t)).simplify() == 0.5*X(t)**2
|
| 651 |
+
assert (X(t)**2 + X(t)**3).simplify() == (X(t) + 1)*X(t)**2
|
| 652 |
+
|
| 653 |
+
def test_WienerProcess():
|
| 654 |
+
X = WienerProcess("X")
|
| 655 |
+
assert X.state_space == S.Reals
|
| 656 |
+
assert X.index_set == Interval(0, oo)
|
| 657 |
+
|
| 658 |
+
t, d, x, y = symbols('t d x y', positive=True)
|
| 659 |
+
assert isinstance(X(t), RandomIndexedSymbol)
|
| 660 |
+
assert X.distribution(t) == NormalDistribution(0, sqrt(t))
|
| 661 |
+
with warns_deprecated_sympy():
|
| 662 |
+
X.distribution(X(t))
|
| 663 |
+
raises(ValueError, lambda: PoissonProcess("X", -1))
|
| 664 |
+
raises(NotImplementedError, lambda: X[t])
|
| 665 |
+
raises(IndexError, lambda: X(-2))
|
| 666 |
+
|
| 667 |
+
assert X.joint_distribution(X(2), X(3)) == JointDistributionHandmade(
|
| 668 |
+
Lambda((X(2), X(3)), sqrt(6)*exp(-X(2)**2/4)*exp(-X(3)**2/6)/(12*pi)))
|
| 669 |
+
assert X.joint_distribution(4, 6) == JointDistributionHandmade(
|
| 670 |
+
Lambda((X(4), X(6)), sqrt(6)*exp(-X(4)**2/8)*exp(-X(6)**2/12)/(24*pi)))
|
| 671 |
+
|
| 672 |
+
assert P(X(t) < 3).simplify() == erf(3*sqrt(2)/(2*sqrt(t)))/2 + S(1)/2
|
| 673 |
+
assert P(X(t) > 2, Contains(t, Interval.Lopen(3, 7))).simplify() == S(1)/2 -\
|
| 674 |
+
erf(sqrt(2)/2)/2
|
| 675 |
+
|
| 676 |
+
# Equivalent to P(X(1)>1)**4
|
| 677 |
+
assert P((X(t) > 4) & (X(d) > 3) & (X(x) > 2) & (X(y) > 1),
|
| 678 |
+
Contains(t, Interval.Lopen(0, 1)) & Contains(d, Interval.Lopen(1, 2))
|
| 679 |
+
& Contains(x, Interval.Lopen(2, 3)) & Contains(y, Interval.Lopen(3, 4))).simplify() ==\
|
| 680 |
+
(1 - erf(sqrt(2)/2))*(1 - erf(sqrt(2)))*(1 - erf(3*sqrt(2)/2))*(1 - erf(2*sqrt(2)))/16
|
| 681 |
+
|
| 682 |
+
# Contains an overlapping interval so, return Probability
|
| 683 |
+
assert P((X(t)< 2) & (X(d)> 3), Contains(t, Interval.Lopen(0, 2))
|
| 684 |
+
& Contains(d, Interval.Ropen(2, 4))) == Probability((X(d) > 3) & (X(t) < 2),
|
| 685 |
+
Contains(d, Interval.Ropen(2, 4)) & Contains(t, Interval.Lopen(0, 2)))
|
| 686 |
+
|
| 687 |
+
assert str(P(Not((X(t) < 5) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) &
|
| 688 |
+
Contains(d, Interval.Lopen(7, 8))).simplify()) == \
|
| 689 |
+
'-(1 - erf(3*sqrt(2)/2))*(2 - erfc(5/2))/4 + 1'
|
| 690 |
+
# Distribution has mean 0 at each timestamp
|
| 691 |
+
assert E(X(t)) == 0
|
| 692 |
+
assert E(x*(X(t) + X(d))*(X(t)**2+X(d)**2), Contains(t, Interval.Lopen(0, 1))
|
| 693 |
+
& Contains(d, Interval.Ropen(1, 2))) == Expectation(x*(X(d) + X(t))*(X(d)**2 + X(t)**2),
|
| 694 |
+
Contains(d, Interval.Ropen(1, 2)) & Contains(t, Interval.Lopen(0, 1)))
|
| 695 |
+
assert E(X(t) + x*E(X(3))) == 0
|
| 696 |
+
|
| 697 |
+
#test issue 20078
|
| 698 |
+
assert (2*X(t) + 3*X(t)).simplify() == 5*X(t)
|
| 699 |
+
assert (2*X(t) - 3*X(t)).simplify() == -X(t)
|
| 700 |
+
assert (2*(0.25*X(t))).simplify() == 0.5*X(t)
|
| 701 |
+
assert (2*X(t) * 0.25*X(t)).simplify() == 0.5*X(t)**2
|
| 702 |
+
assert (X(t)**2 + X(t)**3).simplify() == (X(t) + 1)*X(t)**2
|
| 703 |
+
|
| 704 |
+
|
| 705 |
+
def test_GammaProcess_symbolic():
|
| 706 |
+
t, d, x, y, g, l = symbols('t d x y g l', positive=True)
|
| 707 |
+
X = GammaProcess("X", l, g)
|
| 708 |
+
|
| 709 |
+
raises(NotImplementedError, lambda: X[t])
|
| 710 |
+
raises(IndexError, lambda: X(-1))
|
| 711 |
+
assert isinstance(X(t), RandomIndexedSymbol)
|
| 712 |
+
assert X.state_space == Interval(0, oo)
|
| 713 |
+
assert X.distribution(t) == GammaDistribution(g*t, 1/l)
|
| 714 |
+
with warns_deprecated_sympy():
|
| 715 |
+
X.distribution(X(t))
|
| 716 |
+
assert X.joint_distribution(5, X(3)) == JointDistributionHandmade(Lambda(
|
| 717 |
+
(X(5), X(3)), l**(8*g)*exp(-l*X(3))*exp(-l*X(5))*X(3)**(3*g - 1)*X(5)**(5*g
|
| 718 |
+
- 1)/(gamma(3*g)*gamma(5*g))))
|
| 719 |
+
# property of the gamma process at any given timestamp
|
| 720 |
+
assert E(X(t)) == g*t/l
|
| 721 |
+
assert variance(X(t)).simplify() == g*t/l**2
|
| 722 |
+
|
| 723 |
+
# Equivalent to E(2*X(1)) + E(X(1)**2) + E(X(1)**3), where E(X(1)) == g/l
|
| 724 |
+
assert E(X(t)**2 + X(d)*2 + X(y)**3, Contains(t, Interval.Lopen(0, 1))
|
| 725 |
+
& Contains(d, Interval.Lopen(1, 2)) & Contains(y, Interval.Ropen(3, 4))) == \
|
| 726 |
+
2*g/l + (g**2 + g)/l**2 + (g**3 + 3*g**2 + 2*g)/l**3
|
| 727 |
+
|
| 728 |
+
assert P(X(t) > 3, Contains(t, Interval.Lopen(3, 4))).simplify() == \
|
| 729 |
+
1 - lowergamma(g, 3*l)/gamma(g) # equivalent to P(X(1)>3)
|
| 730 |
+
|
| 731 |
+
|
| 732 |
+
#test issue 20078
|
| 733 |
+
assert (2*X(t) + 3*X(t)).simplify() == 5*X(t)
|
| 734 |
+
assert (2*X(t) - 3*X(t)).simplify() == -X(t)
|
| 735 |
+
assert (2*(0.25*X(t))).simplify() == 0.5*X(t)
|
| 736 |
+
assert (2*X(t) * 0.25*X(t)).simplify() == 0.5*X(t)**2
|
| 737 |
+
assert (X(t)**2 + X(t)**3).simplify() == (X(t) + 1)*X(t)**2
|
| 738 |
+
def test_GammaProcess_numeric():
|
| 739 |
+
t, d, x, y = symbols('t d x y', positive=True)
|
| 740 |
+
X = GammaProcess("X", 1, 2)
|
| 741 |
+
assert X.state_space == Interval(0, oo)
|
| 742 |
+
assert X.index_set == Interval(0, oo)
|
| 743 |
+
assert X.lamda == 1
|
| 744 |
+
assert X.gamma == 2
|
| 745 |
+
|
| 746 |
+
raises(ValueError, lambda: GammaProcess("X", -1, 2))
|
| 747 |
+
raises(ValueError, lambda: GammaProcess("X", 0, -2))
|
| 748 |
+
raises(ValueError, lambda: GammaProcess("X", -1, -2))
|
| 749 |
+
|
| 750 |
+
# all are independent because of non-overlapping intervals
|
| 751 |
+
assert P((X(t) > 4) & (X(d) > 3) & (X(x) > 2) & (X(y) > 1), Contains(t,
|
| 752 |
+
Interval.Lopen(0, 1)) & Contains(d, Interval.Lopen(1, 2)) & Contains(x,
|
| 753 |
+
Interval.Lopen(2, 3)) & Contains(y, Interval.Lopen(3, 4))).simplify() == \
|
| 754 |
+
120*exp(-10)
|
| 755 |
+
|
| 756 |
+
# Check working with Not and Or
|
| 757 |
+
assert P(Not((X(t) < 5) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) &
|
| 758 |
+
Contains(d, Interval.Lopen(7, 8))).simplify() == -4*exp(-3) + 472*exp(-8)/3 + 1
|
| 759 |
+
assert P((X(t) > 2) | (X(t) < 4), Contains(t, Interval.Ropen(1, 4))).simplify() == \
|
| 760 |
+
-643*exp(-4)/15 + 109*exp(-2)/15 + 1
|
| 761 |
+
|
| 762 |
+
assert E(X(t)) == 2*t # E(X(t)) == gamma*t/l
|
| 763 |
+
assert E(X(2) + x*E(X(5))) == 10*x + 4
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_symbolic_multivariate.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.stats import Expectation, Normal, Variance, Covariance
|
| 2 |
+
from sympy.testing.pytest import raises
|
| 3 |
+
from sympy.core.symbol import symbols
|
| 4 |
+
from sympy.matrices.exceptions import ShapeError
|
| 5 |
+
from sympy.matrices.dense import Matrix
|
| 6 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 7 |
+
from sympy.matrices.expressions.special import ZeroMatrix
|
| 8 |
+
from sympy.stats.rv import RandomMatrixSymbol
|
| 9 |
+
from sympy.stats.symbolic_multivariate_probability import (ExpectationMatrix,
|
| 10 |
+
VarianceMatrix, CrossCovarianceMatrix)
|
| 11 |
+
|
| 12 |
+
j, k = symbols("j,k")
|
| 13 |
+
|
| 14 |
+
A = MatrixSymbol("A", k, k)
|
| 15 |
+
B = MatrixSymbol("B", k, k)
|
| 16 |
+
C = MatrixSymbol("C", k, k)
|
| 17 |
+
D = MatrixSymbol("D", k, k)
|
| 18 |
+
|
| 19 |
+
a = MatrixSymbol("a", k, 1)
|
| 20 |
+
b = MatrixSymbol("b", k, 1)
|
| 21 |
+
|
| 22 |
+
A2 = MatrixSymbol("A2", 2, 2)
|
| 23 |
+
B2 = MatrixSymbol("B2", 2, 2)
|
| 24 |
+
|
| 25 |
+
X = RandomMatrixSymbol("X", k, 1)
|
| 26 |
+
Y = RandomMatrixSymbol("Y", k, 1)
|
| 27 |
+
Z = RandomMatrixSymbol("Z", k, 1)
|
| 28 |
+
W = RandomMatrixSymbol("W", k, 1)
|
| 29 |
+
|
| 30 |
+
R = RandomMatrixSymbol("R", k, k)
|
| 31 |
+
|
| 32 |
+
X2 = RandomMatrixSymbol("X2", 2, 1)
|
| 33 |
+
|
| 34 |
+
normal = Normal("normal", 0, 1)
|
| 35 |
+
|
| 36 |
+
m1 = Matrix([
|
| 37 |
+
[1, j*Normal("normal2", 2, 1)],
|
| 38 |
+
[normal, 0]
|
| 39 |
+
])
|
| 40 |
+
|
| 41 |
+
def test_multivariate_expectation():
|
| 42 |
+
expr = Expectation(a)
|
| 43 |
+
assert expr == Expectation(a) == ExpectationMatrix(a)
|
| 44 |
+
assert expr.expand() == a
|
| 45 |
+
|
| 46 |
+
expr = Expectation(X)
|
| 47 |
+
assert expr == Expectation(X) == ExpectationMatrix(X)
|
| 48 |
+
assert expr.shape == (k, 1)
|
| 49 |
+
assert expr.rows == k
|
| 50 |
+
assert expr.cols == 1
|
| 51 |
+
assert isinstance(expr, ExpectationMatrix)
|
| 52 |
+
|
| 53 |
+
expr = Expectation(A*X + b)
|
| 54 |
+
assert expr == ExpectationMatrix(A*X + b)
|
| 55 |
+
assert expr.expand() == A*ExpectationMatrix(X) + b
|
| 56 |
+
assert isinstance(expr, ExpectationMatrix)
|
| 57 |
+
assert expr.shape == (k, 1)
|
| 58 |
+
|
| 59 |
+
expr = Expectation(m1*X2)
|
| 60 |
+
assert expr.expand() == expr
|
| 61 |
+
|
| 62 |
+
expr = Expectation(A2*m1*B2*X2)
|
| 63 |
+
assert expr.args[0].args == (A2, m1, B2, X2)
|
| 64 |
+
assert expr.expand() == A2*ExpectationMatrix(m1*B2*X2)
|
| 65 |
+
|
| 66 |
+
expr = Expectation((X + Y)*(X - Y).T)
|
| 67 |
+
assert expr.expand() == ExpectationMatrix(X*X.T) - ExpectationMatrix(X*Y.T) +\
|
| 68 |
+
ExpectationMatrix(Y*X.T) - ExpectationMatrix(Y*Y.T)
|
| 69 |
+
|
| 70 |
+
expr = Expectation(A*X + B*Y)
|
| 71 |
+
assert expr.expand() == A*ExpectationMatrix(X) + B*ExpectationMatrix(Y)
|
| 72 |
+
|
| 73 |
+
assert Expectation(m1).doit() == Matrix([[1, 2*j], [0, 0]])
|
| 74 |
+
|
| 75 |
+
x1 = Matrix([
|
| 76 |
+
[Normal('N11', 11, 1), Normal('N12', 12, 1)],
|
| 77 |
+
[Normal('N21', 21, 1), Normal('N22', 22, 1)]
|
| 78 |
+
])
|
| 79 |
+
x2 = Matrix([
|
| 80 |
+
[Normal('M11', 1, 1), Normal('M12', 2, 1)],
|
| 81 |
+
[Normal('M21', 3, 1), Normal('M22', 4, 1)]
|
| 82 |
+
])
|
| 83 |
+
|
| 84 |
+
assert Expectation(Expectation(x1 + x2)).doit(deep=False) == ExpectationMatrix(x1 + x2)
|
| 85 |
+
assert Expectation(Expectation(x1 + x2)).doit() == Matrix([[12, 14], [24, 26]])
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def test_multivariate_variance():
|
| 89 |
+
raises(ShapeError, lambda: Variance(A))
|
| 90 |
+
|
| 91 |
+
expr = Variance(a)
|
| 92 |
+
assert expr == Variance(a) == VarianceMatrix(a)
|
| 93 |
+
assert expr.expand() == ZeroMatrix(k, k)
|
| 94 |
+
expr = Variance(a.T)
|
| 95 |
+
assert expr == Variance(a.T) == VarianceMatrix(a.T)
|
| 96 |
+
assert expr.expand() == ZeroMatrix(k, k)
|
| 97 |
+
|
| 98 |
+
expr = Variance(X)
|
| 99 |
+
assert expr == Variance(X) == VarianceMatrix(X)
|
| 100 |
+
assert expr.shape == (k, k)
|
| 101 |
+
assert expr.rows == k
|
| 102 |
+
assert expr.cols == k
|
| 103 |
+
assert isinstance(expr, VarianceMatrix)
|
| 104 |
+
|
| 105 |
+
expr = Variance(A*X)
|
| 106 |
+
assert expr == VarianceMatrix(A*X)
|
| 107 |
+
assert expr.expand() == A*VarianceMatrix(X)*A.T
|
| 108 |
+
assert isinstance(expr, VarianceMatrix)
|
| 109 |
+
assert expr.shape == (k, k)
|
| 110 |
+
|
| 111 |
+
expr = Variance(A*B*X)
|
| 112 |
+
assert expr.expand() == A*B*VarianceMatrix(X)*B.T*A.T
|
| 113 |
+
|
| 114 |
+
expr = Variance(m1*X2)
|
| 115 |
+
assert expr.expand() == expr
|
| 116 |
+
|
| 117 |
+
expr = Variance(A2*m1*B2*X2)
|
| 118 |
+
assert expr.args[0].args == (A2, m1, B2, X2)
|
| 119 |
+
assert expr.expand() == expr
|
| 120 |
+
|
| 121 |
+
expr = Variance(A*X + B*Y)
|
| 122 |
+
assert expr.expand() == 2*A*CrossCovarianceMatrix(X, Y)*B.T +\
|
| 123 |
+
A*VarianceMatrix(X)*A.T + B*VarianceMatrix(Y)*B.T
|
| 124 |
+
|
| 125 |
+
def test_multivariate_crosscovariance():
|
| 126 |
+
raises(ShapeError, lambda: Covariance(X, Y.T))
|
| 127 |
+
raises(ShapeError, lambda: Covariance(X, A))
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
expr = Covariance(a.T, b.T)
|
| 131 |
+
assert expr.shape == (1, 1)
|
| 132 |
+
assert expr.expand() == ZeroMatrix(1, 1)
|
| 133 |
+
|
| 134 |
+
expr = Covariance(a, b)
|
| 135 |
+
assert expr == Covariance(a, b) == CrossCovarianceMatrix(a, b)
|
| 136 |
+
assert expr.expand() == ZeroMatrix(k, k)
|
| 137 |
+
assert expr.shape == (k, k)
|
| 138 |
+
assert expr.rows == k
|
| 139 |
+
assert expr.cols == k
|
| 140 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 141 |
+
|
| 142 |
+
expr = Covariance(A*X + a, b)
|
| 143 |
+
assert expr.expand() == ZeroMatrix(k, k)
|
| 144 |
+
|
| 145 |
+
expr = Covariance(X, Y)
|
| 146 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 147 |
+
assert expr.expand() == expr
|
| 148 |
+
|
| 149 |
+
expr = Covariance(X, X)
|
| 150 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 151 |
+
assert expr.expand() == VarianceMatrix(X)
|
| 152 |
+
|
| 153 |
+
expr = Covariance(X + Y, Z)
|
| 154 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 155 |
+
assert expr.expand() == CrossCovarianceMatrix(X, Z) + CrossCovarianceMatrix(Y, Z)
|
| 156 |
+
|
| 157 |
+
expr = Covariance(A*X, Y)
|
| 158 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 159 |
+
assert expr.expand() == A*CrossCovarianceMatrix(X, Y)
|
| 160 |
+
|
| 161 |
+
expr = Covariance(X, B*Y)
|
| 162 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 163 |
+
assert expr.expand() == CrossCovarianceMatrix(X, Y)*B.T
|
| 164 |
+
|
| 165 |
+
expr = Covariance(A*X + a, B.T*Y + b)
|
| 166 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 167 |
+
assert expr.expand() == A*CrossCovarianceMatrix(X, Y)*B
|
| 168 |
+
|
| 169 |
+
expr = Covariance(A*X + B*Y + a, C.T*Z + D.T*W + b)
|
| 170 |
+
assert isinstance(expr, CrossCovarianceMatrix)
|
| 171 |
+
assert expr.expand() == A*CrossCovarianceMatrix(X, W)*D + A*CrossCovarianceMatrix(X, Z)*C \
|
| 172 |
+
+ B*CrossCovarianceMatrix(Y, W)*D + B*CrossCovarianceMatrix(Y, Z)*C
|
hug/lib/python3.12/site-packages/sympy/stats/tests/test_symbolic_probability.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.concrete.summations import Sum
|
| 2 |
+
from sympy.core.mul import Mul
|
| 3 |
+
from sympy.core.numbers import (oo, pi)
|
| 4 |
+
from sympy.core.relational import Eq
|
| 5 |
+
from sympy.core.symbol import (Dummy, symbols)
|
| 6 |
+
from sympy.functions.elementary.exponential import exp
|
| 7 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 8 |
+
from sympy.functions.elementary.trigonometric import sin
|
| 9 |
+
from sympy.integrals.integrals import Integral
|
| 10 |
+
from sympy.core.expr import unchanged
|
| 11 |
+
from sympy.stats import (Normal, Poisson, variance, Covariance, Variance,
|
| 12 |
+
Probability, Expectation, Moment, CentralMoment)
|
| 13 |
+
from sympy.stats.rv import probability, expectation
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_literal_probability():
|
| 17 |
+
X = Normal('X', 2, 3)
|
| 18 |
+
Y = Normal('Y', 3, 4)
|
| 19 |
+
Z = Poisson('Z', 4)
|
| 20 |
+
W = Poisson('W', 3)
|
| 21 |
+
x = symbols('x', real=True)
|
| 22 |
+
y, w, z = symbols('y, w, z')
|
| 23 |
+
|
| 24 |
+
assert Probability(X > 0).evaluate_integral() == probability(X > 0)
|
| 25 |
+
assert Probability(X > x).evaluate_integral() == probability(X > x)
|
| 26 |
+
assert Probability(X > 0).rewrite(Integral).doit() == probability(X > 0)
|
| 27 |
+
assert Probability(X > x).rewrite(Integral).doit() == probability(X > x)
|
| 28 |
+
|
| 29 |
+
assert Expectation(X).evaluate_integral() == expectation(X)
|
| 30 |
+
assert Expectation(X).rewrite(Integral).doit() == expectation(X)
|
| 31 |
+
assert Expectation(X**2).evaluate_integral() == expectation(X**2)
|
| 32 |
+
assert Expectation(x*X).args == (x*X,)
|
| 33 |
+
assert Expectation(x*X).expand() == x*Expectation(X)
|
| 34 |
+
assert Expectation(2*X + 3*Y + z*X*Y).expand() == 2*Expectation(X) + 3*Expectation(Y) + z*Expectation(X*Y)
|
| 35 |
+
assert Expectation(2*X + 3*Y + z*X*Y).args == (2*X + 3*Y + z*X*Y,)
|
| 36 |
+
assert Expectation(sin(X)) == Expectation(sin(X)).expand()
|
| 37 |
+
assert Expectation(2*x*sin(X)*Y + y*X**2 + z*X*Y).expand() == 2*x*Expectation(sin(X)*Y) \
|
| 38 |
+
+ y*Expectation(X**2) + z*Expectation(X*Y)
|
| 39 |
+
assert Expectation(X + Y).expand() == Expectation(X) + Expectation(Y)
|
| 40 |
+
assert Expectation((X + Y)*(X - Y)).expand() == Expectation(X**2) - Expectation(Y**2)
|
| 41 |
+
assert Expectation((X + Y)*(X - Y)).expand().doit() == -12
|
| 42 |
+
assert Expectation(X + Y, evaluate=True).doit() == 5
|
| 43 |
+
assert Expectation(X + Expectation(Y)).doit() == 5
|
| 44 |
+
assert Expectation(X + Expectation(Y)).doit(deep=False) == 2 + Expectation(Expectation(Y))
|
| 45 |
+
assert Expectation(X + Expectation(Y + Expectation(2*X))).doit(deep=False) == 2 \
|
| 46 |
+
+ Expectation(Expectation(Y + Expectation(2*X)))
|
| 47 |
+
assert Expectation(X + Expectation(Y + Expectation(2*X))).doit() == 9
|
| 48 |
+
assert Expectation(Expectation(2*X)).doit() == 4
|
| 49 |
+
assert Expectation(Expectation(2*X)).doit(deep=False) == Expectation(2*X)
|
| 50 |
+
assert Expectation(4*Expectation(2*X)).doit(deep=False) == 4*Expectation(2*X)
|
| 51 |
+
assert Expectation((X + Y)**3).expand() == 3*Expectation(X*Y**2) +\
|
| 52 |
+
3*Expectation(X**2*Y) + Expectation(X**3) + Expectation(Y**3)
|
| 53 |
+
assert Expectation((X - Y)**3).expand() == 3*Expectation(X*Y**2) -\
|
| 54 |
+
3*Expectation(X**2*Y) + Expectation(X**3) - Expectation(Y**3)
|
| 55 |
+
assert Expectation((X - Y)**2).expand() == -2*Expectation(X*Y) +\
|
| 56 |
+
Expectation(X**2) + Expectation(Y**2)
|
| 57 |
+
|
| 58 |
+
assert Variance(w).args == (w,)
|
| 59 |
+
assert Variance(w).expand() == 0
|
| 60 |
+
assert Variance(X).evaluate_integral() == Variance(X).rewrite(Integral).doit() == variance(X)
|
| 61 |
+
assert Variance(X + z).args == (X + z,)
|
| 62 |
+
assert Variance(X + z).expand() == Variance(X)
|
| 63 |
+
assert Variance(X*Y).args == (Mul(X, Y),)
|
| 64 |
+
assert type(Variance(X*Y)) == Variance
|
| 65 |
+
assert Variance(z*X).expand() == z**2*Variance(X)
|
| 66 |
+
assert Variance(X + Y).expand() == Variance(X) + Variance(Y) + 2*Covariance(X, Y)
|
| 67 |
+
assert Variance(X + Y + Z + W).expand() == (Variance(X) + Variance(Y) + Variance(Z) + Variance(W) +
|
| 68 |
+
2 * Covariance(X, Y) + 2 * Covariance(X, Z) + 2 * Covariance(X, W) +
|
| 69 |
+
2 * Covariance(Y, Z) + 2 * Covariance(Y, W) + 2 * Covariance(W, Z))
|
| 70 |
+
assert Variance(X**2).evaluate_integral() == variance(X**2)
|
| 71 |
+
assert unchanged(Variance, X**2)
|
| 72 |
+
assert Variance(x*X**2).expand() == x**2*Variance(X**2)
|
| 73 |
+
assert Variance(sin(X)).args == (sin(X),)
|
| 74 |
+
assert Variance(sin(X)).expand() == Variance(sin(X))
|
| 75 |
+
assert Variance(x*sin(X)).expand() == x**2*Variance(sin(X))
|
| 76 |
+
|
| 77 |
+
assert Covariance(w, z).args == (w, z)
|
| 78 |
+
assert Covariance(w, z).expand() == 0
|
| 79 |
+
assert Covariance(X, w).expand() == 0
|
| 80 |
+
assert Covariance(w, X).expand() == 0
|
| 81 |
+
assert Covariance(X, Y).args == (X, Y)
|
| 82 |
+
assert type(Covariance(X, Y)) == Covariance
|
| 83 |
+
assert Covariance(z*X + 3, Y).expand() == z*Covariance(X, Y)
|
| 84 |
+
assert Covariance(X, X).args == (X, X)
|
| 85 |
+
assert Covariance(X, X).expand() == Variance(X)
|
| 86 |
+
assert Covariance(z*X + 3, w*Y + 4).expand() == w*z*Covariance(X,Y)
|
| 87 |
+
assert Covariance(X, Y) == Covariance(Y, X)
|
| 88 |
+
assert Covariance(X + Y, Z + W).expand() == Covariance(W, X) + Covariance(W, Y) + Covariance(X, Z) + Covariance(Y, Z)
|
| 89 |
+
assert Covariance(x*X + y*Y, z*Z + w*W).expand() == (x*w*Covariance(W, X) + w*y*Covariance(W, Y) +
|
| 90 |
+
x*z*Covariance(X, Z) + y*z*Covariance(Y, Z))
|
| 91 |
+
assert Covariance(x*X**2 + y*sin(Y), z*Y*Z**2 + w*W).expand() == (w*x*Covariance(W, X**2) + w*y*Covariance(sin(Y), W) +
|
| 92 |
+
x*z*Covariance(Y*Z**2, X**2) + y*z*Covariance(Y*Z**2, sin(Y)))
|
| 93 |
+
assert Covariance(X, X**2).expand() == Covariance(X, X**2)
|
| 94 |
+
assert Covariance(X, sin(X)).expand() == Covariance(sin(X), X)
|
| 95 |
+
assert Covariance(X**2, sin(X)*Y).expand() == Covariance(sin(X)*Y, X**2)
|
| 96 |
+
assert Covariance(w, X).evaluate_integral() == 0
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def test_probability_rewrite():
|
| 100 |
+
X = Normal('X', 2, 3)
|
| 101 |
+
Y = Normal('Y', 3, 4)
|
| 102 |
+
Z = Poisson('Z', 4)
|
| 103 |
+
W = Poisson('W', 3)
|
| 104 |
+
x, y, w, z = symbols('x, y, w, z')
|
| 105 |
+
|
| 106 |
+
assert Variance(w).rewrite(Expectation) == 0
|
| 107 |
+
assert Variance(X).rewrite(Expectation) == Expectation(X ** 2) - Expectation(X) ** 2
|
| 108 |
+
assert Variance(X, condition=Y).rewrite(Expectation) == Expectation(X ** 2, Y) - Expectation(X, Y) ** 2
|
| 109 |
+
assert Variance(X, Y) != Expectation(X**2) - Expectation(X)**2
|
| 110 |
+
assert Variance(X + z).rewrite(Expectation) == Expectation((X + z) ** 2) - Expectation(X + z) ** 2
|
| 111 |
+
assert Variance(X * Y).rewrite(Expectation) == Expectation(X ** 2 * Y ** 2) - Expectation(X * Y) ** 2
|
| 112 |
+
|
| 113 |
+
assert Covariance(w, X).rewrite(Expectation) == -w*Expectation(X) + Expectation(w*X)
|
| 114 |
+
assert Covariance(X, Y).rewrite(Expectation) == Expectation(X*Y) - Expectation(X)*Expectation(Y)
|
| 115 |
+
assert Covariance(X, Y, condition=W).rewrite(Expectation) == Expectation(X * Y, W) - Expectation(X, W) * Expectation(Y, W)
|
| 116 |
+
|
| 117 |
+
w, x, z = symbols("W, x, z")
|
| 118 |
+
px = Probability(Eq(X, x))
|
| 119 |
+
pz = Probability(Eq(Z, z))
|
| 120 |
+
|
| 121 |
+
assert Expectation(X).rewrite(Probability) == Integral(x*px, (x, -oo, oo))
|
| 122 |
+
assert Expectation(Z).rewrite(Probability) == Sum(z*pz, (z, 0, oo))
|
| 123 |
+
assert Variance(X).rewrite(Probability) == Integral(x**2*px, (x, -oo, oo)) - Integral(x*px, (x, -oo, oo))**2
|
| 124 |
+
assert Variance(Z).rewrite(Probability) == Sum(z**2*pz, (z, 0, oo)) - Sum(z*pz, (z, 0, oo))**2
|
| 125 |
+
assert Covariance(w, X).rewrite(Probability) == \
|
| 126 |
+
-w*Integral(x*Probability(Eq(X, x)), (x, -oo, oo)) + Integral(w*x*Probability(Eq(X, x)), (x, -oo, oo))
|
| 127 |
+
|
| 128 |
+
# To test rewrite as sum function
|
| 129 |
+
assert Variance(X).rewrite(Sum) == Variance(X).rewrite(Integral)
|
| 130 |
+
assert Expectation(X).rewrite(Sum) == Expectation(X).rewrite(Integral)
|
| 131 |
+
|
| 132 |
+
assert Covariance(w, X).rewrite(Sum) == 0
|
| 133 |
+
|
| 134 |
+
assert Covariance(w, X).rewrite(Integral) == 0
|
| 135 |
+
|
| 136 |
+
assert Variance(X, condition=Y).rewrite(Probability) == Integral(x**2*Probability(Eq(X, x), Y), (x, -oo, oo)) - \
|
| 137 |
+
Integral(x*Probability(Eq(X, x), Y), (x, -oo, oo))**2
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def test_symbolic_Moment():
|
| 141 |
+
mu = symbols('mu', real=True)
|
| 142 |
+
sigma = symbols('sigma', positive=True)
|
| 143 |
+
x = symbols('x')
|
| 144 |
+
X = Normal('X', mu, sigma)
|
| 145 |
+
M = Moment(X, 4, 2)
|
| 146 |
+
assert M.rewrite(Expectation) == Expectation((X - 2)**4)
|
| 147 |
+
assert M.rewrite(Probability) == Integral((x - 2)**4*Probability(Eq(X, x)),
|
| 148 |
+
(x, -oo, oo))
|
| 149 |
+
k = Dummy('k')
|
| 150 |
+
expri = Integral(sqrt(2)*(k - 2)**4*exp(-(k - \
|
| 151 |
+
mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (k, -oo, oo))
|
| 152 |
+
assert M.rewrite(Integral).dummy_eq(expri)
|
| 153 |
+
assert M.doit() == (mu**4 - 8*mu**3 + 6*mu**2*sigma**2 + \
|
| 154 |
+
24*mu**2 - 24*mu*sigma**2 - 32*mu + 3*sigma**4 + 24*sigma**2 + 16)
|
| 155 |
+
M = Moment(2, 5)
|
| 156 |
+
assert M.doit() == 2**5
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_symbolic_CentralMoment():
|
| 160 |
+
mu = symbols('mu', real=True)
|
| 161 |
+
sigma = symbols('sigma', positive=True)
|
| 162 |
+
x = symbols('x')
|
| 163 |
+
X = Normal('X', mu, sigma)
|
| 164 |
+
CM = CentralMoment(X, 6)
|
| 165 |
+
assert CM.rewrite(Expectation) == Expectation((X - Expectation(X))**6)
|
| 166 |
+
assert CM.rewrite(Probability) == Integral((x - Integral(x*Probability(True),
|
| 167 |
+
(x, -oo, oo)))**6*Probability(Eq(X, x)), (x, -oo, oo))
|
| 168 |
+
k = Dummy('k')
|
| 169 |
+
expri = Integral(sqrt(2)*(k - Integral(sqrt(2)*k*exp(-(k - \
|
| 170 |
+
mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (k, -oo, oo)))**6*exp(-(k - \
|
| 171 |
+
mu)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), (k, -oo, oo))
|
| 172 |
+
assert CM.rewrite(Integral).dummy_eq(expri)
|
| 173 |
+
assert CM.doit().simplify() == 15*sigma**6
|
| 174 |
+
CM = Moment(5, 5)
|
| 175 |
+
assert CM.doit() == 5**5
|