dl1wjd2 commited on
Commit
cd47938
·
verified ·
1 Parent(s): ff67f73

Upload folder using huggingface_hub (part 20)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +35 -0
  2. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/INSTALLER +1 -0
  3. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/METADATA +319 -0
  4. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/RECORD +0 -0
  5. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/WHEEL +5 -0
  6. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/entry_points.txt +2 -0
  7. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/AUTHORS +1379 -0
  8. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/licenses/LICENSE +153 -0
  9. hug/lib/python3.12/site-packages/sympy-1.14.0.dist-info/top_level.txt +2 -0
  10. hug/lib/python3.12/site-packages/sympy/stats/sampling/sample_scipy.py +167 -0
  11. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__init__.py +0 -0
  12. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  13. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_continuous_rv.cpython-312.pyc +0 -0
  14. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_discrete_rv.cpython-312.pyc +0 -0
  15. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/__pycache__/test_sample_finite_rv.cpython-312.pyc +0 -0
  16. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_continuous_rv.py +181 -0
  17. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_discrete_rv.py +109 -0
  18. hug/lib/python3.12/site-packages/sympy/stats/sampling/tests/test_sample_finite_rv.py +94 -0
  19. hug/lib/python3.12/site-packages/sympy/stats/stochastic_process.py +66 -0
  20. hug/lib/python3.12/site-packages/sympy/stats/stochastic_process_types.py +2383 -0
  21. hug/lib/python3.12/site-packages/sympy/stats/symbolic_multivariate_probability.py +308 -0
  22. hug/lib/python3.12/site-packages/sympy/stats/symbolic_probability.py +698 -0
  23. hug/lib/python3.12/site-packages/sympy/stats/tests/__init__.py +0 -0
  24. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  25. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_compound_rv.cpython-312.pyc +0 -0
  26. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_continuous_rv.cpython-312.pyc +3 -0
  27. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_discrete_rv.cpython-312.pyc +0 -0
  28. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_error_prop.cpython-312.pyc +0 -0
  29. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_finite_rv.cpython-312.pyc +0 -0
  30. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_joint_rv.cpython-312.pyc +0 -0
  31. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_matrix_distributions.cpython-312.pyc +0 -0
  32. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_mix.cpython-312.pyc +0 -0
  33. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_random_matrix.cpython-312.pyc +0 -0
  34. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_rv.cpython-312.pyc +0 -0
  35. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_stochastic_process.cpython-312.pyc +0 -0
  36. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_multivariate.cpython-312.pyc +0 -0
  37. hug/lib/python3.12/site-packages/sympy/stats/tests/__pycache__/test_symbolic_probability.cpython-312.pyc +0 -0
  38. hug/lib/python3.12/site-packages/sympy/stats/tests/test_compound_rv.py +159 -0
  39. hug/lib/python3.12/site-packages/sympy/stats/tests/test_continuous_rv.py +1583 -0
  40. hug/lib/python3.12/site-packages/sympy/stats/tests/test_discrete_rv.py +312 -0
  41. hug/lib/python3.12/site-packages/sympy/stats/tests/test_error_prop.py +60 -0
  42. hug/lib/python3.12/site-packages/sympy/stats/tests/test_finite_rv.py +509 -0
  43. hug/lib/python3.12/site-packages/sympy/stats/tests/test_joint_rv.py +436 -0
  44. hug/lib/python3.12/site-packages/sympy/stats/tests/test_matrix_distributions.py +186 -0
  45. hug/lib/python3.12/site-packages/sympy/stats/tests/test_mix.py +82 -0
  46. hug/lib/python3.12/site-packages/sympy/stats/tests/test_random_matrix.py +135 -0
  47. hug/lib/python3.12/site-packages/sympy/stats/tests/test_rv.py +441 -0
  48. hug/lib/python3.12/site-packages/sympy/stats/tests/test_stochastic_process.py +763 -0
  49. hug/lib/python3.12/site-packages/sympy/stats/tests/test_symbolic_multivariate.py +172 -0
  50. 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
+ [![pypi version](https://img.shields.io/pypi/v/sympy.svg)](https://pypi.python.org/pypi/sympy)
52
+ [![Join the chat at https://gitter.im/sympy/sympy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sympy/sympy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
53
+ [![Zenodo Badge](https://zenodo.org/badge/18918/sympy/sympy.svg)](https://zenodo.org/badge/latestdoi/18918/sympy/sympy)
54
+ [![Downloads](https://pepy.tech/badge/sympy/month)](https://pepy.tech/project/sympy)
55
+ [![GitHub Issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/sympy/sympy/issues)
56
+ [![Git Tutorial](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project)
57
+ [![Powered by NumFocus](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](https://numfocus.org)
58
+ [![Commits since last release](https://img.shields.io/github/commits-since/sympy/sympy/latest.svg?longCache=true&style=flat-square&logo=git&logoColor=fff)](https://github.com/sympy/sympy/releases)
59
+
60
+ [![SymPy Banner](https://github.com/sympy/sympy/raw/master/banner.svg)](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