Spaces:
Running
Running
Upload 1329 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/INSTALLER +1 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/METADATA +62 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/RECORD +175 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/REQUESTED +0 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/WHEEL +5 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/entry_points.txt +9 -0
- MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/top_level.txt +1 -0
- MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/INSTALLER +1 -0
- MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/METADATA +25 -0
- MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/RECORD +119 -0
- MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/WHEEL +5 -0
- MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/top_level.txt +1 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/INSTALLER +1 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/LICENSE +27 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/METADATA +233 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/RECORD +180 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/WHEEL +5 -0
- MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/top_level.txt +1 -0
- MLPY/Lib/site-packages/mpmath/__init__.py +468 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/ctx_base.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/ctx_fp.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/ctx_iv.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/ctx_mp.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/ctx_mp_python.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/function_docs.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/identification.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/math2.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/rational.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/usertools.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/__pycache__/visualization.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__init__.py +6 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/__init__.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/approximation.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/calculus.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/differentiation.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/extrapolation.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/inverselaplace.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/odes.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/optimization.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/polynomials.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/__pycache__/quadrature.cpython-39.pyc +0 -0
- MLPY/Lib/site-packages/mpmath/calculus/approximation.py +246 -0
- MLPY/Lib/site-packages/mpmath/calculus/calculus.py +6 -0
- MLPY/Lib/site-packages/mpmath/calculus/differentiation.py +647 -0
- MLPY/Lib/site-packages/mpmath/calculus/extrapolation.py +2115 -0
- MLPY/Lib/site-packages/mpmath/calculus/inverselaplace.py +973 -0
- MLPY/Lib/site-packages/mpmath/calculus/odes.py +288 -0
- MLPY/Lib/site-packages/mpmath/calculus/optimization.py +1102 -0
- MLPY/Lib/site-packages/mpmath/calculus/polynomials.py +213 -0
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/METADATA
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: mlagents
|
3 |
+
Version: 0.30.0
|
4 |
+
Summary: Unity Machine Learning Agents
|
5 |
+
Home-page: https://github.com/Unity-Technologies/ml-agents
|
6 |
+
Author: Unity Technologies
|
7 |
+
Author-email: [email protected]
|
8 |
+
Classifier: Intended Audience :: Developers
|
9 |
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
10 |
+
Classifier: License :: OSI Approved :: Apache Software License
|
11 |
+
Classifier: Programming Language :: Python :: 3.8
|
12 |
+
Classifier: Programming Language :: Python :: 3.9
|
13 |
+
Classifier: Programming Language :: Python :: 3.10
|
14 |
+
Requires-Python: >=3.8.13,<=3.10.8
|
15 |
+
Description-Content-Type: text/markdown
|
16 |
+
Requires-Dist: grpcio >=1.11.0
|
17 |
+
Requires-Dist: h5py >=2.9.0
|
18 |
+
Requires-Dist: mlagents-envs ==0.30.0
|
19 |
+
Requires-Dist: numpy <2.0,>=1.13.3
|
20 |
+
Requires-Dist: Pillow >=4.2.1
|
21 |
+
Requires-Dist: protobuf >=3.6
|
22 |
+
Requires-Dist: pyyaml >=3.1.0
|
23 |
+
Requires-Dist: tensorboard >=1.15
|
24 |
+
Requires-Dist: attrs >=19.3.0
|
25 |
+
Requires-Dist: torch <1.9.0,>=1.6.0 ; platform_system != "Windows" and python_version < "3.9"
|
26 |
+
Requires-Dist: torch <=1.11.0,>=1.8.0 ; platform_system != "Windows" and python_version >= "3.9"
|
27 |
+
Requires-Dist: pypiwin32 ==223 ; platform_system == "Windows"
|
28 |
+
Requires-Dist: cattrs <1.1.0 ; python_version < "3.8"
|
29 |
+
Requires-Dist: importlib-metadata ==4.4 ; python_version < "3.8"
|
30 |
+
Requires-Dist: cattrs <1.7,>=1.1.0 ; python_version >= "3.8"
|
31 |
+
|
32 |
+
# Unity ML-Agents Trainers
|
33 |
+
|
34 |
+
The `mlagents` Python package is part of the
|
35 |
+
[ML-Agents Toolkit](https://github.com/Unity-Technologies/ml-agents). `mlagents`
|
36 |
+
provides a set of reinforcement and imitation learning algorithms designed to be
|
37 |
+
used with Unity environments. The algorithms interface with the Python API
|
38 |
+
provided by the `mlagents_envs` package. See [here](../docs/Python-LLAPI.md) for
|
39 |
+
more information on `mlagents_envs`.
|
40 |
+
|
41 |
+
The algorithms can be accessed using the: `mlagents-learn` access point. See
|
42 |
+
[here](../docs/Training-ML-Agents.md) for more information on using this
|
43 |
+
package.
|
44 |
+
|
45 |
+
## Installation
|
46 |
+
|
47 |
+
Install the `mlagents` package with:
|
48 |
+
|
49 |
+
```sh
|
50 |
+
python -m pip install mlagents==0.30.0
|
51 |
+
```
|
52 |
+
|
53 |
+
## Usage & More Information
|
54 |
+
|
55 |
+
For more information on the ML-Agents Toolkit and how to instrument a Unity
|
56 |
+
scene with the ML-Agents SDK, check out the main
|
57 |
+
[ML-Agents Toolkit documentation](../docs/Readme.md).
|
58 |
+
|
59 |
+
## Limitations
|
60 |
+
|
61 |
+
- Resuming self-play from a checkpoint resets the reported ELO to the default
|
62 |
+
value.
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/RECORD
ADDED
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
../../Scripts/mlagents-learn.exe,sha256=pNeSgQInMNLCUF2n3o5mBxX9oLP8Hr6qJLKNkH-YEG0,108394
|
2 |
+
../../Scripts/mlagents-run-experiment.exe,sha256=tg0YWa3eMDIbkZXgXwroG5tpHqycRvXFEaoR3Od0f40,108403
|
3 |
+
mlagents-0.30.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
4 |
+
mlagents-0.30.0.dist-info/METADATA,sha256=chdO78bUfunObqbfcJB785p7NAftlD-VPWYTu0SHpcc,2406
|
5 |
+
mlagents-0.30.0.dist-info/RECORD,,
|
6 |
+
mlagents-0.30.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7 |
+
mlagents-0.30.0.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
|
8 |
+
mlagents-0.30.0.dist-info/entry_points.txt,sha256=rc8cYQbQtS5CskjJHJzZxmkCYP-yFwR2_CzOffeZL08,310
|
9 |
+
mlagents-0.30.0.dist-info/top_level.txt,sha256=LIH88FaXtKCg_PiFin-NGZISQJ0tIXWpkeTQWtFSj5E,9
|
10 |
+
mlagents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11 |
+
mlagents/__pycache__/__init__.cpython-39.pyc,,
|
12 |
+
mlagents/plugins/__init__.py,sha256=C4AnFR_yVEbD8-iC-cDizZrRixLypvBZxc-VLRwyC8g,265
|
13 |
+
mlagents/plugins/__pycache__/__init__.cpython-39.pyc,,
|
14 |
+
mlagents/plugins/__pycache__/stats_writer.cpython-39.pyc,,
|
15 |
+
mlagents/plugins/__pycache__/trainer_type.cpython-39.pyc,,
|
16 |
+
mlagents/plugins/stats_writer.py,sha256=uS5-k2mx4vNCybBTl5WVn9G4S0mb0-cv_8rC56caS6A,2717
|
17 |
+
mlagents/plugins/trainer_type.py,sha256=FV5byclgcP3nG0s3cdfCit98c_dJ_5ToiR6dZlDFt5g,3120
|
18 |
+
mlagents/torch_utils/__init__.py,sha256=bawTiOuYKBXHJRs7fyyXQHTVp1QUtpji3H-lGO6KkoE,238
|
19 |
+
mlagents/torch_utils/__pycache__/__init__.cpython-39.pyc,,
|
20 |
+
mlagents/torch_utils/__pycache__/cpu_utils.cpython-39.pyc,,
|
21 |
+
mlagents/torch_utils/__pycache__/globals.cpython-39.pyc,,
|
22 |
+
mlagents/torch_utils/__pycache__/torch.cpython-39.pyc,,
|
23 |
+
mlagents/torch_utils/cpu_utils.py,sha256=koYxRxElcLl-XcH43C7r5dZaiFpXTr7VN51rz3i5r-U,1464
|
24 |
+
mlagents/torch_utils/globals.py,sha256=G4PDxGTi-MfDvf9KJCduoeNH9hJJyJ2a0Fbl-5r7HIY,321
|
25 |
+
mlagents/torch_utils/torch.py,sha256=cT7cyz1Jmr1bCDvatdL0J7a_h1HsCRSjQ3yQSlBglvs,1881
|
26 |
+
mlagents/trainers/__init__.py,sha256=ymb7Cn10uOrkBsmNF2FhbpsF0To4FXvnlH4fZYDOYc0,194
|
27 |
+
mlagents/trainers/__pycache__/__init__.cpython-39.pyc,,
|
28 |
+
mlagents/trainers/__pycache__/action_info.cpython-39.pyc,,
|
29 |
+
mlagents/trainers/__pycache__/agent_processor.cpython-39.pyc,,
|
30 |
+
mlagents/trainers/__pycache__/behavior_id_utils.cpython-39.pyc,,
|
31 |
+
mlagents/trainers/__pycache__/buffer.cpython-39.pyc,,
|
32 |
+
mlagents/trainers/__pycache__/cli_utils.cpython-39.pyc,,
|
33 |
+
mlagents/trainers/__pycache__/demo_loader.cpython-39.pyc,,
|
34 |
+
mlagents/trainers/__pycache__/directory_utils.cpython-39.pyc,,
|
35 |
+
mlagents/trainers/__pycache__/env_manager.cpython-39.pyc,,
|
36 |
+
mlagents/trainers/__pycache__/environment_parameter_manager.cpython-39.pyc,,
|
37 |
+
mlagents/trainers/__pycache__/exception.cpython-39.pyc,,
|
38 |
+
mlagents/trainers/__pycache__/learn.cpython-39.pyc,,
|
39 |
+
mlagents/trainers/__pycache__/run_experiment.cpython-39.pyc,,
|
40 |
+
mlagents/trainers/__pycache__/settings.cpython-39.pyc,,
|
41 |
+
mlagents/trainers/__pycache__/simple_env_manager.cpython-39.pyc,,
|
42 |
+
mlagents/trainers/__pycache__/stats.cpython-39.pyc,,
|
43 |
+
mlagents/trainers/__pycache__/subprocess_env_manager.cpython-39.pyc,,
|
44 |
+
mlagents/trainers/__pycache__/trainer_controller.cpython-39.pyc,,
|
45 |
+
mlagents/trainers/__pycache__/training_analytics_side_channel.cpython-39.pyc,,
|
46 |
+
mlagents/trainers/__pycache__/training_status.cpython-39.pyc,,
|
47 |
+
mlagents/trainers/__pycache__/trajectory.cpython-39.pyc,,
|
48 |
+
mlagents/trainers/__pycache__/upgrade_config.cpython-39.pyc,,
|
49 |
+
mlagents/trainers/action_info.py,sha256=xob0TgV393WKE7JzOuGjUNMNXujr9tGxSC5PLiHjUQY,831
|
50 |
+
mlagents/trainers/agent_processor.py,sha256=oYeV7lANba8oXDvwgvj5moT6DfzkV-iutMP8w82M_98,20474
|
51 |
+
mlagents/trainers/behavior_id_utils.py,sha256=hJ_E1-RKYXN-8rnybkI4YUbRq_bRBbWhbupDCBNquHc,2134
|
52 |
+
mlagents/trainers/buffer.py,sha256=CpPKTfVK1xuYQrEcmI0bx112abEHNfWl-nQ0zYV8a14,20000
|
53 |
+
mlagents/trainers/cli_utils.py,sha256=qnWO0dcNe_hlSDtSJ49unehY0uOgcUIyKvVGfSa3MKI,11721
|
54 |
+
mlagents/trainers/demo_loader.py,sha256=zTLXom5tF-_i42wbvdOEhrqb5HHVXTz67UVgd8H3BK8,9790
|
55 |
+
mlagents/trainers/directory_utils.py,sha256=4q6tEO5bBfM8IPCQyhHgLZW1F8ncqW4nhgX1Y7ENgms,3027
|
56 |
+
mlagents/trainers/env_manager.py,sha256=ouzQ3K4flHzYJHxvf_GeWS-Hh5FP8bhm8SYWHrpk0JM,5898
|
57 |
+
mlagents/trainers/environment_parameter_manager.py,sha256=wDO_kqiG8iXqZUwWlnw0aXfdDtlEG8Q9Hpv7ebN35QU,8458
|
58 |
+
mlagents/trainers/exception.py,sha256=EiyulULBNkHCnC85yI7TMt0zM_tFi73C6Xc2Vqu5eoA,1221
|
59 |
+
mlagents/trainers/ghost/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60 |
+
mlagents/trainers/ghost/__pycache__/__init__.cpython-39.pyc,,
|
61 |
+
mlagents/trainers/ghost/__pycache__/controller.cpython-39.pyc,,
|
62 |
+
mlagents/trainers/ghost/__pycache__/trainer.cpython-39.pyc,,
|
63 |
+
mlagents/trainers/ghost/controller.py,sha256=lMP7I7QC2JQFq2ypAJDoeeSIyLzXzNwBxHMUBFHjIWs,4347
|
64 |
+
mlagents/trainers/ghost/trainer.py,sha256=u9Y3YZtNsKHONiLNDO1LynmvWuwxCloxXZ6LJEp6MtM,20972
|
65 |
+
mlagents/trainers/learn.py,sha256=Lc17zalvi0LKNcD6EThBWBafJoH2Pb4HyCIcRaskbkU,10216
|
66 |
+
mlagents/trainers/model_saver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67 |
+
mlagents/trainers/model_saver/__pycache__/__init__.cpython-39.pyc,,
|
68 |
+
mlagents/trainers/model_saver/__pycache__/model_saver.cpython-39.pyc,,
|
69 |
+
mlagents/trainers/model_saver/__pycache__/torch_model_saver.cpython-39.pyc,,
|
70 |
+
mlagents/trainers/model_saver/model_saver.py,sha256=IYKRrarr9xg44UwJf2FmHPy_qZBhtrmAcygqGJewTcs,2569
|
71 |
+
mlagents/trainers/model_saver/torch_model_saver.py,sha256=q_fiUhd4UdQYk04uPcXSU-ai0xm-4EvsjRDMIF7kAwU,6620
|
72 |
+
mlagents/trainers/optimizer/__init__.py,sha256=AZxx5ZQd9FrD3TPvE-eC2TuZvTy8fhKjEKPYo_JylWg,68
|
73 |
+
mlagents/trainers/optimizer/__pycache__/__init__.cpython-39.pyc,,
|
74 |
+
mlagents/trainers/optimizer/__pycache__/optimizer.cpython-39.pyc,,
|
75 |
+
mlagents/trainers/optimizer/__pycache__/torch_optimizer.cpython-39.pyc,,
|
76 |
+
mlagents/trainers/optimizer/optimizer.py,sha256=WX9yAm-6sqV3_DKkvl9nbY0ytueKtc77EK9--osJivc,792
|
77 |
+
mlagents/trainers/optimizer/torch_optimizer.py,sha256=xrxVOqH4CLD3nFr32G75j9B0HTAGxAWW4vmaW-4pDJM,9420
|
78 |
+
mlagents/trainers/poca/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79 |
+
mlagents/trainers/poca/__pycache__/__init__.cpython-39.pyc,,
|
80 |
+
mlagents/trainers/poca/__pycache__/optimizer_torch.cpython-39.pyc,,
|
81 |
+
mlagents/trainers/poca/__pycache__/trainer.cpython-39.pyc,,
|
82 |
+
mlagents/trainers/poca/optimizer_torch.py,sha256=bYhhwtO7Q3YGRYinbj6I1aXsWUFKZG60CFHZ3nJR-hc,27848
|
83 |
+
mlagents/trainers/poca/trainer.py,sha256=YKRl2BZZW4FJj3nM2oSipDQ0_AoZyDy2KPSD9VyVduU,9819
|
84 |
+
mlagents/trainers/policy/__init__.py,sha256=gWYKy9a9WxSXDkCO-qCD1W0Fj8gndTREm8c-f-hx2eM,59
|
85 |
+
mlagents/trainers/policy/__pycache__/__init__.cpython-39.pyc,,
|
86 |
+
mlagents/trainers/policy/__pycache__/checkpoint_manager.cpython-39.pyc,,
|
87 |
+
mlagents/trainers/policy/__pycache__/policy.cpython-39.pyc,,
|
88 |
+
mlagents/trainers/policy/__pycache__/torch_policy.cpython-39.pyc,,
|
89 |
+
mlagents/trainers/policy/checkpoint_manager.py,sha256=sMUNw9T5wjB1n5Zd1jGQ2uDoaDG33meX_sVZCKE2pg0,3958
|
90 |
+
mlagents/trainers/policy/policy.py,sha256=Pa1uH49lWMqqtvf7C4YwU_fIIj609FQ2VsZZRhjARFU,5350
|
91 |
+
mlagents/trainers/policy/torch_policy.py,sha256=YYJQGDBxuwgaN-jpbdFoo_8_UZ5WaFHP1mK-OxzoM6I,6425
|
92 |
+
mlagents/trainers/ppo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93 |
+
mlagents/trainers/ppo/__pycache__/__init__.cpython-39.pyc,,
|
94 |
+
mlagents/trainers/ppo/__pycache__/optimizer_torch.cpython-39.pyc,,
|
95 |
+
mlagents/trainers/ppo/__pycache__/trainer.cpython-39.pyc,,
|
96 |
+
mlagents/trainers/ppo/optimizer_torch.py,sha256=Uh2stK3x-gOURlousroQRp0UMWRwZRg3ViYm_Kfekw4,7812
|
97 |
+
mlagents/trainers/ppo/trainer.py,sha256=zd7sOhm9w7GkZDp6Uymteju1tipLdcVGH_qCrl4Una0,8375
|
98 |
+
mlagents/trainers/run_experiment.py,sha256=dTFzVv_7l3jFp-0pWCLaBTjmY6JHKk4kQ0aAU6-SrGk,1026
|
99 |
+
mlagents/trainers/sac/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
100 |
+
mlagents/trainers/sac/__pycache__/__init__.cpython-39.pyc,,
|
101 |
+
mlagents/trainers/sac/__pycache__/optimizer_torch.cpython-39.pyc,,
|
102 |
+
mlagents/trainers/sac/__pycache__/trainer.cpython-39.pyc,,
|
103 |
+
mlagents/trainers/sac/optimizer_torch.py,sha256=K8j9Yvjkv0dIja1Gu958s7uwZotDZQJOQU9kRuwQ1yw,26502
|
104 |
+
mlagents/trainers/sac/trainer.py,sha256=YtlxEw2mApEHww5d5HcYRR-wTHE3rMHHGmvwPnozFvc,6685
|
105 |
+
mlagents/trainers/settings.py,sha256=hSc7j3W8VPS96EpJjFUkDXc8ipOikvTc1_IKcRDLHKY,37139
|
106 |
+
mlagents/trainers/simple_env_manager.py,sha256=8WM0P_SlSWqzd3iCo_BpbHwU0bJLkY-_ARNlhxoKCKI,3377
|
107 |
+
mlagents/trainers/stats.py,sha256=XhylF85cZd5nEKEUdyHzVOCOWMeC_GAIukMd3gqyAYk,14792
|
108 |
+
mlagents/trainers/subprocess_env_manager.py,sha256=zCFeEcVLpWEbZfnYeZ14UfqGdkkkR3eyHPXIYs3qej8,22762
|
109 |
+
mlagents/trainers/torch_entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
110 |
+
mlagents/trainers/torch_entities/__pycache__/__init__.cpython-39.pyc,,
|
111 |
+
mlagents/trainers/torch_entities/__pycache__/action_flattener.cpython-39.pyc,,
|
112 |
+
mlagents/trainers/torch_entities/__pycache__/action_log_probs.cpython-39.pyc,,
|
113 |
+
mlagents/trainers/torch_entities/__pycache__/action_model.cpython-39.pyc,,
|
114 |
+
mlagents/trainers/torch_entities/__pycache__/agent_action.cpython-39.pyc,,
|
115 |
+
mlagents/trainers/torch_entities/__pycache__/attention.cpython-39.pyc,,
|
116 |
+
mlagents/trainers/torch_entities/__pycache__/conditioning.cpython-39.pyc,,
|
117 |
+
mlagents/trainers/torch_entities/__pycache__/decoders.cpython-39.pyc,,
|
118 |
+
mlagents/trainers/torch_entities/__pycache__/distributions.cpython-39.pyc,,
|
119 |
+
mlagents/trainers/torch_entities/__pycache__/encoders.cpython-39.pyc,,
|
120 |
+
mlagents/trainers/torch_entities/__pycache__/layers.cpython-39.pyc,,
|
121 |
+
mlagents/trainers/torch_entities/__pycache__/model_serialization.cpython-39.pyc,,
|
122 |
+
mlagents/trainers/torch_entities/__pycache__/networks.cpython-39.pyc,,
|
123 |
+
mlagents/trainers/torch_entities/__pycache__/utils.cpython-39.pyc,,
|
124 |
+
mlagents/trainers/torch_entities/action_flattener.py,sha256=c1wiQzaJIsB2wuW8jZU7-o0jgEsn9y_05PxaqEoQFqQ,1713
|
125 |
+
mlagents/trainers/torch_entities/action_log_probs.py,sha256=2NeVwier4ZZHJMsLMtgMKnE2oebZafSBRbEBrc_0b04,4703
|
126 |
+
mlagents/trainers/torch_entities/action_model.py,sha256=wMJVT31IfeKTht3ibUAKElvDzrixKuNhOAVBg6Pm1Ic,10749
|
127 |
+
mlagents/trainers/torch_entities/agent_action.py,sha256=7zx0iBGC-FBgJBoVh5THnzo-57iKt8BYnZFixUQoMlQ,7189
|
128 |
+
mlagents/trainers/torch_entities/attention.py,sha256=VbzJigV7DmQIbUaG7AiqbSjtw2AsyDHtwQVi7V0OeKk,11931
|
129 |
+
mlagents/trainers/torch_entities/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
130 |
+
mlagents/trainers/torch_entities/components/__pycache__/__init__.cpython-39.pyc,,
|
131 |
+
mlagents/trainers/torch_entities/components/bc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
132 |
+
mlagents/trainers/torch_entities/components/bc/__pycache__/__init__.cpython-39.pyc,,
|
133 |
+
mlagents/trainers/torch_entities/components/bc/__pycache__/module.cpython-39.pyc,,
|
134 |
+
mlagents/trainers/torch_entities/components/bc/module.py,sha256=yHcnRcsmVH2ygmK4uqkwjfbwxxGl1Ba8kJ-0weYU2Rc,7469
|
135 |
+
mlagents/trainers/torch_entities/components/reward_providers/__init__.py,sha256=Q6cQK-uPVry728P23eS37j-BzwLwXodslTzdDNF4C4k,835
|
136 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/__init__.cpython-39.pyc,,
|
137 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/base_reward_provider.cpython-39.pyc,,
|
138 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/curiosity_reward_provider.cpython-39.pyc,,
|
139 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/extrinsic_reward_provider.cpython-39.pyc,,
|
140 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/gail_reward_provider.cpython-39.pyc,,
|
141 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/reward_provider_factory.cpython-39.pyc,,
|
142 |
+
mlagents/trainers/torch_entities/components/reward_providers/__pycache__/rnd_reward_provider.cpython-39.pyc,,
|
143 |
+
mlagents/trainers/torch_entities/components/reward_providers/base_reward_provider.py,sha256=0VHxlChwadl8o-pGBFMUL2pkB1I-UqSUmZPRbLWLjV8,2891
|
144 |
+
mlagents/trainers/torch_entities/components/reward_providers/curiosity_reward_provider.py,sha256=xzehU1vqMcZcfpy-FWgcCV0pGuebVT8k8mNBLH0UCPI,9339
|
145 |
+
mlagents/trainers/torch_entities/components/reward_providers/extrinsic_reward_provider.py,sha256=3rEXjC2jNsL_aCBQARh4-s0aLCMRLZv5wPeht-d3M7E,1786
|
146 |
+
mlagents/trainers/torch_entities/components/reward_providers/gail_reward_provider.py,sha256=VzURKz50wj4quTgdTRcareeh-wvPEqU8f8eWiUQTMzo,11190
|
147 |
+
mlagents/trainers/torch_entities/components/reward_providers/reward_provider_factory.py,sha256=9Hk4Ji6r4vIw6twoS0lMndrVvXD-0luOk4mSVLaapVM,1772
|
148 |
+
mlagents/trainers/torch_entities/components/reward_providers/rnd_reward_provider.py,sha256=pBHbtO0rtYGjlMISyUZETqpUkTAbX-RxJodYTx8kiys,3068
|
149 |
+
mlagents/trainers/torch_entities/conditioning.py,sha256=ZU9UAr2-AwNihGM9CzR5c5XGnaYXlmPkG2XTBQuxmVY,5134
|
150 |
+
mlagents/trainers/torch_entities/decoders.py,sha256=qPKcCNUqAFjzGdz8sSFKwAxsJWEcbjkkIXupCe4gT1I,793
|
151 |
+
mlagents/trainers/torch_entities/distributions.py,sha256=9W14ch5duHlsN0eSLlGS4xGfWUN4iy2Fkg18AqZrxfQ,8238
|
152 |
+
mlagents/trainers/torch_entities/encoders.py,sha256=UVYFImSj0mw8mC-L5v7kPtwA7O3yryZOWZeWwQpdamM,11206
|
153 |
+
mlagents/trainers/torch_entities/layers.py,sha256=HHaq4vpKS2PWLzRm7WhGp2ibzmBghe40oXklGHX9paA,7643
|
154 |
+
mlagents/trainers/torch_entities/model_serialization.py,sha256=M8B-SrHTXHn1KnVXu_E93nFMjvsPrs9SFs37PkYDwOA,6272
|
155 |
+
mlagents/trainers/torch_entities/networks.py,sha256=kSMGIa2dwgn1n00UiFxu2qYbS5bpk8zAYvXlozhEfYM,29280
|
156 |
+
mlagents/trainers/torch_entities/utils.py,sha256=O9Ew46WoYHV5wHxoSfnsYyJDgv4HhPOQZTVGXw6ZU1E,18698
|
157 |
+
mlagents/trainers/trainer/__init__.py,sha256=mkctLu3RcN5nXXev0Ca2UdQrfEmEjHaDCcnMQujyn74,139
|
158 |
+
mlagents/trainers/trainer/__pycache__/__init__.cpython-39.pyc,,
|
159 |
+
mlagents/trainers/trainer/__pycache__/off_policy_trainer.cpython-39.pyc,,
|
160 |
+
mlagents/trainers/trainer/__pycache__/on_policy_trainer.cpython-39.pyc,,
|
161 |
+
mlagents/trainers/trainer/__pycache__/rl_trainer.cpython-39.pyc,,
|
162 |
+
mlagents/trainers/trainer/__pycache__/trainer.cpython-39.pyc,,
|
163 |
+
mlagents/trainers/trainer/__pycache__/trainer_factory.cpython-39.pyc,,
|
164 |
+
mlagents/trainers/trainer/__pycache__/trainer_utils.cpython-39.pyc,,
|
165 |
+
mlagents/trainers/trainer/off_policy_trainer.py,sha256=bGamsOF8_X1_W6U_Mmvp9xmqxPs5wWP0RzuDlE7F66c,10489
|
166 |
+
mlagents/trainers/trainer/on_policy_trainer.py,sha256=yiCJtsNKrusDOWEAnNyblmo7X2qDILqjRO1oeih4vFI,5851
|
167 |
+
mlagents/trainers/trainer/rl_trainer.py,sha256=0MH5v1mWXls_pJI6dC9OR3c5rNnwfiOywe5AlqBMbyw,12542
|
168 |
+
mlagents/trainers/trainer/trainer.py,sha256=hEIqksByARHhzA0yck_k3ZKXAZSY551VoTe0cUgASTw,6084
|
169 |
+
mlagents/trainers/trainer/trainer_factory.py,sha256=tY1aGbw1rUIoUBc4cvEuaVsKMUyGUGgowJWQI2s88go,5007
|
170 |
+
mlagents/trainers/trainer/trainer_utils.py,sha256=u9v-0Ccey0myFrBuslfJEQU6iezitHs9WoX2a6Qq1NY,1671
|
171 |
+
mlagents/trainers/trainer_controller.py,sha256=E0IUqv7g4F2BjFQimhVSKrsUzPSCMJwxOmCuLp3RQvs,11391
|
172 |
+
mlagents/trainers/training_analytics_side_channel.py,sha256=xYpSpnAlFbBxv7k7d-nOU5PcLtmOqzSwJJq-WuWZ_r8,8121
|
173 |
+
mlagents/trainers/training_status.py,sha256=8EZ7ZqTCUPJJRo_N6jaUiwyxBlsn84pm4B0Znns_RBo,4323
|
174 |
+
mlagents/trainers/trajectory.py,sha256=_FcCBZaxTKSirT2TpZjNGPGfE90rTPvzXBmru9_CQYU,11646
|
175 |
+
mlagents/trainers/upgrade_config.py,sha256=c5UB4zAQBL9V7ywcVvWPRWe39onFomtQsfncO80LJVw,10319
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/REQUESTED
ADDED
File without changes
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (71.1.0)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/entry_points.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[console_scripts]
|
2 |
+
mlagents-learn = mlagents.trainers.learn:main
|
3 |
+
mlagents-run-experiment = mlagents.trainers.run_experiment:main
|
4 |
+
|
5 |
+
[mlagents.stats_writer]
|
6 |
+
default = mlagents.plugins.stats_writer:get_default_stats_writers
|
7 |
+
|
8 |
+
[mlagents.trainer_type]
|
9 |
+
default = mlagents.plugins.trainer_type:get_default_trainer_types
|
MLPY/Lib/site-packages/mlagents-0.30.0.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
mlagents
|
MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/METADATA
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: mlagents_envs
|
3 |
+
Version: 0.30.0
|
4 |
+
Summary: Unity Machine Learning Agents Interface
|
5 |
+
Home-page: https://github.com/Unity-Technologies/ml-agents
|
6 |
+
Author: Unity Technologies
|
7 |
+
Author-email: [email protected]
|
8 |
+
Classifier: Intended Audience :: Developers
|
9 |
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
10 |
+
Classifier: License :: OSI Approved :: Apache Software License
|
11 |
+
Classifier: Programming Language :: Python :: 3.8
|
12 |
+
Classifier: Programming Language :: Python :: 3.9
|
13 |
+
Classifier: Programming Language :: Python :: 3.10
|
14 |
+
Requires-Python: >=3.8.13,<=3.10.8
|
15 |
+
Requires-Dist: cloudpickle
|
16 |
+
Requires-Dist: grpcio >=1.11.0
|
17 |
+
Requires-Dist: numpy >=1.14.1
|
18 |
+
Requires-Dist: Pillow >=4.2.1
|
19 |
+
Requires-Dist: protobuf >=3.6
|
20 |
+
Requires-Dist: pyyaml >=3.1.0
|
21 |
+
Requires-Dist: gym >=0.21.0
|
22 |
+
Requires-Dist: pettingzoo ==1.15.0
|
23 |
+
Requires-Dist: numpy ==1.21.2
|
24 |
+
Requires-Dist: filelock >=3.4.0
|
25 |
+
|
MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/RECORD
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
mlagents_envs-0.30.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
2 |
+
mlagents_envs-0.30.0.dist-info/METADATA,sha256=ExFBBBp79KyKfJl4JkcI0PqFZA6oPNM72qxXPVnc3RI,922
|
3 |
+
mlagents_envs-0.30.0.dist-info/RECORD,,
|
4 |
+
mlagents_envs-0.30.0.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
|
5 |
+
mlagents_envs-0.30.0.dist-info/top_level.txt,sha256=jEe5REiGp6_VjGewVbI4CILjHZo2IYC03lUztCsSxUQ,14
|
6 |
+
mlagents_envs/__init__.py,sha256=ymb7Cn10uOrkBsmNF2FhbpsF0To4FXvnlH4fZYDOYc0,194
|
7 |
+
mlagents_envs/__pycache__/__init__.cpython-39.pyc,,
|
8 |
+
mlagents_envs/__pycache__/base_env.cpython-39.pyc,,
|
9 |
+
mlagents_envs/__pycache__/communicator.cpython-39.pyc,,
|
10 |
+
mlagents_envs/__pycache__/env_utils.cpython-39.pyc,,
|
11 |
+
mlagents_envs/__pycache__/environment.cpython-39.pyc,,
|
12 |
+
mlagents_envs/__pycache__/exception.cpython-39.pyc,,
|
13 |
+
mlagents_envs/__pycache__/logging_util.cpython-39.pyc,,
|
14 |
+
mlagents_envs/__pycache__/mock_communicator.cpython-39.pyc,,
|
15 |
+
mlagents_envs/__pycache__/rpc_communicator.cpython-39.pyc,,
|
16 |
+
mlagents_envs/__pycache__/rpc_utils.cpython-39.pyc,,
|
17 |
+
mlagents_envs/__pycache__/timers.cpython-39.pyc,,
|
18 |
+
mlagents_envs/base_env.py,sha256=x1Y4rpJMN9vulTyVGFDDIEsqCXxEsJ7QbGQLwFZ4PgY,22625
|
19 |
+
mlagents_envs/communicator.py,sha256=SZByKom33pvGNzu9Tmc0o8XwiTe1XGdTGnqQxV0CJWw,1887
|
20 |
+
mlagents_envs/communicator_objects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21 |
+
mlagents_envs/communicator_objects/__pycache__/__init__.cpython-39.pyc,,
|
22 |
+
mlagents_envs/communicator_objects/__pycache__/agent_action_pb2.cpython-39.pyc,,
|
23 |
+
mlagents_envs/communicator_objects/__pycache__/agent_info_action_pair_pb2.cpython-39.pyc,,
|
24 |
+
mlagents_envs/communicator_objects/__pycache__/agent_info_pb2.cpython-39.pyc,,
|
25 |
+
mlagents_envs/communicator_objects/__pycache__/brain_parameters_pb2.cpython-39.pyc,,
|
26 |
+
mlagents_envs/communicator_objects/__pycache__/capabilities_pb2.cpython-39.pyc,,
|
27 |
+
mlagents_envs/communicator_objects/__pycache__/command_pb2.cpython-39.pyc,,
|
28 |
+
mlagents_envs/communicator_objects/__pycache__/custom_reset_parameters_pb2.cpython-39.pyc,,
|
29 |
+
mlagents_envs/communicator_objects/__pycache__/demonstration_meta_pb2.cpython-39.pyc,,
|
30 |
+
mlagents_envs/communicator_objects/__pycache__/engine_configuration_pb2.cpython-39.pyc,,
|
31 |
+
mlagents_envs/communicator_objects/__pycache__/header_pb2.cpython-39.pyc,,
|
32 |
+
mlagents_envs/communicator_objects/__pycache__/observation_pb2.cpython-39.pyc,,
|
33 |
+
mlagents_envs/communicator_objects/__pycache__/space_type_pb2.cpython-39.pyc,,
|
34 |
+
mlagents_envs/communicator_objects/__pycache__/training_analytics_pb2.cpython-39.pyc,,
|
35 |
+
mlagents_envs/communicator_objects/__pycache__/unity_input_pb2.cpython-39.pyc,,
|
36 |
+
mlagents_envs/communicator_objects/__pycache__/unity_message_pb2.cpython-39.pyc,,
|
37 |
+
mlagents_envs/communicator_objects/__pycache__/unity_output_pb2.cpython-39.pyc,,
|
38 |
+
mlagents_envs/communicator_objects/__pycache__/unity_rl_initialization_input_pb2.cpython-39.pyc,,
|
39 |
+
mlagents_envs/communicator_objects/__pycache__/unity_rl_initialization_output_pb2.cpython-39.pyc,,
|
40 |
+
mlagents_envs/communicator_objects/__pycache__/unity_rl_input_pb2.cpython-39.pyc,,
|
41 |
+
mlagents_envs/communicator_objects/__pycache__/unity_rl_output_pb2.cpython-39.pyc,,
|
42 |
+
mlagents_envs/communicator_objects/__pycache__/unity_to_external_pb2.cpython-39.pyc,,
|
43 |
+
mlagents_envs/communicator_objects/__pycache__/unity_to_external_pb2_grpc.cpython-39.pyc,,
|
44 |
+
mlagents_envs/communicator_objects/agent_action_pb2.py,sha256=cJLj4-1ph--PzYRdzGgYpcBFASvfp5DQdjyuOG-S4eE,3779
|
45 |
+
mlagents_envs/communicator_objects/agent_info_action_pair_pb2.py,sha256=yW-6BcBjE4AdD1wX49VGrJUo8VnhkDRSWP89vFFFWyo,3895
|
46 |
+
mlagents_envs/communicator_objects/agent_info_pb2.py,sha256=ryAM1iA0G8GPcM6v3HnUf2iyYM4Gpkd6DXVziKBWL-s,5851
|
47 |
+
mlagents_envs/communicator_objects/brain_parameters_pb2.py,sha256=Doc74jZ4w8bm9vQmE89XkbofPPKr_BPZ48OiCoH687k,8083
|
48 |
+
mlagents_envs/communicator_objects/capabilities_pb2.py,sha256=CzsSOHwdvIgzxwbiNmNHHYBfs6yW5p4fkAG_EmkvStc,5252
|
49 |
+
mlagents_envs/communicator_objects/command_pb2.py,sha256=ywUBoxkBbXn0YYluy8xHjDQxnmdFcAV1yrpMv_vjWTk,2066
|
50 |
+
mlagents_envs/communicator_objects/custom_reset_parameters_pb2.py,sha256=OzB2Zgi1q4IwEwXV5QwPjAqIghWHN_vIvHttrsHOAgs,2128
|
51 |
+
mlagents_envs/communicator_objects/demonstration_meta_pb2.py,sha256=XzjYZk8P0YjsK4qeXVQRyW6witqOG_4Y460o5Z2w5dE,4255
|
52 |
+
mlagents_envs/communicator_objects/engine_configuration_pb2.py,sha256=P60GIeybVr9-o1HlQP0nKnMd_R5n28pkVUvbRkGtYew,4641
|
53 |
+
mlagents_envs/communicator_objects/header_pb2.py,sha256=jPl6efvaRVikkU0zWkJEbIc9Le56duEx6kwo4H_bDVo,2703
|
54 |
+
mlagents_envs/communicator_objects/observation_pb2.py,sha256=HB1JPlJHRfXQAcZ_IcOu-8NfCPEehoSSsPGCxO8I1_Y,9620
|
55 |
+
mlagents_envs/communicator_objects/space_type_pb2.py,sha256=NLdPFrm9zP_jnwfRfN2Xdor1yXbBthcp_wtqqgeGdc4,1972
|
56 |
+
mlagents_envs/communicator_objects/training_analytics_pb2.py,sha256=cx887zBXzO_oYLnBWe6yqFDp8MFhdAU4dAxkv37XkV4,13623
|
57 |
+
mlagents_envs/communicator_objects/unity_input_pb2.py,sha256=boTQvkktMWcV23M34r9N8q-Z9_st0cMUmpXvIWXNm0M,3903
|
58 |
+
mlagents_envs/communicator_objects/unity_message_pb2.py,sha256=KEKDbZ8qDt8OOrv5CBq37B1l5dd05YQXxDGP513BrM8,4571
|
59 |
+
mlagents_envs/communicator_objects/unity_output_pb2.py,sha256=iIwtET2fdfwCvd_QtZZ0dCWJD3VKpDLfDalc5c4zjFY,3935
|
60 |
+
mlagents_envs/communicator_objects/unity_rl_initialization_input_pb2.py,sha256=k_iEL1KxNDMoZ8WLFm3E-KdgahSBJeTNauxZn7jpu2E,4940
|
61 |
+
mlagents_envs/communicator_objects/unity_rl_initialization_output_pb2.py,sha256=ntOKQtE7k8iyp5xpjpzGg_v79ATY5ep-XHkxgFpiQfo,5973
|
62 |
+
mlagents_envs/communicator_objects/unity_rl_input_pb2.py,sha256=SLyG0dYroHoBOhekwkhFjvbaC-H6-QIvBSTK9G0xiPo,8109
|
63 |
+
mlagents_envs/communicator_objects/unity_rl_output_pb2.py,sha256=2alPQeU_bYUSEn0shht0RiXeQOzbxZ8Rti0S4KJZ2RQ,7220
|
64 |
+
mlagents_envs/communicator_objects/unity_to_external_pb2.py,sha256=-HSKjNoqpwVu5ba4MoXFnew1s8Ot1_2FnNsoPG6hUt4,2356
|
65 |
+
mlagents_envs/communicator_objects/unity_to_external_pb2_grpc.py,sha256=QHmH4daN6Cx-WH-PbucLMcEAVt0NrTIxKHFXVUakJzY,1786
|
66 |
+
mlagents_envs/env_utils.py,sha256=ahAxUVh_ybN7rB0nU7lugelP-pUh3ws_8hlyhi9KPgg,5174
|
67 |
+
mlagents_envs/environment.py,sha256=GWLgwdGZPNsauGp9PCGK6ky_ccI7fb2HXkqAuW0t2Lo,22901
|
68 |
+
mlagents_envs/envs/__init__.py,sha256=ZbLbl2QmrG0w_k28qZruA3xztEQtU3f-QwKH7bcxGyo,578
|
69 |
+
mlagents_envs/envs/__pycache__/__init__.cpython-39.pyc,,
|
70 |
+
mlagents_envs/envs/__pycache__/env_helpers.cpython-39.pyc,,
|
71 |
+
mlagents_envs/envs/__pycache__/pettingzoo_env_factory.cpython-39.pyc,,
|
72 |
+
mlagents_envs/envs/__pycache__/unity_aec_env.cpython-39.pyc,,
|
73 |
+
mlagents_envs/envs/__pycache__/unity_gym_env.cpython-39.pyc,,
|
74 |
+
mlagents_envs/envs/__pycache__/unity_parallel_env.cpython-39.pyc,,
|
75 |
+
mlagents_envs/envs/__pycache__/unity_pettingzoo_base_env.cpython-39.pyc,,
|
76 |
+
mlagents_envs/envs/env_helpers.py,sha256=0_KCQQPDOL2UXub3Wi2p2uUOypLBK7n3xiOBk9mndXE,2860
|
77 |
+
mlagents_envs/envs/pettingzoo_env_factory.py,sha256=BT-RZtJsEfb_UKlUIqlX4xHMi1LNmb3NCDsWgxjDEAc,1957
|
78 |
+
mlagents_envs/envs/unity_aec_env.py,sha256=rOtvT1EYrMXpWJ8mLqdnaqHBnUHNNYx2ubPFqFRgObA,2494
|
79 |
+
mlagents_envs/envs/unity_gym_env.py,sha256=bR_yq6pQqIkp_fA_2PF5oJGCjtOFUIOWY75u1s9V4OE,14060
|
80 |
+
mlagents_envs/envs/unity_parallel_env.py,sha256=a2HCYdmoHX7XgT1PCyhPo-gTyibaU0Ys3TL5FnY95Jc,1594
|
81 |
+
mlagents_envs/envs/unity_pettingzoo_base_env.py,sha256=furHR6SvHjV2PQuCydMSi-h2fmE-vO7BN0ykut_HXqc,12365
|
82 |
+
mlagents_envs/exception.py,sha256=juuUc2myXKVakxkVnnnCDkqRbi84mewGy6CPv5N5hkE,1621
|
83 |
+
mlagents_envs/logging_util.py,sha256=aLYz3jqg_te3jei1hrQKolxIVlF3xwFfA8lzB1CXq7o,1866
|
84 |
+
mlagents_envs/mock_communicator.py,sha256=uvPKopMNsEnX7PRe2vRsxIeWIcbJth9IBjwSq7bLr9k,3931
|
85 |
+
mlagents_envs/registry/__init__.py,sha256=C3D8TtWFhcZKekZIgyXd6gIcnGTozePinCCj2GxqS-k,115
|
86 |
+
mlagents_envs/registry/__pycache__/__init__.cpython-39.pyc,,
|
87 |
+
mlagents_envs/registry/__pycache__/base_registry_entry.cpython-39.pyc,,
|
88 |
+
mlagents_envs/registry/__pycache__/binary_utils.cpython-39.pyc,,
|
89 |
+
mlagents_envs/registry/__pycache__/remote_registry_entry.cpython-39.pyc,,
|
90 |
+
mlagents_envs/registry/__pycache__/unity_env_registry.cpython-39.pyc,,
|
91 |
+
mlagents_envs/registry/base_registry_entry.py,sha256=odZ_EElER899S9Gqo-ZA2dgdmadhhdd3MsUZhJis0CY,1856
|
92 |
+
mlagents_envs/registry/binary_utils.py,sha256=j-URDvMeLV4x7lTvFkbi7emF0AbnhTEvJE7jHA_X8hI,9591
|
93 |
+
mlagents_envs/registry/remote_registry_entry.py,sha256=C6UqVrit4ZmS7r3jjrcYzheLttXYJWSstw68gzU5QQI,3394
|
94 |
+
mlagents_envs/registry/unity_env_registry.py,sha256=d0_8xrDjGTkidwTq-mtfIl2Sp_ncShTsxm5GG3FHKRc,5020
|
95 |
+
mlagents_envs/rpc_communicator.py,sha256=OS968fiWWxOutSTJWpv8cZ25rX-VLY2FHcb9ccR7ISk,6729
|
96 |
+
mlagents_envs/rpc_utils.py,sha256=Im5koVMpi7UqvxEUSuKVVFkhLGTtzgiEerwAkwV4arY,16415
|
97 |
+
mlagents_envs/side_channel/__init__.py,sha256=Jks-qs8TPIPmSGCiv3_GdJ2V5225UZrvptuZoIGLyJI,381
|
98 |
+
mlagents_envs/side_channel/__pycache__/__init__.cpython-39.pyc,,
|
99 |
+
mlagents_envs/side_channel/__pycache__/default_training_analytics_side_channel.cpython-39.pyc,,
|
100 |
+
mlagents_envs/side_channel/__pycache__/engine_configuration_channel.cpython-39.pyc,,
|
101 |
+
mlagents_envs/side_channel/__pycache__/environment_parameters_channel.cpython-39.pyc,,
|
102 |
+
mlagents_envs/side_channel/__pycache__/float_properties_channel.cpython-39.pyc,,
|
103 |
+
mlagents_envs/side_channel/__pycache__/incoming_message.cpython-39.pyc,,
|
104 |
+
mlagents_envs/side_channel/__pycache__/outgoing_message.cpython-39.pyc,,
|
105 |
+
mlagents_envs/side_channel/__pycache__/raw_bytes_channel.cpython-39.pyc,,
|
106 |
+
mlagents_envs/side_channel/__pycache__/side_channel.cpython-39.pyc,,
|
107 |
+
mlagents_envs/side_channel/__pycache__/side_channel_manager.cpython-39.pyc,,
|
108 |
+
mlagents_envs/side_channel/__pycache__/stats_side_channel.cpython-39.pyc,,
|
109 |
+
mlagents_envs/side_channel/default_training_analytics_side_channel.py,sha256=1KK6EPqJcGxeKaRdqjX6dlfnNx4jFPTEOovQ1dnKjWk,1835
|
110 |
+
mlagents_envs/side_channel/engine_configuration_channel.py,sha256=y74y9qABe3590KaCsp6JM0v-mJY29U2DWpsT5FM2iDk,4937
|
111 |
+
mlagents_envs/side_channel/environment_parameters_channel.py,sha256=ym9hvTljdHrfNWlomzIq3FUHNKqzScAl1uS4YOaqJOI,3874
|
112 |
+
mlagents_envs/side_channel/float_properties_channel.py,sha256=7rYK2wyBg-XISUdt_CjutqDehOtyB-i12J6700bWwEU,2227
|
113 |
+
mlagents_envs/side_channel/incoming_message.py,sha256=scXeGH-p1-x6c4TIN9YzYERVjqrR-hqWdlOxeqC9OrY,3366
|
114 |
+
mlagents_envs/side_channel/outgoing_message.py,sha256=gLo3a8m-L4PVINNLKV1znax33KATylgIhT9SwVTIGL8,1961
|
115 |
+
mlagents_envs/side_channel/raw_bytes_channel.py,sha256=r2rSwKinlbQd-nJLdPy5wQ7231SB4dXI-25XweAORfs,1301
|
116 |
+
mlagents_envs/side_channel/side_channel.py,sha256=ns5gaeVkUeP8LV8yDsGDA4vMeYI20vSX1z0hRuE7l2A,1504
|
117 |
+
mlagents_envs/side_channel/side_channel_manager.py,sha256=4W4nVvYs5l2Ad5g5SW9JGLBEYpxlrbhjAqmonlysrE0,3601
|
118 |
+
mlagents_envs/side_channel/stats_side_channel.py,sha256=PI5fA08AJejHAUWLd8FIMyva6MxyKbWn3V8Kbx6zTzk,1876
|
119 |
+
mlagents_envs/timers.py,sha256=nGXmnHV6o6Trx--54lie2Lt3LJEzBDuSORtzo8qDncg,11684
|
MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (71.1.0)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
MLPY/Lib/site-packages/mlagents_envs-0.30.0.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
mlagents_envs
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright (c) 2005-2021 Fredrik Johansson and mpmath contributors
|
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 the copyright holder nor the names of its
|
14 |
+
contributors may be used to endorse or promote products derived
|
15 |
+
from this software without specific prior written permission.
|
16 |
+
|
17 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
21 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
27 |
+
DAMAGE.
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/METADATA
ADDED
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: mpmath
|
3 |
+
Version: 1.3.0
|
4 |
+
Summary: Python library for arbitrary-precision floating-point arithmetic
|
5 |
+
Home-page: http://mpmath.org/
|
6 |
+
Author: Fredrik Johansson
|
7 |
+
Author-email: [email protected]
|
8 |
+
License: BSD
|
9 |
+
Project-URL: Source, https://github.com/fredrik-johansson/mpmath
|
10 |
+
Project-URL: Tracker, https://github.com/fredrik-johansson/mpmath/issues
|
11 |
+
Project-URL: Documentation, http://mpmath.org/doc/current/
|
12 |
+
Classifier: License :: OSI Approved :: BSD License
|
13 |
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
14 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
15 |
+
Classifier: Programming Language :: Python
|
16 |
+
Classifier: Programming Language :: Python :: 2
|
17 |
+
Classifier: Programming Language :: Python :: 2.7
|
18 |
+
Classifier: Programming Language :: Python :: 3
|
19 |
+
Classifier: Programming Language :: Python :: 3.5
|
20 |
+
Classifier: Programming Language :: Python :: 3.6
|
21 |
+
Classifier: Programming Language :: Python :: 3.7
|
22 |
+
Classifier: Programming Language :: Python :: 3.8
|
23 |
+
Classifier: Programming Language :: Python :: 3.9
|
24 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
25 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
26 |
+
License-File: LICENSE
|
27 |
+
Provides-Extra: develop
|
28 |
+
Requires-Dist: pytest (>=4.6) ; extra == 'develop'
|
29 |
+
Requires-Dist: pycodestyle ; extra == 'develop'
|
30 |
+
Requires-Dist: pytest-cov ; extra == 'develop'
|
31 |
+
Requires-Dist: codecov ; extra == 'develop'
|
32 |
+
Requires-Dist: wheel ; extra == 'develop'
|
33 |
+
Provides-Extra: docs
|
34 |
+
Requires-Dist: sphinx ; extra == 'docs'
|
35 |
+
Provides-Extra: gmpy
|
36 |
+
Requires-Dist: gmpy2 (>=2.1.0a4) ; (platform_python_implementation != "PyPy") and extra == 'gmpy'
|
37 |
+
Provides-Extra: tests
|
38 |
+
Requires-Dist: pytest (>=4.6) ; extra == 'tests'
|
39 |
+
|
40 |
+
mpmath
|
41 |
+
======
|
42 |
+
|
43 |
+
|pypi version| |Build status| |Code coverage status| |Zenodo Badge|
|
44 |
+
|
45 |
+
.. |pypi version| image:: https://img.shields.io/pypi/v/mpmath.svg
|
46 |
+
:target: https://pypi.python.org/pypi/mpmath
|
47 |
+
.. |Build status| image:: https://github.com/fredrik-johansson/mpmath/workflows/test/badge.svg
|
48 |
+
:target: https://github.com/fredrik-johansson/mpmath/actions?workflow=test
|
49 |
+
.. |Code coverage status| image:: https://codecov.io/gh/fredrik-johansson/mpmath/branch/master/graph/badge.svg
|
50 |
+
:target: https://codecov.io/gh/fredrik-johansson/mpmath
|
51 |
+
.. |Zenodo Badge| image:: https://zenodo.org/badge/2934512.svg
|
52 |
+
:target: https://zenodo.org/badge/latestdoi/2934512
|
53 |
+
|
54 |
+
A Python library for arbitrary-precision floating-point arithmetic.
|
55 |
+
|
56 |
+
Website: http://mpmath.org/
|
57 |
+
Main author: Fredrik Johansson <[email protected]>
|
58 |
+
|
59 |
+
Mpmath is free software released under the New BSD License (see the
|
60 |
+
LICENSE file for details)
|
61 |
+
|
62 |
+
0. History and credits
|
63 |
+
----------------------
|
64 |
+
|
65 |
+
The following people (among others) have contributed major patches
|
66 |
+
or new features to mpmath:
|
67 |
+
|
68 |
+
* Pearu Peterson <[email protected]>
|
69 |
+
* Mario Pernici <[email protected]>
|
70 |
+
* Ondrej Certik <[email protected]>
|
71 |
+
* Vinzent Steinberg <[email protected]>
|
72 |
+
* Nimish Telang <[email protected]>
|
73 |
+
* Mike Taschuk <[email protected]>
|
74 |
+
* Case Van Horsen <[email protected]>
|
75 |
+
* Jorn Baayen <[email protected]>
|
76 |
+
* Chris Smith <[email protected]>
|
77 |
+
* Juan Arias de Reyna <[email protected]>
|
78 |
+
* Ioannis Tziakos <[email protected]>
|
79 |
+
* Aaron Meurer <[email protected]>
|
80 |
+
* Stefan Krastanov <[email protected]>
|
81 |
+
* Ken Allen <[email protected]>
|
82 |
+
* Timo Hartmann <[email protected]>
|
83 |
+
* Sergey B Kirpichev <[email protected]>
|
84 |
+
* Kris Kuhlman <[email protected]>
|
85 |
+
* Paul Masson <[email protected]>
|
86 |
+
* Michael Kagalenko <[email protected]>
|
87 |
+
* Jonathan Warner <[email protected]>
|
88 |
+
* Max Gaukler <[email protected]>
|
89 |
+
* Guillermo Navas-Palencia <[email protected]>
|
90 |
+
* Nike Dattani <[email protected]>
|
91 |
+
|
92 |
+
Numerous other people have contributed by reporting bugs,
|
93 |
+
requesting new features, or suggesting improvements to the
|
94 |
+
documentation.
|
95 |
+
|
96 |
+
For a detailed changelog, including individual contributions,
|
97 |
+
see the CHANGES file.
|
98 |
+
|
99 |
+
Fredrik's work on mpmath during summer 2008 was sponsored by Google
|
100 |
+
as part of the Google Summer of Code program.
|
101 |
+
|
102 |
+
Fredrik's work on mpmath during summer 2009 was sponsored by the
|
103 |
+
American Institute of Mathematics under the support of the National Science
|
104 |
+
Foundation Grant No. 0757627 (FRG: L-functions and Modular Forms).
|
105 |
+
|
106 |
+
Any opinions, findings, and conclusions or recommendations expressed in this
|
107 |
+
material are those of the author(s) and do not necessarily reflect the
|
108 |
+
views of the sponsors.
|
109 |
+
|
110 |
+
Credit also goes to:
|
111 |
+
|
112 |
+
* The authors of the GMP library and the Python wrapper
|
113 |
+
gmpy, enabling mpmath to become much faster at
|
114 |
+
high precision
|
115 |
+
* The authors of MPFR, pari/gp, MPFUN, and other arbitrary-
|
116 |
+
precision libraries, whose documentation has been helpful
|
117 |
+
for implementing many of the algorithms in mpmath
|
118 |
+
* Wikipedia contributors; Abramowitz & Stegun; Gradshteyn & Ryzhik;
|
119 |
+
Wolfram Research for MathWorld and the Wolfram Functions site.
|
120 |
+
These are the main references used for special functions
|
121 |
+
implementations.
|
122 |
+
* George Brandl for developing the Sphinx documentation tool
|
123 |
+
used to build mpmath's documentation
|
124 |
+
|
125 |
+
Release history:
|
126 |
+
|
127 |
+
* Version 1.3.0 released on March 7, 2023
|
128 |
+
* Version 1.2.0 released on February 1, 2021
|
129 |
+
* Version 1.1.0 released on December 11, 2018
|
130 |
+
* Version 1.0.0 released on September 27, 2017
|
131 |
+
* Version 0.19 released on June 10, 2014
|
132 |
+
* Version 0.18 released on December 31, 2013
|
133 |
+
* Version 0.17 released on February 1, 2011
|
134 |
+
* Version 0.16 released on September 24, 2010
|
135 |
+
* Version 0.15 released on June 6, 2010
|
136 |
+
* Version 0.14 released on February 5, 2010
|
137 |
+
* Version 0.13 released on August 13, 2009
|
138 |
+
* Version 0.12 released on June 9, 2009
|
139 |
+
* Version 0.11 released on January 26, 2009
|
140 |
+
* Version 0.10 released on October 15, 2008
|
141 |
+
* Version 0.9 released on August 23, 2008
|
142 |
+
* Version 0.8 released on April 20, 2008
|
143 |
+
* Version 0.7 released on March 12, 2008
|
144 |
+
* Version 0.6 released on January 13, 2008
|
145 |
+
* Version 0.5 released on November 24, 2007
|
146 |
+
* Version 0.4 released on November 3, 2007
|
147 |
+
* Version 0.3 released on October 5, 2007
|
148 |
+
* Version 0.2 released on October 2, 2007
|
149 |
+
* Version 0.1 released on September 27, 2007
|
150 |
+
|
151 |
+
1. Download & installation
|
152 |
+
--------------------------
|
153 |
+
|
154 |
+
Mpmath requires Python 2.7 or 3.5 (or later versions). It has been tested
|
155 |
+
with CPython 2.7, 3.5 through 3.7 and for PyPy.
|
156 |
+
|
157 |
+
The latest release of mpmath can be downloaded from the mpmath
|
158 |
+
website and from https://github.com/fredrik-johansson/mpmath/releases
|
159 |
+
|
160 |
+
It should also be available in the Python Package Index at
|
161 |
+
https://pypi.python.org/pypi/mpmath
|
162 |
+
|
163 |
+
To install latest release of Mpmath with pip, simply run
|
164 |
+
|
165 |
+
``pip install mpmath``
|
166 |
+
|
167 |
+
Or unpack the mpmath archive and run
|
168 |
+
|
169 |
+
``python setup.py install``
|
170 |
+
|
171 |
+
Mpmath can also be installed using
|
172 |
+
|
173 |
+
``python -m easy_install mpmath``
|
174 |
+
|
175 |
+
The latest development code is available from
|
176 |
+
https://github.com/fredrik-johansson/mpmath
|
177 |
+
|
178 |
+
See the main documentation for more detailed instructions.
|
179 |
+
|
180 |
+
2. Running tests
|
181 |
+
----------------
|
182 |
+
|
183 |
+
The unit tests in mpmath/tests/ can be run via the script
|
184 |
+
runtests.py, but it is recommended to run them with py.test
|
185 |
+
(https://pytest.org/), especially
|
186 |
+
to generate more useful reports in case there are failures.
|
187 |
+
|
188 |
+
You may also want to check out the demo scripts in the demo
|
189 |
+
directory.
|
190 |
+
|
191 |
+
The master branch is automatically tested by Travis CI.
|
192 |
+
|
193 |
+
3. Documentation
|
194 |
+
----------------
|
195 |
+
|
196 |
+
Documentation in reStructuredText format is available in the
|
197 |
+
doc directory included with the source package. These files
|
198 |
+
are human-readable, but can be compiled to prettier HTML using
|
199 |
+
the build.py script (requires Sphinx, http://sphinx.pocoo.org/).
|
200 |
+
|
201 |
+
See setup.txt in the documentation for more information.
|
202 |
+
|
203 |
+
The most recent documentation is also available in HTML format:
|
204 |
+
|
205 |
+
http://mpmath.org/doc/current/
|
206 |
+
|
207 |
+
4. Known problems
|
208 |
+
-----------------
|
209 |
+
|
210 |
+
Mpmath is a work in progress. Major issues include:
|
211 |
+
|
212 |
+
* Some functions may return incorrect values when given extremely
|
213 |
+
large arguments or arguments very close to singularities.
|
214 |
+
|
215 |
+
* Directed rounding works for arithmetic operations. It is implemented
|
216 |
+
heuristically for other operations, and their results may be off by one
|
217 |
+
or two units in the last place (even if otherwise accurate).
|
218 |
+
|
219 |
+
* Some IEEE 754 features are not available. Inifinities and NaN are
|
220 |
+
partially supported; denormal rounding is currently not available
|
221 |
+
at all.
|
222 |
+
|
223 |
+
* The interface for switching precision and rounding is not finalized.
|
224 |
+
The current method is not threadsafe.
|
225 |
+
|
226 |
+
5. Help and bug reports
|
227 |
+
-----------------------
|
228 |
+
|
229 |
+
General questions and comments can be sent to the mpmath mailinglist,
|
230 | |
231 |
+
|
232 |
+
You can also report bugs and send patches to the mpmath issue tracker,
|
233 |
+
https://github.com/fredrik-johansson/mpmath/issues
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/RECORD
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
mpmath-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
2 |
+
mpmath-1.3.0.dist-info/LICENSE,sha256=wmyugdpFCOXiSZhXd6M4IfGDIj67dNf4z7-Q_n7vL7c,1537
|
3 |
+
mpmath-1.3.0.dist-info/METADATA,sha256=RLZupES5wNGa6UgV01a_BHrmtoDBkmi1wmVofNaoFAY,8630
|
4 |
+
mpmath-1.3.0.dist-info/RECORD,,
|
5 |
+
mpmath-1.3.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
6 |
+
mpmath-1.3.0.dist-info/top_level.txt,sha256=BUVWrh8EVlkOhM1n3X9S8msTaVcC-3s6Sjt60avHYus,7
|
7 |
+
mpmath/__init__.py,sha256=skFYTSwfwDBLChAV6pI3SdewgAQR3UBtyrfIK_Jdn-g,8765
|
8 |
+
mpmath/__pycache__/__init__.cpython-39.pyc,,
|
9 |
+
mpmath/__pycache__/ctx_base.cpython-39.pyc,,
|
10 |
+
mpmath/__pycache__/ctx_fp.cpython-39.pyc,,
|
11 |
+
mpmath/__pycache__/ctx_iv.cpython-39.pyc,,
|
12 |
+
mpmath/__pycache__/ctx_mp.cpython-39.pyc,,
|
13 |
+
mpmath/__pycache__/ctx_mp_python.cpython-39.pyc,,
|
14 |
+
mpmath/__pycache__/function_docs.cpython-39.pyc,,
|
15 |
+
mpmath/__pycache__/identification.cpython-39.pyc,,
|
16 |
+
mpmath/__pycache__/math2.cpython-39.pyc,,
|
17 |
+
mpmath/__pycache__/rational.cpython-39.pyc,,
|
18 |
+
mpmath/__pycache__/usertools.cpython-39.pyc,,
|
19 |
+
mpmath/__pycache__/visualization.cpython-39.pyc,,
|
20 |
+
mpmath/calculus/__init__.py,sha256=UAgCIJ1YmaeyTqpNzjBlCZGeIzLtUZMEEpl99VWNjus,162
|
21 |
+
mpmath/calculus/__pycache__/__init__.cpython-39.pyc,,
|
22 |
+
mpmath/calculus/__pycache__/approximation.cpython-39.pyc,,
|
23 |
+
mpmath/calculus/__pycache__/calculus.cpython-39.pyc,,
|
24 |
+
mpmath/calculus/__pycache__/differentiation.cpython-39.pyc,,
|
25 |
+
mpmath/calculus/__pycache__/extrapolation.cpython-39.pyc,,
|
26 |
+
mpmath/calculus/__pycache__/inverselaplace.cpython-39.pyc,,
|
27 |
+
mpmath/calculus/__pycache__/odes.cpython-39.pyc,,
|
28 |
+
mpmath/calculus/__pycache__/optimization.cpython-39.pyc,,
|
29 |
+
mpmath/calculus/__pycache__/polynomials.cpython-39.pyc,,
|
30 |
+
mpmath/calculus/__pycache__/quadrature.cpython-39.pyc,,
|
31 |
+
mpmath/calculus/approximation.py,sha256=vyzu3YI6r63Oq1KFHrQz02mGXAcH23emqNYhJuUaFZ4,8817
|
32 |
+
mpmath/calculus/calculus.py,sha256=A0gSp0hxSyEDfugJViY3CeWalF-vK701YftzrjSQzQ4,112
|
33 |
+
mpmath/calculus/differentiation.py,sha256=2L6CBj8xtX9iip98NPbKsLtwtRjxi571wYmTMHFeL90,20226
|
34 |
+
mpmath/calculus/extrapolation.py,sha256=xM0rvk2DFEF4iR1Jhl-Y3aS93iW9VVJX7y9IGpmzC-A,73306
|
35 |
+
mpmath/calculus/inverselaplace.py,sha256=5-pn8N_t0PtgBTXixsXZ4xxrihK2J5gYsVfTKfDx4gA,36056
|
36 |
+
mpmath/calculus/odes.py,sha256=gaHiw7IJjsONNTAa6izFPZpmcg9uyTp8MULnGdzTIGo,9908
|
37 |
+
mpmath/calculus/optimization.py,sha256=bKnShXElBOmVOIOlFeksDsYCp9fYSmYwKmXDt0z26MM,32856
|
38 |
+
mpmath/calculus/polynomials.py,sha256=D16BhU_SHbVi06IxNwABHR-H77IylndNsN3muPTuFYs,7877
|
39 |
+
mpmath/calculus/quadrature.py,sha256=n-avtS8E43foV-5tr5lofgOBaiMUYE8AJjQcWI9QcKk,42432
|
40 |
+
mpmath/ctx_base.py,sha256=rfjmfMyA55x8R_cWFINUwWVTElfZmyx5erKDdauSEVw,15985
|
41 |
+
mpmath/ctx_fp.py,sha256=ctUjx_NoU0iFWk05cXDYCL2ZtLZOlWs1n6Zao3pbG2g,6572
|
42 |
+
mpmath/ctx_iv.py,sha256=tqdMr-GDfkZk1EhoGeCAajy7pQv-RWtrVqhYjfI8r4g,17211
|
43 |
+
mpmath/ctx_mp.py,sha256=d3r4t7xHNqSFtmqsA9Btq1Npy3WTM-pcM2_jeCyECxY,49452
|
44 |
+
mpmath/ctx_mp_python.py,sha256=3olYWo4lk1SnQ0A_IaZ181qqG8u5pxGat_v-L4Qtn3Y,37815
|
45 |
+
mpmath/function_docs.py,sha256=g4PP8n6ILXmHcLyA50sxK6Tmp_Z4_pRN-wDErU8D1i4,283512
|
46 |
+
mpmath/functions/__init__.py,sha256=YXVdhqv-6LKm6cr5xxtTNTtuD9zDPKGQl8GmS0xz2xo,330
|
47 |
+
mpmath/functions/__pycache__/__init__.cpython-39.pyc,,
|
48 |
+
mpmath/functions/__pycache__/bessel.cpython-39.pyc,,
|
49 |
+
mpmath/functions/__pycache__/elliptic.cpython-39.pyc,,
|
50 |
+
mpmath/functions/__pycache__/expintegrals.cpython-39.pyc,,
|
51 |
+
mpmath/functions/__pycache__/factorials.cpython-39.pyc,,
|
52 |
+
mpmath/functions/__pycache__/functions.cpython-39.pyc,,
|
53 |
+
mpmath/functions/__pycache__/hypergeometric.cpython-39.pyc,,
|
54 |
+
mpmath/functions/__pycache__/orthogonal.cpython-39.pyc,,
|
55 |
+
mpmath/functions/__pycache__/qfunctions.cpython-39.pyc,,
|
56 |
+
mpmath/functions/__pycache__/rszeta.cpython-39.pyc,,
|
57 |
+
mpmath/functions/__pycache__/signals.cpython-39.pyc,,
|
58 |
+
mpmath/functions/__pycache__/theta.cpython-39.pyc,,
|
59 |
+
mpmath/functions/__pycache__/zeta.cpython-39.pyc,,
|
60 |
+
mpmath/functions/__pycache__/zetazeros.cpython-39.pyc,,
|
61 |
+
mpmath/functions/bessel.py,sha256=dUPLu8frlK-vmf3-irX_7uvwyw4xccv6EIizmIZ88kM,37938
|
62 |
+
mpmath/functions/elliptic.py,sha256=qz0yVMb4lWEeOTDL_DWz5u5awmGIPKAsuZFJXgwHJNU,42237
|
63 |
+
mpmath/functions/expintegrals.py,sha256=75X_MRdYc1F_X73bgNiOJqwRlS2hqAzcFLl3RM2tCDc,11644
|
64 |
+
mpmath/functions/factorials.py,sha256=8_6kCR7e4k1GwxiAOJu0NRadeF4jA28qx4hidhu4ILk,5273
|
65 |
+
mpmath/functions/functions.py,sha256=ub2JExvqzCWLkm5yAm72Fr6fdWmZZUknq9_3w9MEigI,18100
|
66 |
+
mpmath/functions/hypergeometric.py,sha256=Z0OMAMC4ylK42n_SnamyFVnUx6zHLyCLCoJDSZ1JrHY,51570
|
67 |
+
mpmath/functions/orthogonal.py,sha256=FabkxKfBoSseA5flWu1a3re-2BYaew9augqIsT8LaLw,16097
|
68 |
+
mpmath/functions/qfunctions.py,sha256=a3EHGKQt_jMd4x9I772Jz-TGFnGY-arWqPvZGz9QSe0,7633
|
69 |
+
mpmath/functions/rszeta.py,sha256=yuUVp4ilIyDmXyE3WTBxDDjwfEJNypJnbPS-xPH5How,46184
|
70 |
+
mpmath/functions/signals.py,sha256=ELotwQaW1CDpv-eeJzOZ5c23NhfaZcj9_Gkb3psvS0Q,703
|
71 |
+
mpmath/functions/theta.py,sha256=KggOocczoMG6_HMoal4oEP7iZ4SKOou9JFE-WzY2r3M,37320
|
72 |
+
mpmath/functions/zeta.py,sha256=ue7JY7GXA0oX8q08sQJl2CSRrZ7kOt8HsftpVjnTwrE,36410
|
73 |
+
mpmath/functions/zetazeros.py,sha256=uq6TVyZBcY2MLX7VSdVfn0TOkowBLM9fXtnySEwaNzw,30858
|
74 |
+
mpmath/identification.py,sha256=7aMdngRAaeL_MafDUNbmEIlGQSklHDZ8pmPFt-OLgkw,29253
|
75 |
+
mpmath/libmp/__init__.py,sha256=UCDjLZw4brbklaCmSixCcPdLdHkz8sF_-6F_wr0duAg,3790
|
76 |
+
mpmath/libmp/__pycache__/__init__.cpython-39.pyc,,
|
77 |
+
mpmath/libmp/__pycache__/backend.cpython-39.pyc,,
|
78 |
+
mpmath/libmp/__pycache__/gammazeta.cpython-39.pyc,,
|
79 |
+
mpmath/libmp/__pycache__/libelefun.cpython-39.pyc,,
|
80 |
+
mpmath/libmp/__pycache__/libhyper.cpython-39.pyc,,
|
81 |
+
mpmath/libmp/__pycache__/libintmath.cpython-39.pyc,,
|
82 |
+
mpmath/libmp/__pycache__/libmpc.cpython-39.pyc,,
|
83 |
+
mpmath/libmp/__pycache__/libmpf.cpython-39.pyc,,
|
84 |
+
mpmath/libmp/__pycache__/libmpi.cpython-39.pyc,,
|
85 |
+
mpmath/libmp/backend.py,sha256=26A8pUkaGov26vrrFNQVyWJ5LDtK8sl3UHrYLecaTjA,3360
|
86 |
+
mpmath/libmp/gammazeta.py,sha256=Xqdw6PMoswDaSca_sOs-IglRuk3fb8c9p43M_lbcrlc,71469
|
87 |
+
mpmath/libmp/libelefun.py,sha256=joBZP4FOdxPfieWso1LPtSr6dHydpG_LQiF_bYQYWMg,43861
|
88 |
+
mpmath/libmp/libhyper.py,sha256=J9fmdDF6u27EcssEWvBuVaAa3hFjPvPN1SgRgu1dEbc,36624
|
89 |
+
mpmath/libmp/libintmath.py,sha256=aIRT0rkUZ_sdGQf3TNCLd-pBMvtQWjssbvFLfK7U0jc,16688
|
90 |
+
mpmath/libmp/libmpc.py,sha256=KBndUjs5YVS32-Id3fflDfYgpdW1Prx6zfo8Ez5Qbrs,26875
|
91 |
+
mpmath/libmp/libmpf.py,sha256=vpP0kNVkScbCVoZogJ4Watl4I7Ce0d4dzHVjfVe57so,45021
|
92 |
+
mpmath/libmp/libmpi.py,sha256=u0I5Eiwkqa-4-dXETi5k7MuaxBeZbvCAPFtl93U9YF0,27622
|
93 |
+
mpmath/math2.py,sha256=O5Dglg81SsW0wfHDUJcXOD8-cCaLvbVIvyw0sVmRbpI,18561
|
94 |
+
mpmath/matrices/__init__.py,sha256=ETzGDciYbq9ftiKwaMbJ15EI-KNXHrzRb-ZHehhqFjs,94
|
95 |
+
mpmath/matrices/__pycache__/__init__.cpython-39.pyc,,
|
96 |
+
mpmath/matrices/__pycache__/calculus.cpython-39.pyc,,
|
97 |
+
mpmath/matrices/__pycache__/eigen.cpython-39.pyc,,
|
98 |
+
mpmath/matrices/__pycache__/eigen_symmetric.cpython-39.pyc,,
|
99 |
+
mpmath/matrices/__pycache__/linalg.cpython-39.pyc,,
|
100 |
+
mpmath/matrices/__pycache__/matrices.cpython-39.pyc,,
|
101 |
+
mpmath/matrices/calculus.py,sha256=PNRq-p2nxgT-fzC54K2depi8ddhdx6Q86G8qpUiHeUY,18609
|
102 |
+
mpmath/matrices/eigen.py,sha256=GbDXI3CixzEdXxr1G86uUWkAngAvd-05MmSQ-Tsu_5k,24394
|
103 |
+
mpmath/matrices/eigen_symmetric.py,sha256=FPKPeQr1cGYw6Y6ea32a1YdEWQDLP6JlQHEA2WfNLYg,58534
|
104 |
+
mpmath/matrices/linalg.py,sha256=04C3ijzMFom7ob5fXBCDfyPPdo3BIboIeE8x2A6vqF0,26958
|
105 |
+
mpmath/matrices/matrices.py,sha256=o78Eq62EHQnxcsR0LBoWDEGREOoN4L2iDM1q3dQrw0o,32331
|
106 |
+
mpmath/rational.py,sha256=64d56fvZXngYZT7nOAHeFRUX77eJ1A0R3rpfWBU-mSo,5976
|
107 |
+
mpmath/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
108 |
+
mpmath/tests/__pycache__/__init__.cpython-39.pyc,,
|
109 |
+
mpmath/tests/__pycache__/extratest_gamma.cpython-39.pyc,,
|
110 |
+
mpmath/tests/__pycache__/extratest_zeta.cpython-39.pyc,,
|
111 |
+
mpmath/tests/__pycache__/runtests.cpython-39.pyc,,
|
112 |
+
mpmath/tests/__pycache__/test_basic_ops.cpython-39.pyc,,
|
113 |
+
mpmath/tests/__pycache__/test_bitwise.cpython-39.pyc,,
|
114 |
+
mpmath/tests/__pycache__/test_calculus.cpython-39.pyc,,
|
115 |
+
mpmath/tests/__pycache__/test_compatibility.cpython-39.pyc,,
|
116 |
+
mpmath/tests/__pycache__/test_convert.cpython-39.pyc,,
|
117 |
+
mpmath/tests/__pycache__/test_diff.cpython-39.pyc,,
|
118 |
+
mpmath/tests/__pycache__/test_division.cpython-39.pyc,,
|
119 |
+
mpmath/tests/__pycache__/test_eigen.cpython-39.pyc,,
|
120 |
+
mpmath/tests/__pycache__/test_eigen_symmetric.cpython-39.pyc,,
|
121 |
+
mpmath/tests/__pycache__/test_elliptic.cpython-39.pyc,,
|
122 |
+
mpmath/tests/__pycache__/test_fp.cpython-39.pyc,,
|
123 |
+
mpmath/tests/__pycache__/test_functions.cpython-39.pyc,,
|
124 |
+
mpmath/tests/__pycache__/test_functions2.cpython-39.pyc,,
|
125 |
+
mpmath/tests/__pycache__/test_gammazeta.cpython-39.pyc,,
|
126 |
+
mpmath/tests/__pycache__/test_hp.cpython-39.pyc,,
|
127 |
+
mpmath/tests/__pycache__/test_identify.cpython-39.pyc,,
|
128 |
+
mpmath/tests/__pycache__/test_interval.cpython-39.pyc,,
|
129 |
+
mpmath/tests/__pycache__/test_levin.cpython-39.pyc,,
|
130 |
+
mpmath/tests/__pycache__/test_linalg.cpython-39.pyc,,
|
131 |
+
mpmath/tests/__pycache__/test_matrices.cpython-39.pyc,,
|
132 |
+
mpmath/tests/__pycache__/test_mpmath.cpython-39.pyc,,
|
133 |
+
mpmath/tests/__pycache__/test_ode.cpython-39.pyc,,
|
134 |
+
mpmath/tests/__pycache__/test_pickle.cpython-39.pyc,,
|
135 |
+
mpmath/tests/__pycache__/test_power.cpython-39.pyc,,
|
136 |
+
mpmath/tests/__pycache__/test_quad.cpython-39.pyc,,
|
137 |
+
mpmath/tests/__pycache__/test_rootfinding.cpython-39.pyc,,
|
138 |
+
mpmath/tests/__pycache__/test_special.cpython-39.pyc,,
|
139 |
+
mpmath/tests/__pycache__/test_str.cpython-39.pyc,,
|
140 |
+
mpmath/tests/__pycache__/test_summation.cpython-39.pyc,,
|
141 |
+
mpmath/tests/__pycache__/test_trig.cpython-39.pyc,,
|
142 |
+
mpmath/tests/__pycache__/test_visualization.cpython-39.pyc,,
|
143 |
+
mpmath/tests/__pycache__/torture.cpython-39.pyc,,
|
144 |
+
mpmath/tests/extratest_gamma.py,sha256=xidhXUelILcxtiPGoTBHjqUOKIJzEaZ_v3nntGQyWZQ,7228
|
145 |
+
mpmath/tests/extratest_zeta.py,sha256=sg10j9RhjBpV2EdUqyYhGV2ERWvM--EvwwGIz6HTmlw,1003
|
146 |
+
mpmath/tests/runtests.py,sha256=7NUV82F3K_5AhU8mCLUFf5OibtT7uloFCwPyM3l71wM,5189
|
147 |
+
mpmath/tests/test_basic_ops.py,sha256=dsB8DRG-GrPzBaZ-bIauYabaeqXbfqBo9SIP9BqcTSs,15348
|
148 |
+
mpmath/tests/test_bitwise.py,sha256=-nLYhgQbhDza3SQM63BhktYntACagqMYx9ib3dPnTKM,7686
|
149 |
+
mpmath/tests/test_calculus.py,sha256=4oxtNfMpO4RLLoOzrv7r9-h8BcqfBsJIE6UpsHe7c4w,9187
|
150 |
+
mpmath/tests/test_compatibility.py,sha256=_t3ASZ3jhfAMnN1voWX7PDNIDzn-3PokkJGIdT1x7y0,2306
|
151 |
+
mpmath/tests/test_convert.py,sha256=JPcDcTJIWh5prIxjx5DM1aNWgqlUoF2KpHvAgK3uHi4,8834
|
152 |
+
mpmath/tests/test_diff.py,sha256=qjiF8NxQ8vueuZ5ZHGPQ-kjcj_I7Jh_fEdFtaA8DzEI,2466
|
153 |
+
mpmath/tests/test_division.py,sha256=6lUeZfmaBWvvszdqlWLMHgXPjVsxvW1WZpd4-jFWCpU,5340
|
154 |
+
mpmath/tests/test_eigen.py,sha256=2mnqVATGbsJkvSVHPpitfAk881twFfb3LsO3XikV9Hs,3905
|
155 |
+
mpmath/tests/test_eigen_symmetric.py,sha256=v0VimCicIU2owASDMBaP-t-30uq-pXcsglt95KBtNO4,8778
|
156 |
+
mpmath/tests/test_elliptic.py,sha256=Kjiwq9Bb6N_OOzzWewGQ1M_PMa7vRs42V0t90gloZxo,26225
|
157 |
+
mpmath/tests/test_fp.py,sha256=AJo0FTyH4BuUnUsv176LD956om308KGYndy-b54KGxM,89997
|
158 |
+
mpmath/tests/test_functions.py,sha256=b47VywdomoOX6KmMmz9-iv2IqVIydwKSuUw2pWlFHrY,30955
|
159 |
+
mpmath/tests/test_functions2.py,sha256=vlw2RWhL1oTcifnOMDx1a_YzN96UgNNIE5STeKRv1HY,96990
|
160 |
+
mpmath/tests/test_gammazeta.py,sha256=AB34O0DV7AlEf9Z4brnCadeQU5-uAwhWRw5FZas65DA,27917
|
161 |
+
mpmath/tests/test_hp.py,sha256=6hcENu6Te2klPEiTSeLBIRPlH7PADlJwFKbx8xpnOhg,10461
|
162 |
+
mpmath/tests/test_identify.py,sha256=lGUIPfrB2paTg0cFUo64GmMzF77F9gs9FQjX7gxGHV8,692
|
163 |
+
mpmath/tests/test_interval.py,sha256=TjYd7a9ca6iRJiLjw06isLeZTuGoGAPmgleDZ0cYfJ0,17527
|
164 |
+
mpmath/tests/test_levin.py,sha256=P8M11yV1dj_gdSNv5xuwCzFiF86QyRDtPMjURy6wJ28,5090
|
165 |
+
mpmath/tests/test_linalg.py,sha256=miKEnwB8iwWV13hi1bF1cg3hgB4rTKOR0fvDVfWmXds,10440
|
166 |
+
mpmath/tests/test_matrices.py,sha256=qyA4Ml2CvNvW034lzB01G6wVgNr7UrgZqh2wkMXtpzM,7944
|
167 |
+
mpmath/tests/test_mpmath.py,sha256=LVyJUeofiaxW-zLKWVBCz59L9UQsjlW0Ts9_oBiEv_4,196
|
168 |
+
mpmath/tests/test_ode.py,sha256=zAxexBH4fnmFNO4bvEHbug1NJWC5zqfFaVDlYijowkY,1822
|
169 |
+
mpmath/tests/test_pickle.py,sha256=Y8CKmDLFsJHUqG8CDaBw5ilrPP4YT1xijVduLpQ7XFE,401
|
170 |
+
mpmath/tests/test_power.py,sha256=sz_K02SmNxpa6Kb1uJLN_N4tXTJGdQ___vPRshEN7Gk,5227
|
171 |
+
mpmath/tests/test_quad.py,sha256=49Ltft0vZ_kdKLL5s-Kj-BzAVoF5LPVEUeNUzdOkghI,3893
|
172 |
+
mpmath/tests/test_rootfinding.py,sha256=umQegEaKHmYOEl5jEyoD-VLKDtXsTJJkepKEr4c0dC0,3132
|
173 |
+
mpmath/tests/test_special.py,sha256=YbMIoMIkJEvvKYIzS0CXthJFG0--j6un7-tcE6b7FPM,2848
|
174 |
+
mpmath/tests/test_str.py,sha256=0WsGD9hMPRi8zcuYMA9Cu2mOvQiCFskPwMsMf8lBDK4,544
|
175 |
+
mpmath/tests/test_summation.py,sha256=fdNlsvRVOsbWxbhlyDLDaEO2S8kTJrRMKIvB5-aNci0,2035
|
176 |
+
mpmath/tests/test_trig.py,sha256=zPtkIEnZaThxcWur4k7BX8-2Jmj-AhO191Svv7ANYUU,4799
|
177 |
+
mpmath/tests/test_visualization.py,sha256=1PqtkoUx-WsKYgTRiu5o9pBc85kwhf1lzU2eobDQCJM,944
|
178 |
+
mpmath/tests/torture.py,sha256=LD95oES7JY2KroELK-m-jhvtbvZaKChnt0Cq7kFMNCw,7868
|
179 |
+
mpmath/usertools.py,sha256=a-TDw7XSRsPdBEffxOooDV4WDFfuXnO58P75dcAD87I,3029
|
180 |
+
mpmath/visualization.py,sha256=pnnbjcd9AhFVRBZavYX5gjx4ytK_kXoDDisYR6EpXhs,10627
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: bdist_wheel (0.38.4)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
MLPY/Lib/site-packages/mpmath-1.3.0.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
mpmath
|
MLPY/Lib/site-packages/mpmath/__init__.py
ADDED
@@ -0,0 +1,468 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
__version__ = '1.3.0'
|
2 |
+
|
3 |
+
from .usertools import monitor, timing
|
4 |
+
|
5 |
+
from .ctx_fp import FPContext
|
6 |
+
from .ctx_mp import MPContext
|
7 |
+
from .ctx_iv import MPIntervalContext
|
8 |
+
|
9 |
+
fp = FPContext()
|
10 |
+
mp = MPContext()
|
11 |
+
iv = MPIntervalContext()
|
12 |
+
|
13 |
+
fp._mp = mp
|
14 |
+
mp._mp = mp
|
15 |
+
iv._mp = mp
|
16 |
+
mp._fp = fp
|
17 |
+
fp._fp = fp
|
18 |
+
mp._iv = iv
|
19 |
+
fp._iv = iv
|
20 |
+
iv._iv = iv
|
21 |
+
|
22 |
+
# XXX: extremely bad pickle hack
|
23 |
+
from . import ctx_mp as _ctx_mp
|
24 |
+
_ctx_mp._mpf_module.mpf = mp.mpf
|
25 |
+
_ctx_mp._mpf_module.mpc = mp.mpc
|
26 |
+
|
27 |
+
make_mpf = mp.make_mpf
|
28 |
+
make_mpc = mp.make_mpc
|
29 |
+
|
30 |
+
extraprec = mp.extraprec
|
31 |
+
extradps = mp.extradps
|
32 |
+
workprec = mp.workprec
|
33 |
+
workdps = mp.workdps
|
34 |
+
autoprec = mp.autoprec
|
35 |
+
maxcalls = mp.maxcalls
|
36 |
+
memoize = mp.memoize
|
37 |
+
|
38 |
+
mag = mp.mag
|
39 |
+
|
40 |
+
bernfrac = mp.bernfrac
|
41 |
+
|
42 |
+
qfrom = mp.qfrom
|
43 |
+
mfrom = mp.mfrom
|
44 |
+
kfrom = mp.kfrom
|
45 |
+
taufrom = mp.taufrom
|
46 |
+
qbarfrom = mp.qbarfrom
|
47 |
+
ellipfun = mp.ellipfun
|
48 |
+
jtheta = mp.jtheta
|
49 |
+
kleinj = mp.kleinj
|
50 |
+
eta = mp.eta
|
51 |
+
|
52 |
+
qp = mp.qp
|
53 |
+
qhyper = mp.qhyper
|
54 |
+
qgamma = mp.qgamma
|
55 |
+
qfac = mp.qfac
|
56 |
+
|
57 |
+
nint_distance = mp.nint_distance
|
58 |
+
|
59 |
+
plot = mp.plot
|
60 |
+
cplot = mp.cplot
|
61 |
+
splot = mp.splot
|
62 |
+
|
63 |
+
odefun = mp.odefun
|
64 |
+
|
65 |
+
jacobian = mp.jacobian
|
66 |
+
findroot = mp.findroot
|
67 |
+
multiplicity = mp.multiplicity
|
68 |
+
|
69 |
+
isinf = mp.isinf
|
70 |
+
isnan = mp.isnan
|
71 |
+
isnormal = mp.isnormal
|
72 |
+
isint = mp.isint
|
73 |
+
isfinite = mp.isfinite
|
74 |
+
almosteq = mp.almosteq
|
75 |
+
nan = mp.nan
|
76 |
+
rand = mp.rand
|
77 |
+
|
78 |
+
absmin = mp.absmin
|
79 |
+
absmax = mp.absmax
|
80 |
+
|
81 |
+
fraction = mp.fraction
|
82 |
+
|
83 |
+
linspace = mp.linspace
|
84 |
+
arange = mp.arange
|
85 |
+
|
86 |
+
mpmathify = convert = mp.convert
|
87 |
+
mpc = mp.mpc
|
88 |
+
|
89 |
+
mpi = iv._mpi
|
90 |
+
|
91 |
+
nstr = mp.nstr
|
92 |
+
nprint = mp.nprint
|
93 |
+
chop = mp.chop
|
94 |
+
|
95 |
+
fneg = mp.fneg
|
96 |
+
fadd = mp.fadd
|
97 |
+
fsub = mp.fsub
|
98 |
+
fmul = mp.fmul
|
99 |
+
fdiv = mp.fdiv
|
100 |
+
fprod = mp.fprod
|
101 |
+
|
102 |
+
quad = mp.quad
|
103 |
+
quadgl = mp.quadgl
|
104 |
+
quadts = mp.quadts
|
105 |
+
quadosc = mp.quadosc
|
106 |
+
quadsubdiv = mp.quadsubdiv
|
107 |
+
|
108 |
+
invertlaplace = mp.invertlaplace
|
109 |
+
invlaptalbot = mp.invlaptalbot
|
110 |
+
invlapstehfest = mp.invlapstehfest
|
111 |
+
invlapdehoog = mp.invlapdehoog
|
112 |
+
|
113 |
+
pslq = mp.pslq
|
114 |
+
identify = mp.identify
|
115 |
+
findpoly = mp.findpoly
|
116 |
+
|
117 |
+
richardson = mp.richardson
|
118 |
+
shanks = mp.shanks
|
119 |
+
levin = mp.levin
|
120 |
+
cohen_alt = mp.cohen_alt
|
121 |
+
nsum = mp.nsum
|
122 |
+
nprod = mp.nprod
|
123 |
+
difference = mp.difference
|
124 |
+
diff = mp.diff
|
125 |
+
diffs = mp.diffs
|
126 |
+
diffs_prod = mp.diffs_prod
|
127 |
+
diffs_exp = mp.diffs_exp
|
128 |
+
diffun = mp.diffun
|
129 |
+
differint = mp.differint
|
130 |
+
taylor = mp.taylor
|
131 |
+
pade = mp.pade
|
132 |
+
polyval = mp.polyval
|
133 |
+
polyroots = mp.polyroots
|
134 |
+
fourier = mp.fourier
|
135 |
+
fourierval = mp.fourierval
|
136 |
+
sumem = mp.sumem
|
137 |
+
sumap = mp.sumap
|
138 |
+
chebyfit = mp.chebyfit
|
139 |
+
limit = mp.limit
|
140 |
+
|
141 |
+
matrix = mp.matrix
|
142 |
+
eye = mp.eye
|
143 |
+
diag = mp.diag
|
144 |
+
zeros = mp.zeros
|
145 |
+
ones = mp.ones
|
146 |
+
hilbert = mp.hilbert
|
147 |
+
randmatrix = mp.randmatrix
|
148 |
+
swap_row = mp.swap_row
|
149 |
+
extend = mp.extend
|
150 |
+
norm = mp.norm
|
151 |
+
mnorm = mp.mnorm
|
152 |
+
|
153 |
+
lu_solve = mp.lu_solve
|
154 |
+
lu = mp.lu
|
155 |
+
qr = mp.qr
|
156 |
+
unitvector = mp.unitvector
|
157 |
+
inverse = mp.inverse
|
158 |
+
residual = mp.residual
|
159 |
+
qr_solve = mp.qr_solve
|
160 |
+
cholesky = mp.cholesky
|
161 |
+
cholesky_solve = mp.cholesky_solve
|
162 |
+
det = mp.det
|
163 |
+
cond = mp.cond
|
164 |
+
hessenberg = mp.hessenberg
|
165 |
+
schur = mp.schur
|
166 |
+
eig = mp.eig
|
167 |
+
eig_sort = mp.eig_sort
|
168 |
+
eigsy = mp.eigsy
|
169 |
+
eighe = mp.eighe
|
170 |
+
eigh = mp.eigh
|
171 |
+
svd_r = mp.svd_r
|
172 |
+
svd_c = mp.svd_c
|
173 |
+
svd = mp.svd
|
174 |
+
gauss_quadrature = mp.gauss_quadrature
|
175 |
+
|
176 |
+
expm = mp.expm
|
177 |
+
sqrtm = mp.sqrtm
|
178 |
+
powm = mp.powm
|
179 |
+
logm = mp.logm
|
180 |
+
sinm = mp.sinm
|
181 |
+
cosm = mp.cosm
|
182 |
+
|
183 |
+
mpf = mp.mpf
|
184 |
+
j = mp.j
|
185 |
+
exp = mp.exp
|
186 |
+
expj = mp.expj
|
187 |
+
expjpi = mp.expjpi
|
188 |
+
ln = mp.ln
|
189 |
+
im = mp.im
|
190 |
+
re = mp.re
|
191 |
+
inf = mp.inf
|
192 |
+
ninf = mp.ninf
|
193 |
+
sign = mp.sign
|
194 |
+
|
195 |
+
eps = mp.eps
|
196 |
+
pi = mp.pi
|
197 |
+
ln2 = mp.ln2
|
198 |
+
ln10 = mp.ln10
|
199 |
+
phi = mp.phi
|
200 |
+
e = mp.e
|
201 |
+
euler = mp.euler
|
202 |
+
catalan = mp.catalan
|
203 |
+
khinchin = mp.khinchin
|
204 |
+
glaisher = mp.glaisher
|
205 |
+
apery = mp.apery
|
206 |
+
degree = mp.degree
|
207 |
+
twinprime = mp.twinprime
|
208 |
+
mertens = mp.mertens
|
209 |
+
|
210 |
+
ldexp = mp.ldexp
|
211 |
+
frexp = mp.frexp
|
212 |
+
|
213 |
+
fsum = mp.fsum
|
214 |
+
fdot = mp.fdot
|
215 |
+
|
216 |
+
sqrt = mp.sqrt
|
217 |
+
cbrt = mp.cbrt
|
218 |
+
exp = mp.exp
|
219 |
+
ln = mp.ln
|
220 |
+
log = mp.log
|
221 |
+
log10 = mp.log10
|
222 |
+
power = mp.power
|
223 |
+
cos = mp.cos
|
224 |
+
sin = mp.sin
|
225 |
+
tan = mp.tan
|
226 |
+
cosh = mp.cosh
|
227 |
+
sinh = mp.sinh
|
228 |
+
tanh = mp.tanh
|
229 |
+
acos = mp.acos
|
230 |
+
asin = mp.asin
|
231 |
+
atan = mp.atan
|
232 |
+
asinh = mp.asinh
|
233 |
+
acosh = mp.acosh
|
234 |
+
atanh = mp.atanh
|
235 |
+
sec = mp.sec
|
236 |
+
csc = mp.csc
|
237 |
+
cot = mp.cot
|
238 |
+
sech = mp.sech
|
239 |
+
csch = mp.csch
|
240 |
+
coth = mp.coth
|
241 |
+
asec = mp.asec
|
242 |
+
acsc = mp.acsc
|
243 |
+
acot = mp.acot
|
244 |
+
asech = mp.asech
|
245 |
+
acsch = mp.acsch
|
246 |
+
acoth = mp.acoth
|
247 |
+
cospi = mp.cospi
|
248 |
+
sinpi = mp.sinpi
|
249 |
+
sinc = mp.sinc
|
250 |
+
sincpi = mp.sincpi
|
251 |
+
cos_sin = mp.cos_sin
|
252 |
+
cospi_sinpi = mp.cospi_sinpi
|
253 |
+
fabs = mp.fabs
|
254 |
+
re = mp.re
|
255 |
+
im = mp.im
|
256 |
+
conj = mp.conj
|
257 |
+
floor = mp.floor
|
258 |
+
ceil = mp.ceil
|
259 |
+
nint = mp.nint
|
260 |
+
frac = mp.frac
|
261 |
+
root = mp.root
|
262 |
+
nthroot = mp.nthroot
|
263 |
+
hypot = mp.hypot
|
264 |
+
fmod = mp.fmod
|
265 |
+
ldexp = mp.ldexp
|
266 |
+
frexp = mp.frexp
|
267 |
+
sign = mp.sign
|
268 |
+
arg = mp.arg
|
269 |
+
phase = mp.phase
|
270 |
+
polar = mp.polar
|
271 |
+
rect = mp.rect
|
272 |
+
degrees = mp.degrees
|
273 |
+
radians = mp.radians
|
274 |
+
atan2 = mp.atan2
|
275 |
+
fib = mp.fib
|
276 |
+
fibonacci = mp.fibonacci
|
277 |
+
lambertw = mp.lambertw
|
278 |
+
zeta = mp.zeta
|
279 |
+
altzeta = mp.altzeta
|
280 |
+
gamma = mp.gamma
|
281 |
+
rgamma = mp.rgamma
|
282 |
+
factorial = mp.factorial
|
283 |
+
fac = mp.fac
|
284 |
+
fac2 = mp.fac2
|
285 |
+
beta = mp.beta
|
286 |
+
betainc = mp.betainc
|
287 |
+
psi = mp.psi
|
288 |
+
#psi0 = mp.psi0
|
289 |
+
#psi1 = mp.psi1
|
290 |
+
#psi2 = mp.psi2
|
291 |
+
#psi3 = mp.psi3
|
292 |
+
polygamma = mp.polygamma
|
293 |
+
digamma = mp.digamma
|
294 |
+
#trigamma = mp.trigamma
|
295 |
+
#tetragamma = mp.tetragamma
|
296 |
+
#pentagamma = mp.pentagamma
|
297 |
+
harmonic = mp.harmonic
|
298 |
+
bernoulli = mp.bernoulli
|
299 |
+
bernfrac = mp.bernfrac
|
300 |
+
stieltjes = mp.stieltjes
|
301 |
+
hurwitz = mp.hurwitz
|
302 |
+
dirichlet = mp.dirichlet
|
303 |
+
bernpoly = mp.bernpoly
|
304 |
+
eulerpoly = mp.eulerpoly
|
305 |
+
eulernum = mp.eulernum
|
306 |
+
polylog = mp.polylog
|
307 |
+
clsin = mp.clsin
|
308 |
+
clcos = mp.clcos
|
309 |
+
gammainc = mp.gammainc
|
310 |
+
gammaprod = mp.gammaprod
|
311 |
+
binomial = mp.binomial
|
312 |
+
rf = mp.rf
|
313 |
+
ff = mp.ff
|
314 |
+
hyper = mp.hyper
|
315 |
+
hyp0f1 = mp.hyp0f1
|
316 |
+
hyp1f1 = mp.hyp1f1
|
317 |
+
hyp1f2 = mp.hyp1f2
|
318 |
+
hyp2f1 = mp.hyp2f1
|
319 |
+
hyp2f2 = mp.hyp2f2
|
320 |
+
hyp2f0 = mp.hyp2f0
|
321 |
+
hyp2f3 = mp.hyp2f3
|
322 |
+
hyp3f2 = mp.hyp3f2
|
323 |
+
hyperu = mp.hyperu
|
324 |
+
hypercomb = mp.hypercomb
|
325 |
+
meijerg = mp.meijerg
|
326 |
+
appellf1 = mp.appellf1
|
327 |
+
appellf2 = mp.appellf2
|
328 |
+
appellf3 = mp.appellf3
|
329 |
+
appellf4 = mp.appellf4
|
330 |
+
hyper2d = mp.hyper2d
|
331 |
+
bihyper = mp.bihyper
|
332 |
+
erf = mp.erf
|
333 |
+
erfc = mp.erfc
|
334 |
+
erfi = mp.erfi
|
335 |
+
erfinv = mp.erfinv
|
336 |
+
npdf = mp.npdf
|
337 |
+
ncdf = mp.ncdf
|
338 |
+
expint = mp.expint
|
339 |
+
e1 = mp.e1
|
340 |
+
ei = mp.ei
|
341 |
+
li = mp.li
|
342 |
+
ci = mp.ci
|
343 |
+
si = mp.si
|
344 |
+
chi = mp.chi
|
345 |
+
shi = mp.shi
|
346 |
+
fresnels = mp.fresnels
|
347 |
+
fresnelc = mp.fresnelc
|
348 |
+
airyai = mp.airyai
|
349 |
+
airybi = mp.airybi
|
350 |
+
airyaizero = mp.airyaizero
|
351 |
+
airybizero = mp.airybizero
|
352 |
+
scorergi = mp.scorergi
|
353 |
+
scorerhi = mp.scorerhi
|
354 |
+
ellipk = mp.ellipk
|
355 |
+
ellipe = mp.ellipe
|
356 |
+
ellipf = mp.ellipf
|
357 |
+
ellippi = mp.ellippi
|
358 |
+
elliprc = mp.elliprc
|
359 |
+
elliprj = mp.elliprj
|
360 |
+
elliprf = mp.elliprf
|
361 |
+
elliprd = mp.elliprd
|
362 |
+
elliprg = mp.elliprg
|
363 |
+
agm = mp.agm
|
364 |
+
jacobi = mp.jacobi
|
365 |
+
chebyt = mp.chebyt
|
366 |
+
chebyu = mp.chebyu
|
367 |
+
legendre = mp.legendre
|
368 |
+
legenp = mp.legenp
|
369 |
+
legenq = mp.legenq
|
370 |
+
hermite = mp.hermite
|
371 |
+
pcfd = mp.pcfd
|
372 |
+
pcfu = mp.pcfu
|
373 |
+
pcfv = mp.pcfv
|
374 |
+
pcfw = mp.pcfw
|
375 |
+
gegenbauer = mp.gegenbauer
|
376 |
+
laguerre = mp.laguerre
|
377 |
+
spherharm = mp.spherharm
|
378 |
+
besselj = mp.besselj
|
379 |
+
j0 = mp.j0
|
380 |
+
j1 = mp.j1
|
381 |
+
besseli = mp.besseli
|
382 |
+
bessely = mp.bessely
|
383 |
+
besselk = mp.besselk
|
384 |
+
besseljzero = mp.besseljzero
|
385 |
+
besselyzero = mp.besselyzero
|
386 |
+
hankel1 = mp.hankel1
|
387 |
+
hankel2 = mp.hankel2
|
388 |
+
struveh = mp.struveh
|
389 |
+
struvel = mp.struvel
|
390 |
+
angerj = mp.angerj
|
391 |
+
webere = mp.webere
|
392 |
+
lommels1 = mp.lommels1
|
393 |
+
lommels2 = mp.lommels2
|
394 |
+
whitm = mp.whitm
|
395 |
+
whitw = mp.whitw
|
396 |
+
ber = mp.ber
|
397 |
+
bei = mp.bei
|
398 |
+
ker = mp.ker
|
399 |
+
kei = mp.kei
|
400 |
+
coulombc = mp.coulombc
|
401 |
+
coulombf = mp.coulombf
|
402 |
+
coulombg = mp.coulombg
|
403 |
+
barnesg = mp.barnesg
|
404 |
+
superfac = mp.superfac
|
405 |
+
hyperfac = mp.hyperfac
|
406 |
+
loggamma = mp.loggamma
|
407 |
+
siegeltheta = mp.siegeltheta
|
408 |
+
siegelz = mp.siegelz
|
409 |
+
grampoint = mp.grampoint
|
410 |
+
zetazero = mp.zetazero
|
411 |
+
riemannr = mp.riemannr
|
412 |
+
primepi = mp.primepi
|
413 |
+
primepi2 = mp.primepi2
|
414 |
+
primezeta = mp.primezeta
|
415 |
+
bell = mp.bell
|
416 |
+
polyexp = mp.polyexp
|
417 |
+
expm1 = mp.expm1
|
418 |
+
log1p = mp.log1p
|
419 |
+
powm1 = mp.powm1
|
420 |
+
unitroots = mp.unitroots
|
421 |
+
cyclotomic = mp.cyclotomic
|
422 |
+
mangoldt = mp.mangoldt
|
423 |
+
secondzeta = mp.secondzeta
|
424 |
+
nzeros = mp.nzeros
|
425 |
+
backlunds = mp.backlunds
|
426 |
+
lerchphi = mp.lerchphi
|
427 |
+
stirling1 = mp.stirling1
|
428 |
+
stirling2 = mp.stirling2
|
429 |
+
squarew = mp.squarew
|
430 |
+
trianglew = mp.trianglew
|
431 |
+
sawtoothw = mp.sawtoothw
|
432 |
+
unit_triangle = mp.unit_triangle
|
433 |
+
sigmoid = mp.sigmoid
|
434 |
+
|
435 |
+
# be careful when changing this name, don't use test*!
|
436 |
+
def runtests():
|
437 |
+
"""
|
438 |
+
Run all mpmath tests and print output.
|
439 |
+
"""
|
440 |
+
import os.path
|
441 |
+
from inspect import getsourcefile
|
442 |
+
from .tests import runtests as tests
|
443 |
+
testdir = os.path.dirname(os.path.abspath(getsourcefile(tests)))
|
444 |
+
importdir = os.path.abspath(testdir + '/../..')
|
445 |
+
tests.testit(importdir, testdir)
|
446 |
+
|
447 |
+
def doctests(filter=[]):
|
448 |
+
import sys
|
449 |
+
from timeit import default_timer as clock
|
450 |
+
for i, arg in enumerate(sys.argv):
|
451 |
+
if '__init__.py' in arg:
|
452 |
+
filter = [sn for sn in sys.argv[i+1:] if not sn.startswith("-")]
|
453 |
+
break
|
454 |
+
import doctest
|
455 |
+
globs = globals().copy()
|
456 |
+
for obj in globs: #sorted(globs.keys()):
|
457 |
+
if filter:
|
458 |
+
if not sum([pat in obj for pat in filter]):
|
459 |
+
continue
|
460 |
+
sys.stdout.write(str(obj) + " ")
|
461 |
+
sys.stdout.flush()
|
462 |
+
t1 = clock()
|
463 |
+
doctest.run_docstring_examples(globs[obj], {}, verbose=("-v" in sys.argv))
|
464 |
+
t2 = clock()
|
465 |
+
print(round(t2-t1, 3))
|
466 |
+
|
467 |
+
if __name__ == '__main__':
|
468 |
+
doctests()
|
MLPY/Lib/site-packages/mpmath/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (8.24 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/ctx_base.cpython-39.pyc
ADDED
Binary file (16.3 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/ctx_fp.cpython-39.pyc
ADDED
Binary file (7.81 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/ctx_iv.cpython-39.pyc
ADDED
Binary file (20.8 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/ctx_mp.cpython-39.pyc
ADDED
Binary file (43.7 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/ctx_mp_python.cpython-39.pyc
ADDED
Binary file (35.5 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/function_docs.cpython-39.pyc
ADDED
Binary file (284 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/identification.cpython-39.pyc
ADDED
Binary file (28.5 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/math2.cpython-39.pyc
ADDED
Binary file (15.2 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/rational.cpython-39.pyc
ADDED
Binary file (6.09 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/usertools.cpython-39.pyc
ADDED
Binary file (3.57 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/__pycache__/visualization.cpython-39.pyc
ADDED
Binary file (9.75 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__init__.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from . import calculus
|
2 |
+
# XXX: hack to set methods
|
3 |
+
from . import approximation
|
4 |
+
from . import differentiation
|
5 |
+
from . import extrapolation
|
6 |
+
from . import polynomials
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (329 Bytes). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/approximation.cpython-39.pyc
ADDED
Binary file (9.11 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/calculus.cpython-39.pyc
ADDED
Binary file (451 Bytes). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/differentiation.cpython-39.pyc
ADDED
Binary file (20.3 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/extrapolation.cpython-39.pyc
ADDED
Binary file (69.6 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/inverselaplace.cpython-39.pyc
ADDED
Binary file (30.8 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/odes.cpython-39.pyc
ADDED
Binary file (10.2 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/optimization.cpython-39.pyc
ADDED
Binary file (30.3 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/polynomials.cpython-39.pyc
ADDED
Binary file (7.76 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/__pycache__/quadrature.cpython-39.pyc
ADDED
Binary file (39.6 kB). View file
|
|
MLPY/Lib/site-packages/mpmath/calculus/approximation.py
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ..libmp.backend import xrange
|
2 |
+
from .calculus import defun
|
3 |
+
|
4 |
+
#----------------------------------------------------------------------------#
|
5 |
+
# Approximation methods #
|
6 |
+
#----------------------------------------------------------------------------#
|
7 |
+
|
8 |
+
# The Chebyshev approximation formula is given at:
|
9 |
+
# http://mathworld.wolfram.com/ChebyshevApproximationFormula.html
|
10 |
+
|
11 |
+
# The only major changes in the following code is that we return the
|
12 |
+
# expanded polynomial coefficients instead of Chebyshev coefficients,
|
13 |
+
# and that we automatically transform [a,b] -> [-1,1] and back
|
14 |
+
# for convenience.
|
15 |
+
|
16 |
+
# Coefficient in Chebyshev approximation
|
17 |
+
def chebcoeff(ctx,f,a,b,j,N):
|
18 |
+
s = ctx.mpf(0)
|
19 |
+
h = ctx.mpf(0.5)
|
20 |
+
for k in range(1, N+1):
|
21 |
+
t = ctx.cospi((k-h)/N)
|
22 |
+
s += f(t*(b-a)*h + (b+a)*h) * ctx.cospi(j*(k-h)/N)
|
23 |
+
return 2*s/N
|
24 |
+
|
25 |
+
# Generate Chebyshev polynomials T_n(ax+b) in expanded form
|
26 |
+
def chebT(ctx, a=1, b=0):
|
27 |
+
Tb = [1]
|
28 |
+
yield Tb
|
29 |
+
Ta = [b, a]
|
30 |
+
while 1:
|
31 |
+
yield Ta
|
32 |
+
# Recurrence: T[n+1](ax+b) = 2*(ax+b)*T[n](ax+b) - T[n-1](ax+b)
|
33 |
+
Tmp = [0] + [2*a*t for t in Ta]
|
34 |
+
for i, c in enumerate(Ta): Tmp[i] += 2*b*c
|
35 |
+
for i, c in enumerate(Tb): Tmp[i] -= c
|
36 |
+
Ta, Tb = Tmp, Ta
|
37 |
+
|
38 |
+
@defun
|
39 |
+
def chebyfit(ctx, f, interval, N, error=False):
|
40 |
+
r"""
|
41 |
+
Computes a polynomial of degree `N-1` that approximates the
|
42 |
+
given function `f` on the interval `[a, b]`. With ``error=True``,
|
43 |
+
:func:`~mpmath.chebyfit` also returns an accurate estimate of the
|
44 |
+
maximum absolute error; that is, the maximum value of
|
45 |
+
`|f(x) - P(x)|` for `x \in [a, b]`.
|
46 |
+
|
47 |
+
:func:`~mpmath.chebyfit` uses the Chebyshev approximation formula,
|
48 |
+
which gives a nearly optimal solution: that is, the maximum
|
49 |
+
error of the approximating polynomial is very close to
|
50 |
+
the smallest possible for any polynomial of the same degree.
|
51 |
+
|
52 |
+
Chebyshev approximation is very useful if one needs repeated
|
53 |
+
evaluation of an expensive function, such as function defined
|
54 |
+
implicitly by an integral or a differential equation. (For
|
55 |
+
example, it could be used to turn a slow mpmath function
|
56 |
+
into a fast machine-precision version of the same.)
|
57 |
+
|
58 |
+
**Examples**
|
59 |
+
|
60 |
+
Here we use :func:`~mpmath.chebyfit` to generate a low-degree approximation
|
61 |
+
of `f(x) = \cos(x)`, valid on the interval `[1, 2]`::
|
62 |
+
|
63 |
+
>>> from mpmath import *
|
64 |
+
>>> mp.dps = 15; mp.pretty = True
|
65 |
+
>>> poly, err = chebyfit(cos, [1, 2], 5, error=True)
|
66 |
+
>>> nprint(poly)
|
67 |
+
[0.00291682, 0.146166, -0.732491, 0.174141, 0.949553]
|
68 |
+
>>> nprint(err, 12)
|
69 |
+
1.61351758081e-5
|
70 |
+
|
71 |
+
The polynomial can be evaluated using ``polyval``::
|
72 |
+
|
73 |
+
>>> nprint(polyval(poly, 1.6), 12)
|
74 |
+
-0.0291858904138
|
75 |
+
>>> nprint(cos(1.6), 12)
|
76 |
+
-0.0291995223013
|
77 |
+
|
78 |
+
Sampling the true error at 1000 points shows that the error
|
79 |
+
estimate generated by ``chebyfit`` is remarkably good::
|
80 |
+
|
81 |
+
>>> error = lambda x: abs(cos(x) - polyval(poly, x))
|
82 |
+
>>> nprint(max([error(1+n/1000.) for n in range(1000)]), 12)
|
83 |
+
1.61349954245e-5
|
84 |
+
|
85 |
+
**Choice of degree**
|
86 |
+
|
87 |
+
The degree `N` can be set arbitrarily high, to obtain an
|
88 |
+
arbitrarily good approximation. As a rule of thumb, an
|
89 |
+
`N`-term Chebyshev approximation is good to `N/(b-a)` decimal
|
90 |
+
places on a unit interval (although this depends on how
|
91 |
+
well-behaved `f` is). The cost grows accordingly: ``chebyfit``
|
92 |
+
evaluates the function `(N^2)/2` times to compute the
|
93 |
+
coefficients and an additional `N` times to estimate the error.
|
94 |
+
|
95 |
+
**Possible issues**
|
96 |
+
|
97 |
+
One should be careful to use a sufficiently high working
|
98 |
+
precision both when calling ``chebyfit`` and when evaluating
|
99 |
+
the resulting polynomial, as the polynomial is sometimes
|
100 |
+
ill-conditioned. It is for example difficult to reach
|
101 |
+
15-digit accuracy when evaluating the polynomial using
|
102 |
+
machine precision floats, no matter the theoretical
|
103 |
+
accuracy of the polynomial. (The option to return the
|
104 |
+
coefficients in Chebyshev form should be made available
|
105 |
+
in the future.)
|
106 |
+
|
107 |
+
It is important to note the Chebyshev approximation works
|
108 |
+
poorly if `f` is not smooth. A function containing singularities,
|
109 |
+
rapid oscillation, etc can be approximated more effectively by
|
110 |
+
multiplying it by a weight function that cancels out the
|
111 |
+
nonsmooth features, or by dividing the interval into several
|
112 |
+
segments.
|
113 |
+
"""
|
114 |
+
a, b = ctx._as_points(interval)
|
115 |
+
orig = ctx.prec
|
116 |
+
try:
|
117 |
+
ctx.prec = orig + int(N**0.5) + 20
|
118 |
+
c = [chebcoeff(ctx,f,a,b,k,N) for k in range(N)]
|
119 |
+
d = [ctx.zero] * N
|
120 |
+
d[0] = -c[0]/2
|
121 |
+
h = ctx.mpf(0.5)
|
122 |
+
T = chebT(ctx, ctx.mpf(2)/(b-a), ctx.mpf(-1)*(b+a)/(b-a))
|
123 |
+
for (k, Tk) in zip(range(N), T):
|
124 |
+
for i in range(len(Tk)):
|
125 |
+
d[i] += c[k]*Tk[i]
|
126 |
+
d = d[::-1]
|
127 |
+
# Estimate maximum error
|
128 |
+
err = ctx.zero
|
129 |
+
for k in range(N):
|
130 |
+
x = ctx.cos(ctx.pi*k/N) * (b-a)*h + (b+a)*h
|
131 |
+
err = max(err, abs(f(x) - ctx.polyval(d, x)))
|
132 |
+
finally:
|
133 |
+
ctx.prec = orig
|
134 |
+
if error:
|
135 |
+
return d, +err
|
136 |
+
else:
|
137 |
+
return d
|
138 |
+
|
139 |
+
@defun
|
140 |
+
def fourier(ctx, f, interval, N):
|
141 |
+
r"""
|
142 |
+
Computes the Fourier series of degree `N` of the given function
|
143 |
+
on the interval `[a, b]`. More precisely, :func:`~mpmath.fourier` returns
|
144 |
+
two lists `(c, s)` of coefficients (the cosine series and sine
|
145 |
+
series, respectively), such that
|
146 |
+
|
147 |
+
.. math ::
|
148 |
+
|
149 |
+
f(x) \sim \sum_{k=0}^N
|
150 |
+
c_k \cos(k m x) + s_k \sin(k m x)
|
151 |
+
|
152 |
+
where `m = 2 \pi / (b-a)`.
|
153 |
+
|
154 |
+
Note that many texts define the first coefficient as `2 c_0` instead
|
155 |
+
of `c_0`. The easiest way to evaluate the computed series correctly
|
156 |
+
is to pass it to :func:`~mpmath.fourierval`.
|
157 |
+
|
158 |
+
**Examples**
|
159 |
+
|
160 |
+
The function `f(x) = x` has a simple Fourier series on the standard
|
161 |
+
interval `[-\pi, \pi]`. The cosine coefficients are all zero (because
|
162 |
+
the function has odd symmetry), and the sine coefficients are
|
163 |
+
rational numbers::
|
164 |
+
|
165 |
+
>>> from mpmath import *
|
166 |
+
>>> mp.dps = 15; mp.pretty = True
|
167 |
+
>>> c, s = fourier(lambda x: x, [-pi, pi], 5)
|
168 |
+
>>> nprint(c)
|
169 |
+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
170 |
+
>>> nprint(s)
|
171 |
+
[0.0, 2.0, -1.0, 0.666667, -0.5, 0.4]
|
172 |
+
|
173 |
+
This computes a Fourier series of a nonsymmetric function on
|
174 |
+
a nonstandard interval::
|
175 |
+
|
176 |
+
>>> I = [-1, 1.5]
|
177 |
+
>>> f = lambda x: x**2 - 4*x + 1
|
178 |
+
>>> cs = fourier(f, I, 4)
|
179 |
+
>>> nprint(cs[0])
|
180 |
+
[0.583333, 1.12479, -1.27552, 0.904708, -0.441296]
|
181 |
+
>>> nprint(cs[1])
|
182 |
+
[0.0, -2.6255, 0.580905, 0.219974, -0.540057]
|
183 |
+
|
184 |
+
It is instructive to plot a function along with its truncated
|
185 |
+
Fourier series::
|
186 |
+
|
187 |
+
>>> plot([f, lambda x: fourierval(cs, I, x)], I) #doctest: +SKIP
|
188 |
+
|
189 |
+
Fourier series generally converge slowly (and may not converge
|
190 |
+
pointwise). For example, if `f(x) = \cosh(x)`, a 10-term Fourier
|
191 |
+
series gives an `L^2` error corresponding to 2-digit accuracy::
|
192 |
+
|
193 |
+
>>> I = [-1, 1]
|
194 |
+
>>> cs = fourier(cosh, I, 9)
|
195 |
+
>>> g = lambda x: (cosh(x) - fourierval(cs, I, x))**2
|
196 |
+
>>> nprint(sqrt(quad(g, I)))
|
197 |
+
0.00467963
|
198 |
+
|
199 |
+
:func:`~mpmath.fourier` uses numerical quadrature. For nonsmooth functions,
|
200 |
+
the accuracy (and speed) can be improved by including all singular
|
201 |
+
points in the interval specification::
|
202 |
+
|
203 |
+
>>> nprint(fourier(abs, [-1, 1], 0), 10)
|
204 |
+
([0.5000441648], [0.0])
|
205 |
+
>>> nprint(fourier(abs, [-1, 0, 1], 0), 10)
|
206 |
+
([0.5], [0.0])
|
207 |
+
|
208 |
+
"""
|
209 |
+
interval = ctx._as_points(interval)
|
210 |
+
a = interval[0]
|
211 |
+
b = interval[-1]
|
212 |
+
L = b-a
|
213 |
+
cos_series = []
|
214 |
+
sin_series = []
|
215 |
+
cutoff = ctx.eps*10
|
216 |
+
for n in xrange(N+1):
|
217 |
+
m = 2*n*ctx.pi/L
|
218 |
+
an = 2*ctx.quadgl(lambda t: f(t)*ctx.cos(m*t), interval)/L
|
219 |
+
bn = 2*ctx.quadgl(lambda t: f(t)*ctx.sin(m*t), interval)/L
|
220 |
+
if n == 0:
|
221 |
+
an /= 2
|
222 |
+
if abs(an) < cutoff: an = ctx.zero
|
223 |
+
if abs(bn) < cutoff: bn = ctx.zero
|
224 |
+
cos_series.append(an)
|
225 |
+
sin_series.append(bn)
|
226 |
+
return cos_series, sin_series
|
227 |
+
|
228 |
+
@defun
|
229 |
+
def fourierval(ctx, series, interval, x):
|
230 |
+
"""
|
231 |
+
Evaluates a Fourier series (in the format computed by
|
232 |
+
by :func:`~mpmath.fourier` for the given interval) at the point `x`.
|
233 |
+
|
234 |
+
The series should be a pair `(c, s)` where `c` is the
|
235 |
+
cosine series and `s` is the sine series. The two lists
|
236 |
+
need not have the same length.
|
237 |
+
"""
|
238 |
+
cs, ss = series
|
239 |
+
ab = ctx._as_points(interval)
|
240 |
+
a = interval[0]
|
241 |
+
b = interval[-1]
|
242 |
+
m = 2*ctx.pi/(ab[-1]-ab[0])
|
243 |
+
s = ctx.zero
|
244 |
+
s += ctx.fsum(cs[n]*ctx.cos(m*n*x) for n in xrange(len(cs)) if cs[n])
|
245 |
+
s += ctx.fsum(ss[n]*ctx.sin(m*n*x) for n in xrange(len(ss)) if ss[n])
|
246 |
+
return s
|
MLPY/Lib/site-packages/mpmath/calculus/calculus.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class CalculusMethods(object):
|
2 |
+
pass
|
3 |
+
|
4 |
+
def defun(f):
|
5 |
+
setattr(CalculusMethods, f.__name__, f)
|
6 |
+
return f
|
MLPY/Lib/site-packages/mpmath/calculus/differentiation.py
ADDED
@@ -0,0 +1,647 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ..libmp.backend import xrange
|
2 |
+
from .calculus import defun
|
3 |
+
|
4 |
+
try:
|
5 |
+
iteritems = dict.iteritems
|
6 |
+
except AttributeError:
|
7 |
+
iteritems = dict.items
|
8 |
+
|
9 |
+
#----------------------------------------------------------------------------#
|
10 |
+
# Differentiation #
|
11 |
+
#----------------------------------------------------------------------------#
|
12 |
+
|
13 |
+
@defun
|
14 |
+
def difference(ctx, s, n):
|
15 |
+
r"""
|
16 |
+
Given a sequence `(s_k)` containing at least `n+1` items, returns the
|
17 |
+
`n`-th forward difference,
|
18 |
+
|
19 |
+
.. math ::
|
20 |
+
|
21 |
+
\Delta^n = \sum_{k=0}^{\infty} (-1)^{k+n} {n \choose k} s_k.
|
22 |
+
"""
|
23 |
+
n = int(n)
|
24 |
+
d = ctx.zero
|
25 |
+
b = (-1) ** (n & 1)
|
26 |
+
for k in xrange(n+1):
|
27 |
+
d += b * s[k]
|
28 |
+
b = (b * (k-n)) // (k+1)
|
29 |
+
return d
|
30 |
+
|
31 |
+
def hsteps(ctx, f, x, n, prec, **options):
|
32 |
+
singular = options.get('singular')
|
33 |
+
addprec = options.get('addprec', 10)
|
34 |
+
direction = options.get('direction', 0)
|
35 |
+
workprec = (prec+2*addprec) * (n+1)
|
36 |
+
orig = ctx.prec
|
37 |
+
try:
|
38 |
+
ctx.prec = workprec
|
39 |
+
h = options.get('h')
|
40 |
+
if h is None:
|
41 |
+
if options.get('relative'):
|
42 |
+
hextramag = int(ctx.mag(x))
|
43 |
+
else:
|
44 |
+
hextramag = 0
|
45 |
+
h = ctx.ldexp(1, -prec-addprec-hextramag)
|
46 |
+
else:
|
47 |
+
h = ctx.convert(h)
|
48 |
+
# Directed: steps x, x+h, ... x+n*h
|
49 |
+
direction = options.get('direction', 0)
|
50 |
+
if direction:
|
51 |
+
h *= ctx.sign(direction)
|
52 |
+
steps = xrange(n+1)
|
53 |
+
norm = h
|
54 |
+
# Central: steps x-n*h, x-(n-2)*h ..., x, ..., x+(n-2)*h, x+n*h
|
55 |
+
else:
|
56 |
+
steps = xrange(-n, n+1, 2)
|
57 |
+
norm = (2*h)
|
58 |
+
# Perturb
|
59 |
+
if singular:
|
60 |
+
x += 0.5*h
|
61 |
+
values = [f(x+k*h) for k in steps]
|
62 |
+
return values, norm, workprec
|
63 |
+
finally:
|
64 |
+
ctx.prec = orig
|
65 |
+
|
66 |
+
|
67 |
+
@defun
|
68 |
+
def diff(ctx, f, x, n=1, **options):
|
69 |
+
r"""
|
70 |
+
Numerically computes the derivative of `f`, `f'(x)`, or generally for
|
71 |
+
an integer `n \ge 0`, the `n`-th derivative `f^{(n)}(x)`.
|
72 |
+
A few basic examples are::
|
73 |
+
|
74 |
+
>>> from mpmath import *
|
75 |
+
>>> mp.dps = 15; mp.pretty = True
|
76 |
+
>>> diff(lambda x: x**2 + x, 1.0)
|
77 |
+
3.0
|
78 |
+
>>> diff(lambda x: x**2 + x, 1.0, 2)
|
79 |
+
2.0
|
80 |
+
>>> diff(lambda x: x**2 + x, 1.0, 3)
|
81 |
+
0.0
|
82 |
+
>>> nprint([diff(exp, 3, n) for n in range(5)]) # exp'(x) = exp(x)
|
83 |
+
[20.0855, 20.0855, 20.0855, 20.0855, 20.0855]
|
84 |
+
|
85 |
+
Even more generally, given a tuple of arguments `(x_1, \ldots, x_k)`
|
86 |
+
and order `(n_1, \ldots, n_k)`, the partial derivative
|
87 |
+
`f^{(n_1,\ldots,n_k)}(x_1,\ldots,x_k)` is evaluated. For example::
|
88 |
+
|
89 |
+
>>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (0,1))
|
90 |
+
2.75
|
91 |
+
>>> diff(lambda x,y: 3*x*y + 2*y - x, (0.25, 0.5), (1,1))
|
92 |
+
3.0
|
93 |
+
|
94 |
+
**Options**
|
95 |
+
|
96 |
+
The following optional keyword arguments are recognized:
|
97 |
+
|
98 |
+
``method``
|
99 |
+
Supported methods are ``'step'`` or ``'quad'``: derivatives may be
|
100 |
+
computed using either a finite difference with a small step
|
101 |
+
size `h` (default), or numerical quadrature.
|
102 |
+
``direction``
|
103 |
+
Direction of finite difference: can be -1 for a left
|
104 |
+
difference, 0 for a central difference (default), or +1
|
105 |
+
for a right difference; more generally can be any complex number.
|
106 |
+
``addprec``
|
107 |
+
Extra precision for `h` used to account for the function's
|
108 |
+
sensitivity to perturbations (default = 10).
|
109 |
+
``relative``
|
110 |
+
Choose `h` relative to the magnitude of `x`, rather than an
|
111 |
+
absolute value; useful for large or tiny `x` (default = False).
|
112 |
+
``h``
|
113 |
+
As an alternative to ``addprec`` and ``relative``, manually
|
114 |
+
select the step size `h`.
|
115 |
+
``singular``
|
116 |
+
If True, evaluation exactly at the point `x` is avoided; this is
|
117 |
+
useful for differentiating functions with removable singularities.
|
118 |
+
Default = False.
|
119 |
+
``radius``
|
120 |
+
Radius of integration contour (with ``method = 'quad'``).
|
121 |
+
Default = 0.25. A larger radius typically is faster and more
|
122 |
+
accurate, but it must be chosen so that `f` has no
|
123 |
+
singularities within the radius from the evaluation point.
|
124 |
+
|
125 |
+
A finite difference requires `n+1` function evaluations and must be
|
126 |
+
performed at `(n+1)` times the target precision. Accordingly, `f` must
|
127 |
+
support fast evaluation at high precision.
|
128 |
+
|
129 |
+
With integration, a larger number of function evaluations is
|
130 |
+
required, but not much extra precision is required. For high order
|
131 |
+
derivatives, this method may thus be faster if f is very expensive to
|
132 |
+
evaluate at high precision.
|
133 |
+
|
134 |
+
**Further examples**
|
135 |
+
|
136 |
+
The direction option is useful for computing left- or right-sided
|
137 |
+
derivatives of nonsmooth functions::
|
138 |
+
|
139 |
+
>>> diff(abs, 0, direction=0)
|
140 |
+
0.0
|
141 |
+
>>> diff(abs, 0, direction=1)
|
142 |
+
1.0
|
143 |
+
>>> diff(abs, 0, direction=-1)
|
144 |
+
-1.0
|
145 |
+
|
146 |
+
More generally, if the direction is nonzero, a right difference
|
147 |
+
is computed where the step size is multiplied by sign(direction).
|
148 |
+
For example, with direction=+j, the derivative from the positive
|
149 |
+
imaginary direction will be computed::
|
150 |
+
|
151 |
+
>>> diff(abs, 0, direction=j)
|
152 |
+
(0.0 - 1.0j)
|
153 |
+
|
154 |
+
With integration, the result may have a small imaginary part
|
155 |
+
even even if the result is purely real::
|
156 |
+
|
157 |
+
>>> diff(sqrt, 1, method='quad') # doctest:+ELLIPSIS
|
158 |
+
(0.5 - 4.59...e-26j)
|
159 |
+
>>> chop(_)
|
160 |
+
0.5
|
161 |
+
|
162 |
+
Adding precision to obtain an accurate value::
|
163 |
+
|
164 |
+
>>> diff(cos, 1e-30)
|
165 |
+
0.0
|
166 |
+
>>> diff(cos, 1e-30, h=0.0001)
|
167 |
+
-9.99999998328279e-31
|
168 |
+
>>> diff(cos, 1e-30, addprec=100)
|
169 |
+
-1.0e-30
|
170 |
+
|
171 |
+
"""
|
172 |
+
partial = False
|
173 |
+
try:
|
174 |
+
orders = list(n)
|
175 |
+
x = list(x)
|
176 |
+
partial = True
|
177 |
+
except TypeError:
|
178 |
+
pass
|
179 |
+
if partial:
|
180 |
+
x = [ctx.convert(_) for _ in x]
|
181 |
+
return _partial_diff(ctx, f, x, orders, options)
|
182 |
+
method = options.get('method', 'step')
|
183 |
+
if n == 0 and method != 'quad' and not options.get('singular'):
|
184 |
+
return f(ctx.convert(x))
|
185 |
+
prec = ctx.prec
|
186 |
+
try:
|
187 |
+
if method == 'step':
|
188 |
+
values, norm, workprec = hsteps(ctx, f, x, n, prec, **options)
|
189 |
+
ctx.prec = workprec
|
190 |
+
v = ctx.difference(values, n) / norm**n
|
191 |
+
elif method == 'quad':
|
192 |
+
ctx.prec += 10
|
193 |
+
radius = ctx.convert(options.get('radius', 0.25))
|
194 |
+
def g(t):
|
195 |
+
rei = radius*ctx.expj(t)
|
196 |
+
z = x + rei
|
197 |
+
return f(z) / rei**n
|
198 |
+
d = ctx.quadts(g, [0, 2*ctx.pi])
|
199 |
+
v = d * ctx.factorial(n) / (2*ctx.pi)
|
200 |
+
else:
|
201 |
+
raise ValueError("unknown method: %r" % method)
|
202 |
+
finally:
|
203 |
+
ctx.prec = prec
|
204 |
+
return +v
|
205 |
+
|
206 |
+
def _partial_diff(ctx, f, xs, orders, options):
|
207 |
+
if not orders:
|
208 |
+
return f()
|
209 |
+
if not sum(orders):
|
210 |
+
return f(*xs)
|
211 |
+
i = 0
|
212 |
+
for i in range(len(orders)):
|
213 |
+
if orders[i]:
|
214 |
+
break
|
215 |
+
order = orders[i]
|
216 |
+
def fdiff_inner(*f_args):
|
217 |
+
def inner(t):
|
218 |
+
return f(*(f_args[:i] + (t,) + f_args[i+1:]))
|
219 |
+
return ctx.diff(inner, f_args[i], order, **options)
|
220 |
+
orders[i] = 0
|
221 |
+
return _partial_diff(ctx, fdiff_inner, xs, orders, options)
|
222 |
+
|
223 |
+
@defun
|
224 |
+
def diffs(ctx, f, x, n=None, **options):
|
225 |
+
r"""
|
226 |
+
Returns a generator that yields the sequence of derivatives
|
227 |
+
|
228 |
+
.. math ::
|
229 |
+
|
230 |
+
f(x), f'(x), f''(x), \ldots, f^{(k)}(x), \ldots
|
231 |
+
|
232 |
+
With ``method='step'``, :func:`~mpmath.diffs` uses only `O(k)`
|
233 |
+
function evaluations to generate the first `k` derivatives,
|
234 |
+
rather than the roughly `O(k^2)` evaluations
|
235 |
+
required if one calls :func:`~mpmath.diff` `k` separate times.
|
236 |
+
|
237 |
+
With `n < \infty`, the generator stops as soon as the
|
238 |
+
`n`-th derivative has been generated. If the exact number of
|
239 |
+
needed derivatives is known in advance, this is further
|
240 |
+
slightly more efficient.
|
241 |
+
|
242 |
+
Options are the same as for :func:`~mpmath.diff`.
|
243 |
+
|
244 |
+
**Examples**
|
245 |
+
|
246 |
+
>>> from mpmath import *
|
247 |
+
>>> mp.dps = 15
|
248 |
+
>>> nprint(list(diffs(cos, 1, 5)))
|
249 |
+
[0.540302, -0.841471, -0.540302, 0.841471, 0.540302, -0.841471]
|
250 |
+
>>> for i, d in zip(range(6), diffs(cos, 1)):
|
251 |
+
... print("%s %s" % (i, d))
|
252 |
+
...
|
253 |
+
0 0.54030230586814
|
254 |
+
1 -0.841470984807897
|
255 |
+
2 -0.54030230586814
|
256 |
+
3 0.841470984807897
|
257 |
+
4 0.54030230586814
|
258 |
+
5 -0.841470984807897
|
259 |
+
|
260 |
+
"""
|
261 |
+
if n is None:
|
262 |
+
n = ctx.inf
|
263 |
+
else:
|
264 |
+
n = int(n)
|
265 |
+
if options.get('method', 'step') != 'step':
|
266 |
+
k = 0
|
267 |
+
while k < n + 1:
|
268 |
+
yield ctx.diff(f, x, k, **options)
|
269 |
+
k += 1
|
270 |
+
return
|
271 |
+
singular = options.get('singular')
|
272 |
+
if singular:
|
273 |
+
yield ctx.diff(f, x, 0, singular=True)
|
274 |
+
else:
|
275 |
+
yield f(ctx.convert(x))
|
276 |
+
if n < 1:
|
277 |
+
return
|
278 |
+
if n == ctx.inf:
|
279 |
+
A, B = 1, 2
|
280 |
+
else:
|
281 |
+
A, B = 1, n+1
|
282 |
+
while 1:
|
283 |
+
callprec = ctx.prec
|
284 |
+
y, norm, workprec = hsteps(ctx, f, x, B, callprec, **options)
|
285 |
+
for k in xrange(A, B):
|
286 |
+
try:
|
287 |
+
ctx.prec = workprec
|
288 |
+
d = ctx.difference(y, k) / norm**k
|
289 |
+
finally:
|
290 |
+
ctx.prec = callprec
|
291 |
+
yield +d
|
292 |
+
if k >= n:
|
293 |
+
return
|
294 |
+
A, B = B, int(A*1.4+1)
|
295 |
+
B = min(B, n)
|
296 |
+
|
297 |
+
def iterable_to_function(gen):
|
298 |
+
gen = iter(gen)
|
299 |
+
data = []
|
300 |
+
def f(k):
|
301 |
+
for i in xrange(len(data), k+1):
|
302 |
+
data.append(next(gen))
|
303 |
+
return data[k]
|
304 |
+
return f
|
305 |
+
|
306 |
+
@defun
|
307 |
+
def diffs_prod(ctx, factors):
|
308 |
+
r"""
|
309 |
+
Given a list of `N` iterables or generators yielding
|
310 |
+
`f_k(x), f'_k(x), f''_k(x), \ldots` for `k = 1, \ldots, N`,
|
311 |
+
generate `g(x), g'(x), g''(x), \ldots` where
|
312 |
+
`g(x) = f_1(x) f_2(x) \cdots f_N(x)`.
|
313 |
+
|
314 |
+
At high precision and for large orders, this is typically more efficient
|
315 |
+
than numerical differentiation if the derivatives of each `f_k(x)`
|
316 |
+
admit direct computation.
|
317 |
+
|
318 |
+
Note: This function does not increase the working precision internally,
|
319 |
+
so guard digits may have to be added externally for full accuracy.
|
320 |
+
|
321 |
+
**Examples**
|
322 |
+
|
323 |
+
>>> from mpmath import *
|
324 |
+
>>> mp.dps = 15; mp.pretty = True
|
325 |
+
>>> f = lambda x: exp(x)*cos(x)*sin(x)
|
326 |
+
>>> u = diffs(f, 1)
|
327 |
+
>>> v = mp.diffs_prod([diffs(exp,1), diffs(cos,1), diffs(sin,1)])
|
328 |
+
>>> next(u); next(v)
|
329 |
+
1.23586333600241
|
330 |
+
1.23586333600241
|
331 |
+
>>> next(u); next(v)
|
332 |
+
0.104658952245596
|
333 |
+
0.104658952245596
|
334 |
+
>>> next(u); next(v)
|
335 |
+
-5.96999877552086
|
336 |
+
-5.96999877552086
|
337 |
+
>>> next(u); next(v)
|
338 |
+
-12.4632923122697
|
339 |
+
-12.4632923122697
|
340 |
+
|
341 |
+
"""
|
342 |
+
N = len(factors)
|
343 |
+
if N == 1:
|
344 |
+
for c in factors[0]:
|
345 |
+
yield c
|
346 |
+
else:
|
347 |
+
u = iterable_to_function(ctx.diffs_prod(factors[:N//2]))
|
348 |
+
v = iterable_to_function(ctx.diffs_prod(factors[N//2:]))
|
349 |
+
n = 0
|
350 |
+
while 1:
|
351 |
+
#yield sum(binomial(n,k)*u(n-k)*v(k) for k in xrange(n+1))
|
352 |
+
s = u(n) * v(0)
|
353 |
+
a = 1
|
354 |
+
for k in xrange(1,n+1):
|
355 |
+
a = a * (n-k+1) // k
|
356 |
+
s += a * u(n-k) * v(k)
|
357 |
+
yield s
|
358 |
+
n += 1
|
359 |
+
|
360 |
+
def dpoly(n, _cache={}):
|
361 |
+
"""
|
362 |
+
nth differentiation polynomial for exp (Faa di Bruno's formula).
|
363 |
+
|
364 |
+
TODO: most exponents are zero, so maybe a sparse representation
|
365 |
+
would be better.
|
366 |
+
"""
|
367 |
+
if n in _cache:
|
368 |
+
return _cache[n]
|
369 |
+
if not _cache:
|
370 |
+
_cache[0] = {(0,):1}
|
371 |
+
R = dpoly(n-1)
|
372 |
+
R = dict((c+(0,),v) for (c,v) in iteritems(R))
|
373 |
+
Ra = {}
|
374 |
+
for powers, count in iteritems(R):
|
375 |
+
powers1 = (powers[0]+1,) + powers[1:]
|
376 |
+
if powers1 in Ra:
|
377 |
+
Ra[powers1] += count
|
378 |
+
else:
|
379 |
+
Ra[powers1] = count
|
380 |
+
for powers, count in iteritems(R):
|
381 |
+
if not sum(powers):
|
382 |
+
continue
|
383 |
+
for k,p in enumerate(powers):
|
384 |
+
if p:
|
385 |
+
powers2 = powers[:k] + (p-1,powers[k+1]+1) + powers[k+2:]
|
386 |
+
if powers2 in Ra:
|
387 |
+
Ra[powers2] += p*count
|
388 |
+
else:
|
389 |
+
Ra[powers2] = p*count
|
390 |
+
_cache[n] = Ra
|
391 |
+
return _cache[n]
|
392 |
+
|
393 |
+
@defun
|
394 |
+
def diffs_exp(ctx, fdiffs):
|
395 |
+
r"""
|
396 |
+
Given an iterable or generator yielding `f(x), f'(x), f''(x), \ldots`
|
397 |
+
generate `g(x), g'(x), g''(x), \ldots` where `g(x) = \exp(f(x))`.
|
398 |
+
|
399 |
+
At high precision and for large orders, this is typically more efficient
|
400 |
+
than numerical differentiation if the derivatives of `f(x)`
|
401 |
+
admit direct computation.
|
402 |
+
|
403 |
+
Note: This function does not increase the working precision internally,
|
404 |
+
so guard digits may have to be added externally for full accuracy.
|
405 |
+
|
406 |
+
**Examples**
|
407 |
+
|
408 |
+
The derivatives of the gamma function can be computed using
|
409 |
+
logarithmic differentiation::
|
410 |
+
|
411 |
+
>>> from mpmath import *
|
412 |
+
>>> mp.dps = 15; mp.pretty = True
|
413 |
+
>>>
|
414 |
+
>>> def diffs_loggamma(x):
|
415 |
+
... yield loggamma(x)
|
416 |
+
... i = 0
|
417 |
+
... while 1:
|
418 |
+
... yield psi(i,x)
|
419 |
+
... i += 1
|
420 |
+
...
|
421 |
+
>>> u = diffs_exp(diffs_loggamma(3))
|
422 |
+
>>> v = diffs(gamma, 3)
|
423 |
+
>>> next(u); next(v)
|
424 |
+
2.0
|
425 |
+
2.0
|
426 |
+
>>> next(u); next(v)
|
427 |
+
1.84556867019693
|
428 |
+
1.84556867019693
|
429 |
+
>>> next(u); next(v)
|
430 |
+
2.49292999190269
|
431 |
+
2.49292999190269
|
432 |
+
>>> next(u); next(v)
|
433 |
+
3.44996501352367
|
434 |
+
3.44996501352367
|
435 |
+
|
436 |
+
"""
|
437 |
+
fn = iterable_to_function(fdiffs)
|
438 |
+
f0 = ctx.exp(fn(0))
|
439 |
+
yield f0
|
440 |
+
i = 1
|
441 |
+
while 1:
|
442 |
+
s = ctx.mpf(0)
|
443 |
+
for powers, c in iteritems(dpoly(i)):
|
444 |
+
s += c*ctx.fprod(fn(k+1)**p for (k,p) in enumerate(powers) if p)
|
445 |
+
yield s * f0
|
446 |
+
i += 1
|
447 |
+
|
448 |
+
@defun
|
449 |
+
def differint(ctx, f, x, n=1, x0=0):
|
450 |
+
r"""
|
451 |
+
Calculates the Riemann-Liouville differintegral, or fractional
|
452 |
+
derivative, defined by
|
453 |
+
|
454 |
+
.. math ::
|
455 |
+
|
456 |
+
\,_{x_0}{\mathbb{D}}^n_xf(x) = \frac{1}{\Gamma(m-n)} \frac{d^m}{dx^m}
|
457 |
+
\int_{x_0}^{x}(x-t)^{m-n-1}f(t)dt
|
458 |
+
|
459 |
+
where `f` is a given (presumably well-behaved) function,
|
460 |
+
`x` is the evaluation point, `n` is the order, and `x_0` is
|
461 |
+
the reference point of integration (`m` is an arbitrary
|
462 |
+
parameter selected automatically).
|
463 |
+
|
464 |
+
With `n = 1`, this is just the standard derivative `f'(x)`; with `n = 2`,
|
465 |
+
the second derivative `f''(x)`, etc. With `n = -1`, it gives
|
466 |
+
`\int_{x_0}^x f(t) dt`, with `n = -2`
|
467 |
+
it gives `\int_{x_0}^x \left( \int_{x_0}^t f(u) du \right) dt`, etc.
|
468 |
+
|
469 |
+
As `n` is permitted to be any number, this operator generalizes
|
470 |
+
iterated differentiation and iterated integration to a single
|
471 |
+
operator with a continuous order parameter.
|
472 |
+
|
473 |
+
**Examples**
|
474 |
+
|
475 |
+
There is an exact formula for the fractional derivative of a
|
476 |
+
monomial `x^p`, which may be used as a reference. For example,
|
477 |
+
the following gives a half-derivative (order 0.5)::
|
478 |
+
|
479 |
+
>>> from mpmath import *
|
480 |
+
>>> mp.dps = 15; mp.pretty = True
|
481 |
+
>>> x = mpf(3); p = 2; n = 0.5
|
482 |
+
>>> differint(lambda t: t**p, x, n)
|
483 |
+
7.81764019044672
|
484 |
+
>>> gamma(p+1)/gamma(p-n+1) * x**(p-n)
|
485 |
+
7.81764019044672
|
486 |
+
|
487 |
+
Another useful test function is the exponential function, whose
|
488 |
+
integration / differentiation formula easy generalizes
|
489 |
+
to arbitrary order. Here we first compute a third derivative,
|
490 |
+
and then a triply nested integral. (The reference point `x_0`
|
491 |
+
is set to `-\infty` to avoid nonzero endpoint terms.)::
|
492 |
+
|
493 |
+
>>> differint(lambda x: exp(pi*x), -1.5, 3)
|
494 |
+
0.278538406900792
|
495 |
+
>>> exp(pi*-1.5) * pi**3
|
496 |
+
0.278538406900792
|
497 |
+
>>> differint(lambda x: exp(pi*x), 3.5, -3, -inf)
|
498 |
+
1922.50563031149
|
499 |
+
>>> exp(pi*3.5) / pi**3
|
500 |
+
1922.50563031149
|
501 |
+
|
502 |
+
However, for noninteger `n`, the differentiation formula for the
|
503 |
+
exponential function must be modified to give the same result as the
|
504 |
+
Riemann-Liouville differintegral::
|
505 |
+
|
506 |
+
>>> x = mpf(3.5)
|
507 |
+
>>> c = pi
|
508 |
+
>>> n = 1+2*j
|
509 |
+
>>> differint(lambda x: exp(c*x), x, n)
|
510 |
+
(-123295.005390743 + 140955.117867654j)
|
511 |
+
>>> x**(-n) * exp(c)**x * (x*c)**n * gammainc(-n, 0, x*c) / gamma(-n)
|
512 |
+
(-123295.005390743 + 140955.117867654j)
|
513 |
+
|
514 |
+
|
515 |
+
"""
|
516 |
+
m = max(int(ctx.ceil(ctx.re(n)))+1, 1)
|
517 |
+
r = m-n-1
|
518 |
+
g = lambda x: ctx.quad(lambda t: (x-t)**r * f(t), [x0, x])
|
519 |
+
return ctx.diff(g, x, m) / ctx.gamma(m-n)
|
520 |
+
|
521 |
+
@defun
|
522 |
+
def diffun(ctx, f, n=1, **options):
|
523 |
+
r"""
|
524 |
+
Given a function `f`, returns a function `g(x)` that evaluates the nth
|
525 |
+
derivative `f^{(n)}(x)`::
|
526 |
+
|
527 |
+
>>> from mpmath import *
|
528 |
+
>>> mp.dps = 15; mp.pretty = True
|
529 |
+
>>> cos2 = diffun(sin)
|
530 |
+
>>> sin2 = diffun(sin, 4)
|
531 |
+
>>> cos(1.3), cos2(1.3)
|
532 |
+
(0.267498828624587, 0.267498828624587)
|
533 |
+
>>> sin(1.3), sin2(1.3)
|
534 |
+
(0.963558185417193, 0.963558185417193)
|
535 |
+
|
536 |
+
The function `f` must support arbitrary precision evaluation.
|
537 |
+
See :func:`~mpmath.diff` for additional details and supported
|
538 |
+
keyword options.
|
539 |
+
"""
|
540 |
+
if n == 0:
|
541 |
+
return f
|
542 |
+
def g(x):
|
543 |
+
return ctx.diff(f, x, n, **options)
|
544 |
+
return g
|
545 |
+
|
546 |
+
@defun
|
547 |
+
def taylor(ctx, f, x, n, **options):
|
548 |
+
r"""
|
549 |
+
Produces a degree-`n` Taylor polynomial around the point `x` of the
|
550 |
+
given function `f`. The coefficients are returned as a list.
|
551 |
+
|
552 |
+
>>> from mpmath import *
|
553 |
+
>>> mp.dps = 15; mp.pretty = True
|
554 |
+
>>> nprint(chop(taylor(sin, 0, 5)))
|
555 |
+
[0.0, 1.0, 0.0, -0.166667, 0.0, 0.00833333]
|
556 |
+
|
557 |
+
The coefficients are computed using high-order numerical
|
558 |
+
differentiation. The function must be possible to evaluate
|
559 |
+
to arbitrary precision. See :func:`~mpmath.diff` for additional details
|
560 |
+
and supported keyword options.
|
561 |
+
|
562 |
+
Note that to evaluate the Taylor polynomial as an approximation
|
563 |
+
of `f`, e.g. with :func:`~mpmath.polyval`, the coefficients must be reversed,
|
564 |
+
and the point of the Taylor expansion must be subtracted from
|
565 |
+
the argument:
|
566 |
+
|
567 |
+
>>> p = taylor(exp, 2.0, 10)
|
568 |
+
>>> polyval(p[::-1], 2.5 - 2.0)
|
569 |
+
12.1824939606092
|
570 |
+
>>> exp(2.5)
|
571 |
+
12.1824939607035
|
572 |
+
|
573 |
+
"""
|
574 |
+
gen = enumerate(ctx.diffs(f, x, n, **options))
|
575 |
+
if options.get("chop", True):
|
576 |
+
return [ctx.chop(d)/ctx.factorial(i) for i, d in gen]
|
577 |
+
else:
|
578 |
+
return [d/ctx.factorial(i) for i, d in gen]
|
579 |
+
|
580 |
+
@defun
|
581 |
+
def pade(ctx, a, L, M):
|
582 |
+
r"""
|
583 |
+
Computes a Pade approximation of degree `(L, M)` to a function.
|
584 |
+
Given at least `L+M+1` Taylor coefficients `a` approximating
|
585 |
+
a function `A(x)`, :func:`~mpmath.pade` returns coefficients of
|
586 |
+
polynomials `P, Q` satisfying
|
587 |
+
|
588 |
+
.. math ::
|
589 |
+
|
590 |
+
P = \sum_{k=0}^L p_k x^k
|
591 |
+
|
592 |
+
Q = \sum_{k=0}^M q_k x^k
|
593 |
+
|
594 |
+
Q_0 = 1
|
595 |
+
|
596 |
+
A(x) Q(x) = P(x) + O(x^{L+M+1})
|
597 |
+
|
598 |
+
`P(x)/Q(x)` can provide a good approximation to an analytic function
|
599 |
+
beyond the radius of convergence of its Taylor series (example
|
600 |
+
from G.A. Baker 'Essentials of Pade Approximants' Academic Press,
|
601 |
+
Ch.1A)::
|
602 |
+
|
603 |
+
>>> from mpmath import *
|
604 |
+
>>> mp.dps = 15; mp.pretty = True
|
605 |
+
>>> one = mpf(1)
|
606 |
+
>>> def f(x):
|
607 |
+
... return sqrt((one + 2*x)/(one + x))
|
608 |
+
...
|
609 |
+
>>> a = taylor(f, 0, 6)
|
610 |
+
>>> p, q = pade(a, 3, 3)
|
611 |
+
>>> x = 10
|
612 |
+
>>> polyval(p[::-1], x)/polyval(q[::-1], x)
|
613 |
+
1.38169105566806
|
614 |
+
>>> f(x)
|
615 |
+
1.38169855941551
|
616 |
+
|
617 |
+
"""
|
618 |
+
# To determine L+1 coefficients of P and M coefficients of Q
|
619 |
+
# L+M+1 coefficients of A must be provided
|
620 |
+
if len(a) < L+M+1:
|
621 |
+
raise ValueError("L+M+1 Coefficients should be provided")
|
622 |
+
|
623 |
+
if M == 0:
|
624 |
+
if L == 0:
|
625 |
+
return [ctx.one], [ctx.one]
|
626 |
+
else:
|
627 |
+
return a[:L+1], [ctx.one]
|
628 |
+
|
629 |
+
# Solve first
|
630 |
+
# a[L]*q[1] + ... + a[L-M+1]*q[M] = -a[L+1]
|
631 |
+
# ...
|
632 |
+
# a[L+M-1]*q[1] + ... + a[L]*q[M] = -a[L+M]
|
633 |
+
A = ctx.matrix(M)
|
634 |
+
for j in range(M):
|
635 |
+
for i in range(min(M, L+j+1)):
|
636 |
+
A[j, i] = a[L+j-i]
|
637 |
+
v = -ctx.matrix(a[(L+1):(L+M+1)])
|
638 |
+
x = ctx.lu_solve(A, v)
|
639 |
+
q = [ctx.one] + list(x)
|
640 |
+
# compute p
|
641 |
+
p = [0]*(L+1)
|
642 |
+
for i in range(L+1):
|
643 |
+
s = a[i]
|
644 |
+
for j in range(1, min(M,i) + 1):
|
645 |
+
s += q[j]*a[i-j]
|
646 |
+
p[i] = s
|
647 |
+
return p, q
|
MLPY/Lib/site-packages/mpmath/calculus/extrapolation.py
ADDED
@@ -0,0 +1,2115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
try:
|
2 |
+
from itertools import izip
|
3 |
+
except ImportError:
|
4 |
+
izip = zip
|
5 |
+
|
6 |
+
from ..libmp.backend import xrange
|
7 |
+
from .calculus import defun
|
8 |
+
|
9 |
+
try:
|
10 |
+
next = next
|
11 |
+
except NameError:
|
12 |
+
next = lambda _: _.next()
|
13 |
+
|
14 |
+
@defun
|
15 |
+
def richardson(ctx, seq):
|
16 |
+
r"""
|
17 |
+
Given a list ``seq`` of the first `N` elements of a slowly convergent
|
18 |
+
infinite sequence, :func:`~mpmath.richardson` computes the `N`-term
|
19 |
+
Richardson extrapolate for the limit.
|
20 |
+
|
21 |
+
:func:`~mpmath.richardson` returns `(v, c)` where `v` is the estimated
|
22 |
+
limit and `c` is the magnitude of the largest weight used during the
|
23 |
+
computation. The weight provides an estimate of the precision
|
24 |
+
lost to cancellation. Due to cancellation effects, the sequence must
|
25 |
+
be typically be computed at a much higher precision than the target
|
26 |
+
accuracy of the extrapolation.
|
27 |
+
|
28 |
+
**Applicability and issues**
|
29 |
+
|
30 |
+
The `N`-step Richardson extrapolation algorithm used by
|
31 |
+
:func:`~mpmath.richardson` is described in [1].
|
32 |
+
|
33 |
+
Richardson extrapolation only works for a specific type of sequence,
|
34 |
+
namely one converging like partial sums of
|
35 |
+
`P(1)/Q(1) + P(2)/Q(2) + \ldots` where `P` and `Q` are polynomials.
|
36 |
+
When the sequence does not convergence at such a rate
|
37 |
+
:func:`~mpmath.richardson` generally produces garbage.
|
38 |
+
|
39 |
+
Richardson extrapolation has the advantage of being fast: the `N`-term
|
40 |
+
extrapolate requires only `O(N)` arithmetic operations, and usually
|
41 |
+
produces an estimate that is accurate to `O(N)` digits. Contrast with
|
42 |
+
the Shanks transformation (see :func:`~mpmath.shanks`), which requires
|
43 |
+
`O(N^2)` operations.
|
44 |
+
|
45 |
+
:func:`~mpmath.richardson` is unable to produce an estimate for the
|
46 |
+
approximation error. One way to estimate the error is to perform
|
47 |
+
two extrapolations with slightly different `N` and comparing the
|
48 |
+
results.
|
49 |
+
|
50 |
+
Richardson extrapolation does not work for oscillating sequences.
|
51 |
+
As a simple workaround, :func:`~mpmath.richardson` detects if the last
|
52 |
+
three elements do not differ monotonically, and in that case
|
53 |
+
applies extrapolation only to the even-index elements.
|
54 |
+
|
55 |
+
**Example**
|
56 |
+
|
57 |
+
Applying Richardson extrapolation to the Leibniz series for `\pi`::
|
58 |
+
|
59 |
+
>>> from mpmath import *
|
60 |
+
>>> mp.dps = 30; mp.pretty = True
|
61 |
+
>>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m))
|
62 |
+
... for m in range(1,30)]
|
63 |
+
>>> v, c = richardson(S[:10])
|
64 |
+
>>> v
|
65 |
+
3.2126984126984126984126984127
|
66 |
+
>>> nprint([v-pi, c])
|
67 |
+
[0.0711058, 2.0]
|
68 |
+
|
69 |
+
>>> v, c = richardson(S[:30])
|
70 |
+
>>> v
|
71 |
+
3.14159265468624052829954206226
|
72 |
+
>>> nprint([v-pi, c])
|
73 |
+
[1.09645e-9, 20833.3]
|
74 |
+
|
75 |
+
**References**
|
76 |
+
|
77 |
+
1. [BenderOrszag]_ pp. 375-376
|
78 |
+
|
79 |
+
"""
|
80 |
+
if len(seq) < 3:
|
81 |
+
raise ValueError("seq should be of minimum length 3")
|
82 |
+
if ctx.sign(seq[-1]-seq[-2]) != ctx.sign(seq[-2]-seq[-3]):
|
83 |
+
seq = seq[::2]
|
84 |
+
N = len(seq)//2-1
|
85 |
+
s = ctx.zero
|
86 |
+
# The general weight is c[k] = (N+k)**N * (-1)**(k+N) / k! / (N-k)!
|
87 |
+
# To avoid repeated factorials, we simplify the quotient
|
88 |
+
# of successive weights to obtain a recurrence relation
|
89 |
+
c = (-1)**N * N**N / ctx.mpf(ctx._ifac(N))
|
90 |
+
maxc = 1
|
91 |
+
for k in xrange(N+1):
|
92 |
+
s += c * seq[N+k]
|
93 |
+
maxc = max(abs(c), maxc)
|
94 |
+
c *= (k-N)*ctx.mpf(k+N+1)**N
|
95 |
+
c /= ((1+k)*ctx.mpf(k+N)**N)
|
96 |
+
return s, maxc
|
97 |
+
|
98 |
+
@defun
|
99 |
+
def shanks(ctx, seq, table=None, randomized=False):
|
100 |
+
r"""
|
101 |
+
Given a list ``seq`` of the first `N` elements of a slowly
|
102 |
+
convergent infinite sequence `(A_k)`, :func:`~mpmath.shanks` computes the iterated
|
103 |
+
Shanks transformation `S(A), S(S(A)), \ldots, S^{N/2}(A)`. The Shanks
|
104 |
+
transformation often provides strong convergence acceleration,
|
105 |
+
especially if the sequence is oscillating.
|
106 |
+
|
107 |
+
The iterated Shanks transformation is computed using the Wynn
|
108 |
+
epsilon algorithm (see [1]). :func:`~mpmath.shanks` returns the full
|
109 |
+
epsilon table generated by Wynn's algorithm, which can be read
|
110 |
+
off as follows:
|
111 |
+
|
112 |
+
* The table is a list of lists forming a lower triangular matrix,
|
113 |
+
where higher row and column indices correspond to more accurate
|
114 |
+
values.
|
115 |
+
* The columns with even index hold dummy entries (required for the
|
116 |
+
computation) and the columns with odd index hold the actual
|
117 |
+
extrapolates.
|
118 |
+
* The last element in the last row is typically the most
|
119 |
+
accurate estimate of the limit.
|
120 |
+
* The difference to the third last element in the last row
|
121 |
+
provides an estimate of the approximation error.
|
122 |
+
* The magnitude of the second last element provides an estimate
|
123 |
+
of the numerical accuracy lost to cancellation.
|
124 |
+
|
125 |
+
For convenience, so the extrapolation is stopped at an odd index
|
126 |
+
so that ``shanks(seq)[-1][-1]`` always gives an estimate of the
|
127 |
+
limit.
|
128 |
+
|
129 |
+
Optionally, an existing table can be passed to :func:`~mpmath.shanks`.
|
130 |
+
This can be used to efficiently extend a previous computation after
|
131 |
+
new elements have been appended to the sequence. The table will
|
132 |
+
then be updated in-place.
|
133 |
+
|
134 |
+
**The Shanks transformation**
|
135 |
+
|
136 |
+
The Shanks transformation is defined as follows (see [2]): given
|
137 |
+
the input sequence `(A_0, A_1, \ldots)`, the transformed sequence is
|
138 |
+
given by
|
139 |
+
|
140 |
+
.. math ::
|
141 |
+
|
142 |
+
S(A_k) = \frac{A_{k+1}A_{k-1}-A_k^2}{A_{k+1}+A_{k-1}-2 A_k}
|
143 |
+
|
144 |
+
The Shanks transformation gives the exact limit `A_{\infty}` in a
|
145 |
+
single step if `A_k = A + a q^k`. Note in particular that it
|
146 |
+
extrapolates the exact sum of a geometric series in a single step.
|
147 |
+
|
148 |
+
Applying the Shanks transformation once often improves convergence
|
149 |
+
substantially for an arbitrary sequence, but the optimal effect is
|
150 |
+
obtained by applying it iteratively:
|
151 |
+
`S(S(A_k)), S(S(S(A_k))), \ldots`.
|
152 |
+
|
153 |
+
Wynn's epsilon algorithm provides an efficient way to generate
|
154 |
+
the table of iterated Shanks transformations. It reduces the
|
155 |
+
computation of each element to essentially a single division, at
|
156 |
+
the cost of requiring dummy elements in the table. See [1] for
|
157 |
+
details.
|
158 |
+
|
159 |
+
**Precision issues**
|
160 |
+
|
161 |
+
Due to cancellation effects, the sequence must be typically be
|
162 |
+
computed at a much higher precision than the target accuracy
|
163 |
+
of the extrapolation.
|
164 |
+
|
165 |
+
If the Shanks transformation converges to the exact limit (such
|
166 |
+
as if the sequence is a geometric series), then a division by
|
167 |
+
zero occurs. By default, :func:`~mpmath.shanks` handles this case by
|
168 |
+
terminating the iteration and returning the table it has
|
169 |
+
generated so far. With *randomized=True*, it will instead
|
170 |
+
replace the zero by a pseudorandom number close to zero.
|
171 |
+
(TODO: find a better solution to this problem.)
|
172 |
+
|
173 |
+
**Examples**
|
174 |
+
|
175 |
+
We illustrate by applying Shanks transformation to the Leibniz
|
176 |
+
series for `\pi`::
|
177 |
+
|
178 |
+
>>> from mpmath import *
|
179 |
+
>>> mp.dps = 50
|
180 |
+
>>> S = [4*sum(mpf(-1)**n/(2*n+1) for n in range(m))
|
181 |
+
... for m in range(1,30)]
|
182 |
+
>>>
|
183 |
+
>>> T = shanks(S[:7])
|
184 |
+
>>> for row in T:
|
185 |
+
... nprint(row)
|
186 |
+
...
|
187 |
+
[-0.75]
|
188 |
+
[1.25, 3.16667]
|
189 |
+
[-1.75, 3.13333, -28.75]
|
190 |
+
[2.25, 3.14524, 82.25, 3.14234]
|
191 |
+
[-2.75, 3.13968, -177.75, 3.14139, -969.937]
|
192 |
+
[3.25, 3.14271, 327.25, 3.14166, 3515.06, 3.14161]
|
193 |
+
|
194 |
+
The extrapolated accuracy is about 4 digits, and about 4 digits
|
195 |
+
may have been lost due to cancellation::
|
196 |
+
|
197 |
+
>>> L = T[-1]
|
198 |
+
>>> nprint([abs(L[-1] - pi), abs(L[-1] - L[-3]), abs(L[-2])])
|
199 |
+
[2.22532e-5, 4.78309e-5, 3515.06]
|
200 |
+
|
201 |
+
Now we extend the computation::
|
202 |
+
|
203 |
+
>>> T = shanks(S[:25], T)
|
204 |
+
>>> L = T[-1]
|
205 |
+
>>> nprint([abs(L[-1] - pi), abs(L[-1] - L[-3]), abs(L[-2])])
|
206 |
+
[3.75527e-19, 1.48478e-19, 2.96014e+17]
|
207 |
+
|
208 |
+
The value for pi is now accurate to 18 digits. About 18 digits may
|
209 |
+
also have been lost to cancellation.
|
210 |
+
|
211 |
+
Here is an example with a geometric series, where the convergence
|
212 |
+
is immediate (the sum is exactly 1)::
|
213 |
+
|
214 |
+
>>> mp.dps = 15
|
215 |
+
>>> for row in shanks([0.5, 0.75, 0.875, 0.9375, 0.96875]):
|
216 |
+
... nprint(row)
|
217 |
+
[4.0]
|
218 |
+
[8.0, 1.0]
|
219 |
+
|
220 |
+
**References**
|
221 |
+
|
222 |
+
1. [GravesMorris]_
|
223 |
+
|
224 |
+
2. [BenderOrszag]_ pp. 368-375
|
225 |
+
|
226 |
+
"""
|
227 |
+
if len(seq) < 2:
|
228 |
+
raise ValueError("seq should be of minimum length 2")
|
229 |
+
if table:
|
230 |
+
START = len(table)
|
231 |
+
else:
|
232 |
+
START = 0
|
233 |
+
table = []
|
234 |
+
STOP = len(seq) - 1
|
235 |
+
if STOP & 1:
|
236 |
+
STOP -= 1
|
237 |
+
one = ctx.one
|
238 |
+
eps = +ctx.eps
|
239 |
+
if randomized:
|
240 |
+
from random import Random
|
241 |
+
rnd = Random()
|
242 |
+
rnd.seed(START)
|
243 |
+
for i in xrange(START, STOP):
|
244 |
+
row = []
|
245 |
+
for j in xrange(i+1):
|
246 |
+
if j == 0:
|
247 |
+
a, b = 0, seq[i+1]-seq[i]
|
248 |
+
else:
|
249 |
+
if j == 1:
|
250 |
+
a = seq[i]
|
251 |
+
else:
|
252 |
+
a = table[i-1][j-2]
|
253 |
+
b = row[j-1] - table[i-1][j-1]
|
254 |
+
if not b:
|
255 |
+
if randomized:
|
256 |
+
b = (1 + rnd.getrandbits(10))*eps
|
257 |
+
elif i & 1:
|
258 |
+
return table[:-1]
|
259 |
+
else:
|
260 |
+
return table
|
261 |
+
row.append(a + one/b)
|
262 |
+
table.append(row)
|
263 |
+
return table
|
264 |
+
|
265 |
+
|
266 |
+
class levin_class:
|
267 |
+
# levin: Copyright 2013 Timo Hartmann (thartmann15 at gmail.com)
|
268 |
+
r"""
|
269 |
+
This interface implements Levin's (nonlinear) sequence transformation for
|
270 |
+
convergence acceleration and summation of divergent series. It performs
|
271 |
+
better than the Shanks/Wynn-epsilon algorithm for logarithmic convergent
|
272 |
+
or alternating divergent series.
|
273 |
+
|
274 |
+
Let *A* be the series we want to sum:
|
275 |
+
|
276 |
+
.. math ::
|
277 |
+
|
278 |
+
A = \sum_{k=0}^{\infty} a_k
|
279 |
+
|
280 |
+
Attention: all `a_k` must be non-zero!
|
281 |
+
|
282 |
+
Let `s_n` be the partial sums of this series:
|
283 |
+
|
284 |
+
.. math ::
|
285 |
+
|
286 |
+
s_n = \sum_{k=0}^n a_k.
|
287 |
+
|
288 |
+
**Methods**
|
289 |
+
|
290 |
+
Calling ``levin`` returns an object with the following methods.
|
291 |
+
|
292 |
+
``update(...)`` works with the list of individual terms `a_k` of *A*, and
|
293 |
+
``update_step(...)`` works with the list of partial sums `s_k` of *A*:
|
294 |
+
|
295 |
+
.. code ::
|
296 |
+
|
297 |
+
v, e = ...update([a_0, a_1,..., a_k])
|
298 |
+
v, e = ...update_psum([s_0, s_1,..., s_k])
|
299 |
+
|
300 |
+
``step(...)`` works with the individual terms `a_k` and ``step_psum(...)``
|
301 |
+
works with the partial sums `s_k`:
|
302 |
+
|
303 |
+
.. code ::
|
304 |
+
|
305 |
+
v, e = ...step(a_k)
|
306 |
+
v, e = ...step_psum(s_k)
|
307 |
+
|
308 |
+
*v* is the current estimate for *A*, and *e* is an error estimate which is
|
309 |
+
simply the difference between the current estimate and the last estimate.
|
310 |
+
One should not mix ``update``, ``update_psum``, ``step`` and ``step_psum``.
|
311 |
+
|
312 |
+
**A word of caution**
|
313 |
+
|
314 |
+
One can only hope for good results (i.e. convergence acceleration or
|
315 |
+
resummation) if the `s_n` have some well defind asymptotic behavior for
|
316 |
+
large `n` and are not erratic or random. Furthermore one usually needs very
|
317 |
+
high working precision because of the numerical cancellation. If the working
|
318 |
+
precision is insufficient, levin may produce silently numerical garbage.
|
319 |
+
Furthermore even if the Levin-transformation converges, in the general case
|
320 |
+
there is no proof that the result is mathematically sound. Only for very
|
321 |
+
special classes of problems one can prove that the Levin-transformation
|
322 |
+
converges to the expected result (for example Stieltjes-type integrals).
|
323 |
+
Furthermore the Levin-transform is quite expensive (i.e. slow) in comparison
|
324 |
+
to Shanks/Wynn-epsilon, Richardson & co.
|
325 |
+
In summary one can say that the Levin-transformation is powerful but
|
326 |
+
unreliable and that it may need a copious amount of working precision.
|
327 |
+
|
328 |
+
The Levin transform has several variants differing in the choice of weights.
|
329 |
+
Some variants are better suited for the possible flavours of convergence
|
330 |
+
behaviour of *A* than other variants:
|
331 |
+
|
332 |
+
.. code ::
|
333 |
+
|
334 |
+
convergence behaviour levin-u levin-t levin-v shanks/wynn-epsilon
|
335 |
+
|
336 |
+
logarithmic + - + -
|
337 |
+
linear + + + +
|
338 |
+
alternating divergent + + + +
|
339 |
+
|
340 |
+
"+" means the variant is suitable,"-" means the variant is not suitable;
|
341 |
+
for comparison the Shanks/Wynn-epsilon transform is listed, too.
|
342 |
+
|
343 |
+
The variant is controlled though the variant keyword (i.e. ``variant="u"``,
|
344 |
+
``variant="t"`` or ``variant="v"``). Overall "u" is probably the best choice.
|
345 |
+
|
346 |
+
Finally it is possible to use the Sidi-S transform instead of the Levin transform
|
347 |
+
by using the keyword ``method='sidi'``. The Sidi-S transform works better than the
|
348 |
+
Levin transformation for some divergent series (see the examples).
|
349 |
+
|
350 |
+
Parameters:
|
351 |
+
|
352 |
+
.. code ::
|
353 |
+
|
354 |
+
method "levin" or "sidi" chooses either the Levin or the Sidi-S transformation
|
355 |
+
variant "u","t" or "v" chooses the weight variant.
|
356 |
+
|
357 |
+
The Levin transform is also accessible through the nsum interface.
|
358 |
+
``method="l"`` or ``method="levin"`` select the normal Levin transform while
|
359 |
+
``method="sidi"``
|
360 |
+
selects the Sidi-S transform. The variant is in both cases selected through the
|
361 |
+
levin_variant keyword. The stepsize in :func:`~mpmath.nsum` must not be chosen too large, otherwise
|
362 |
+
it will miss the point where the Levin transform converges resulting in numerical
|
363 |
+
overflow/garbage. For highly divergent series a copious amount of working precision
|
364 |
+
must be chosen.
|
365 |
+
|
366 |
+
**Examples**
|
367 |
+
|
368 |
+
First we sum the zeta function::
|
369 |
+
|
370 |
+
>>> from mpmath import mp
|
371 |
+
>>> mp.prec = 53
|
372 |
+
>>> eps = mp.mpf(mp.eps)
|
373 |
+
>>> with mp.extraprec(2 * mp.prec): # levin needs a high working precision
|
374 |
+
... L = mp.levin(method = "levin", variant = "u")
|
375 |
+
... S, s, n = [], 0, 1
|
376 |
+
... while 1:
|
377 |
+
... s += mp.one / (n * n)
|
378 |
+
... n += 1
|
379 |
+
... S.append(s)
|
380 |
+
... v, e = L.update_psum(S)
|
381 |
+
... if e < eps:
|
382 |
+
... break
|
383 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
384 |
+
>>> print(mp.chop(v - mp.pi ** 2 / 6))
|
385 |
+
0.0
|
386 |
+
>>> w = mp.nsum(lambda n: 1 / (n*n), [1, mp.inf], method = "levin", levin_variant = "u")
|
387 |
+
>>> print(mp.chop(v - w))
|
388 |
+
0.0
|
389 |
+
|
390 |
+
Now we sum the zeta function outside its range of convergence
|
391 |
+
(attention: This does not work at the negative integers!)::
|
392 |
+
|
393 |
+
>>> eps = mp.mpf(mp.eps)
|
394 |
+
>>> with mp.extraprec(2 * mp.prec): # levin needs a high working precision
|
395 |
+
... L = mp.levin(method = "levin", variant = "v")
|
396 |
+
... A, n = [], 1
|
397 |
+
... while 1:
|
398 |
+
... s = mp.mpf(n) ** (2 + 3j)
|
399 |
+
... n += 1
|
400 |
+
... A.append(s)
|
401 |
+
... v, e = L.update(A)
|
402 |
+
... if e < eps:
|
403 |
+
... break
|
404 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
405 |
+
>>> print(mp.chop(v - mp.zeta(-2-3j)))
|
406 |
+
0.0
|
407 |
+
>>> w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v")
|
408 |
+
>>> print(mp.chop(v - w))
|
409 |
+
0.0
|
410 |
+
|
411 |
+
Now we sum the divergent asymptotic expansion of an integral related to the
|
412 |
+
exponential integral (see also [2] p.373). The Sidi-S transform works best here::
|
413 |
+
|
414 |
+
>>> z = mp.mpf(10)
|
415 |
+
>>> exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf])
|
416 |
+
>>> # exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral
|
417 |
+
>>> eps = mp.mpf(mp.eps)
|
418 |
+
>>> with mp.extraprec(2 * mp.prec): # high working precisions are mandatory for divergent resummation
|
419 |
+
... L = mp.levin(method = "sidi", variant = "t")
|
420 |
+
... n = 0
|
421 |
+
... while 1:
|
422 |
+
... s = (-1)**n * mp.fac(n) * z ** (-n)
|
423 |
+
... v, e = L.step(s)
|
424 |
+
... n += 1
|
425 |
+
... if e < eps:
|
426 |
+
... break
|
427 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
428 |
+
>>> print(mp.chop(v - exact))
|
429 |
+
0.0
|
430 |
+
>>> w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t")
|
431 |
+
>>> print(mp.chop(v - w))
|
432 |
+
0.0
|
433 |
+
|
434 |
+
Another highly divergent integral is also summable::
|
435 |
+
|
436 |
+
>>> z = mp.mpf(2)
|
437 |
+
>>> eps = mp.mpf(mp.eps)
|
438 |
+
>>> exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi)
|
439 |
+
>>> # exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi)) # this is the symbolic expression for the integral
|
440 |
+
>>> with mp.extraprec(7 * mp.prec): # we need copious amount of precision to sum this highly divergent series
|
441 |
+
... L = mp.levin(method = "levin", variant = "t")
|
442 |
+
... n, s = 0, 0
|
443 |
+
... while 1:
|
444 |
+
... s += (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n))
|
445 |
+
... n += 1
|
446 |
+
... v, e = L.step_psum(s)
|
447 |
+
... if e < eps:
|
448 |
+
... break
|
449 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
450 |
+
>>> print(mp.chop(v - exact))
|
451 |
+
0.0
|
452 |
+
>>> w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)),
|
453 |
+
... [0, mp.inf], method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in xrange(1000)])
|
454 |
+
>>> print(mp.chop(v - w))
|
455 |
+
0.0
|
456 |
+
|
457 |
+
These examples run with 15-20 decimal digits precision. For higher precision the
|
458 |
+
working precision must be raised.
|
459 |
+
|
460 |
+
**Examples for nsum**
|
461 |
+
|
462 |
+
Here we calculate Euler's constant as the constant term in the Laurent
|
463 |
+
expansion of `\zeta(s)` at `s=1`. This sum converges extremly slowly because of
|
464 |
+
the logarithmic convergence behaviour of the Dirichlet series for zeta::
|
465 |
+
|
466 |
+
>>> mp.dps = 30
|
467 |
+
>>> z = mp.mpf(10) ** (-10)
|
468 |
+
>>> a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "l") - 1 / z
|
469 |
+
>>> print(mp.chop(a - mp.euler, tol = 1e-10))
|
470 |
+
0.0
|
471 |
+
|
472 |
+
The Sidi-S transform performs excellently for the alternating series of `\log(2)`::
|
473 |
+
|
474 |
+
>>> a = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "sidi")
|
475 |
+
>>> print(mp.chop(a - mp.log(2)))
|
476 |
+
0.0
|
477 |
+
|
478 |
+
Hypergeometric series can also be summed outside their range of convergence.
|
479 |
+
The stepsize in :func:`~mpmath.nsum` must not be chosen too large, otherwise it will miss the
|
480 |
+
point where the Levin transform converges resulting in numerical overflow/garbage::
|
481 |
+
|
482 |
+
>>> z = 2 + 1j
|
483 |
+
>>> exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z)
|
484 |
+
>>> f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n))
|
485 |
+
>>> v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in xrange(1000)])
|
486 |
+
>>> print(mp.chop(exact-v))
|
487 |
+
0.0
|
488 |
+
|
489 |
+
References:
|
490 |
+
|
491 |
+
[1] E.J. Weniger - "Nonlinear Sequence Transformations for the Acceleration of
|
492 |
+
Convergence and the Summation of Divergent Series" arXiv:math/0306302
|
493 |
+
|
494 |
+
[2] A. Sidi - "Pratical Extrapolation Methods"
|
495 |
+
|
496 |
+
[3] H.H.H. Homeier - "Scalar Levin-Type Sequence Transformations" arXiv:math/0005209
|
497 |
+
|
498 |
+
"""
|
499 |
+
|
500 |
+
def __init__(self, method = "levin", variant = "u"):
|
501 |
+
self.variant = variant
|
502 |
+
self.n = 0
|
503 |
+
self.a0 = 0
|
504 |
+
self.theta = 1
|
505 |
+
self.A = []
|
506 |
+
self.B = []
|
507 |
+
self.last = 0
|
508 |
+
self.last_s = False
|
509 |
+
|
510 |
+
if method == "levin":
|
511 |
+
self.factor = self.factor_levin
|
512 |
+
elif method == "sidi":
|
513 |
+
self.factor = self.factor_sidi
|
514 |
+
else:
|
515 |
+
raise ValueError("levin: unknown method \"%s\"" % method)
|
516 |
+
|
517 |
+
def factor_levin(self, i):
|
518 |
+
# original levin
|
519 |
+
# [1] p.50,e.7.5-7 (with n-j replaced by i)
|
520 |
+
return (self.theta + i) * (self.theta + self.n - 1) ** (self.n - i - 2) / self.ctx.mpf(self.theta + self.n) ** (self.n - i - 1)
|
521 |
+
|
522 |
+
def factor_sidi(self, i):
|
523 |
+
# sidi analogon to levin (factorial series)
|
524 |
+
# [1] p.59,e.8.3-16 (with n-j replaced by i)
|
525 |
+
return (self.theta + self.n - 1) * (self.theta + self.n - 2) / self.ctx.mpf((self.theta + 2 * self.n - i - 2) * (self.theta + 2 * self.n - i - 3))
|
526 |
+
|
527 |
+
def run(self, s, a0, a1 = 0):
|
528 |
+
if self.variant=="t":
|
529 |
+
# levin t
|
530 |
+
w=a0
|
531 |
+
elif self.variant=="u":
|
532 |
+
# levin u
|
533 |
+
w=a0*(self.theta+self.n)
|
534 |
+
elif self.variant=="v":
|
535 |
+
# levin v
|
536 |
+
w=a0*a1/(a0-a1)
|
537 |
+
else:
|
538 |
+
assert False, "unknown variant"
|
539 |
+
|
540 |
+
if w==0:
|
541 |
+
raise ValueError("levin: zero weight")
|
542 |
+
|
543 |
+
self.A.append(s/w)
|
544 |
+
self.B.append(1/w)
|
545 |
+
|
546 |
+
for i in range(self.n-1,-1,-1):
|
547 |
+
if i==self.n-1:
|
548 |
+
f=1
|
549 |
+
else:
|
550 |
+
f=self.factor(i)
|
551 |
+
|
552 |
+
self.A[i]=self.A[i+1]-f*self.A[i]
|
553 |
+
self.B[i]=self.B[i+1]-f*self.B[i]
|
554 |
+
|
555 |
+
self.n+=1
|
556 |
+
|
557 |
+
###########################################################################
|
558 |
+
|
559 |
+
def update_psum(self,S):
|
560 |
+
"""
|
561 |
+
This routine applies the convergence acceleration to the list of partial sums.
|
562 |
+
|
563 |
+
A = sum(a_k, k = 0..infinity)
|
564 |
+
s_n = sum(a_k, k = 0..n)
|
565 |
+
|
566 |
+
v, e = ...update_psum([s_0, s_1,..., s_k])
|
567 |
+
|
568 |
+
output:
|
569 |
+
v current estimate of the series A
|
570 |
+
e an error estimate which is simply the difference between the current
|
571 |
+
estimate and the last estimate.
|
572 |
+
"""
|
573 |
+
|
574 |
+
if self.variant!="v":
|
575 |
+
if self.n==0:
|
576 |
+
self.run(S[0],S[0])
|
577 |
+
while self.n<len(S):
|
578 |
+
self.run(S[self.n],S[self.n]-S[self.n-1])
|
579 |
+
else:
|
580 |
+
if len(S)==1:
|
581 |
+
self.last=0
|
582 |
+
return S[0],abs(S[0])
|
583 |
+
|
584 |
+
if self.n==0:
|
585 |
+
self.a1=S[1]-S[0]
|
586 |
+
self.run(S[0],S[0],self.a1)
|
587 |
+
|
588 |
+
while self.n<len(S)-1:
|
589 |
+
na1=S[self.n+1]-S[self.n]
|
590 |
+
self.run(S[self.n],self.a1,na1)
|
591 |
+
self.a1=na1
|
592 |
+
|
593 |
+
value=self.A[0]/self.B[0]
|
594 |
+
err=abs(value-self.last)
|
595 |
+
self.last=value
|
596 |
+
|
597 |
+
return value,err
|
598 |
+
|
599 |
+
def update(self,X):
|
600 |
+
"""
|
601 |
+
This routine applies the convergence acceleration to the list of individual terms.
|
602 |
+
|
603 |
+
A = sum(a_k, k = 0..infinity)
|
604 |
+
|
605 |
+
v, e = ...update([a_0, a_1,..., a_k])
|
606 |
+
|
607 |
+
output:
|
608 |
+
v current estimate of the series A
|
609 |
+
e an error estimate which is simply the difference between the current
|
610 |
+
estimate and the last estimate.
|
611 |
+
"""
|
612 |
+
|
613 |
+
if self.variant!="v":
|
614 |
+
if self.n==0:
|
615 |
+
self.s=X[0]
|
616 |
+
self.run(self.s,X[0])
|
617 |
+
while self.n<len(X):
|
618 |
+
self.s+=X[self.n]
|
619 |
+
self.run(self.s,X[self.n])
|
620 |
+
else:
|
621 |
+
if len(X)==1:
|
622 |
+
self.last=0
|
623 |
+
return X[0],abs(X[0])
|
624 |
+
|
625 |
+
if self.n==0:
|
626 |
+
self.s=X[0]
|
627 |
+
self.run(self.s,X[0],X[1])
|
628 |
+
|
629 |
+
while self.n<len(X)-1:
|
630 |
+
self.s+=X[self.n]
|
631 |
+
self.run(self.s,X[self.n],X[self.n+1])
|
632 |
+
|
633 |
+
value=self.A[0]/self.B[0]
|
634 |
+
err=abs(value-self.last)
|
635 |
+
self.last=value
|
636 |
+
|
637 |
+
return value,err
|
638 |
+
|
639 |
+
###########################################################################
|
640 |
+
|
641 |
+
def step_psum(self,s):
|
642 |
+
"""
|
643 |
+
This routine applies the convergence acceleration to the partial sums.
|
644 |
+
|
645 |
+
A = sum(a_k, k = 0..infinity)
|
646 |
+
s_n = sum(a_k, k = 0..n)
|
647 |
+
|
648 |
+
v, e = ...step_psum(s_k)
|
649 |
+
|
650 |
+
output:
|
651 |
+
v current estimate of the series A
|
652 |
+
e an error estimate which is simply the difference between the current
|
653 |
+
estimate and the last estimate.
|
654 |
+
"""
|
655 |
+
|
656 |
+
if self.variant!="v":
|
657 |
+
if self.n==0:
|
658 |
+
self.last_s=s
|
659 |
+
self.run(s,s)
|
660 |
+
else:
|
661 |
+
self.run(s,s-self.last_s)
|
662 |
+
self.last_s=s
|
663 |
+
else:
|
664 |
+
if isinstance(self.last_s,bool):
|
665 |
+
self.last_s=s
|
666 |
+
self.last_w=s
|
667 |
+
self.last=0
|
668 |
+
return s,abs(s)
|
669 |
+
|
670 |
+
na1=s-self.last_s
|
671 |
+
self.run(self.last_s,self.last_w,na1)
|
672 |
+
self.last_w=na1
|
673 |
+
self.last_s=s
|
674 |
+
|
675 |
+
value=self.A[0]/self.B[0]
|
676 |
+
err=abs(value-self.last)
|
677 |
+
self.last=value
|
678 |
+
|
679 |
+
return value,err
|
680 |
+
|
681 |
+
def step(self,x):
|
682 |
+
"""
|
683 |
+
This routine applies the convergence acceleration to the individual terms.
|
684 |
+
|
685 |
+
A = sum(a_k, k = 0..infinity)
|
686 |
+
|
687 |
+
v, e = ...step(a_k)
|
688 |
+
|
689 |
+
output:
|
690 |
+
v current estimate of the series A
|
691 |
+
e an error estimate which is simply the difference between the current
|
692 |
+
estimate and the last estimate.
|
693 |
+
"""
|
694 |
+
|
695 |
+
if self.variant!="v":
|
696 |
+
if self.n==0:
|
697 |
+
self.s=x
|
698 |
+
self.run(self.s,x)
|
699 |
+
else:
|
700 |
+
self.s+=x
|
701 |
+
self.run(self.s,x)
|
702 |
+
else:
|
703 |
+
if isinstance(self.last_s,bool):
|
704 |
+
self.last_s=x
|
705 |
+
self.s=0
|
706 |
+
self.last=0
|
707 |
+
return x,abs(x)
|
708 |
+
|
709 |
+
self.s+=self.last_s
|
710 |
+
self.run(self.s,self.last_s,x)
|
711 |
+
self.last_s=x
|
712 |
+
|
713 |
+
value=self.A[0]/self.B[0]
|
714 |
+
err=abs(value-self.last)
|
715 |
+
self.last=value
|
716 |
+
|
717 |
+
return value,err
|
718 |
+
|
719 |
+
def levin(ctx, method = "levin", variant = "u"):
|
720 |
+
L = levin_class(method = method, variant = variant)
|
721 |
+
L.ctx = ctx
|
722 |
+
return L
|
723 |
+
|
724 |
+
levin.__doc__ = levin_class.__doc__
|
725 |
+
defun(levin)
|
726 |
+
|
727 |
+
|
728 |
+
class cohen_alt_class:
|
729 |
+
# cohen_alt: Copyright 2013 Timo Hartmann (thartmann15 at gmail.com)
|
730 |
+
r"""
|
731 |
+
This interface implements the convergence acceleration of alternating series
|
732 |
+
as described in H. Cohen, F.R. Villegas, D. Zagier - "Convergence Acceleration
|
733 |
+
of Alternating Series". This series transformation works only well if the
|
734 |
+
individual terms of the series have an alternating sign. It belongs to the
|
735 |
+
class of linear series transformations (in contrast to the Shanks/Wynn-epsilon
|
736 |
+
or Levin transform). This series transformation is also able to sum some types
|
737 |
+
of divergent series. See the paper under which conditions this resummation is
|
738 |
+
mathematical sound.
|
739 |
+
|
740 |
+
Let *A* be the series we want to sum:
|
741 |
+
|
742 |
+
.. math ::
|
743 |
+
|
744 |
+
A = \sum_{k=0}^{\infty} a_k
|
745 |
+
|
746 |
+
Let `s_n` be the partial sums of this series:
|
747 |
+
|
748 |
+
.. math ::
|
749 |
+
|
750 |
+
s_n = \sum_{k=0}^n a_k.
|
751 |
+
|
752 |
+
|
753 |
+
**Interface**
|
754 |
+
|
755 |
+
Calling ``cohen_alt`` returns an object with the following methods.
|
756 |
+
|
757 |
+
Then ``update(...)`` works with the list of individual terms `a_k` and
|
758 |
+
``update_psum(...)`` works with the list of partial sums `s_k`:
|
759 |
+
|
760 |
+
.. code ::
|
761 |
+
|
762 |
+
v, e = ...update([a_0, a_1,..., a_k])
|
763 |
+
v, e = ...update_psum([s_0, s_1,..., s_k])
|
764 |
+
|
765 |
+
*v* is the current estimate for *A*, and *e* is an error estimate which is
|
766 |
+
simply the difference between the current estimate and the last estimate.
|
767 |
+
|
768 |
+
**Examples**
|
769 |
+
|
770 |
+
Here we compute the alternating zeta function using ``update_psum``::
|
771 |
+
|
772 |
+
>>> from mpmath import mp
|
773 |
+
>>> AC = mp.cohen_alt()
|
774 |
+
>>> S, s, n = [], 0, 1
|
775 |
+
>>> while 1:
|
776 |
+
... s += -((-1) ** n) * mp.one / (n * n)
|
777 |
+
... n += 1
|
778 |
+
... S.append(s)
|
779 |
+
... v, e = AC.update_psum(S)
|
780 |
+
... if e < mp.eps:
|
781 |
+
... break
|
782 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
783 |
+
>>> print(mp.chop(v - mp.pi ** 2 / 12))
|
784 |
+
0.0
|
785 |
+
|
786 |
+
Here we compute the product `\prod_{n=1}^{\infty} \Gamma(1+1/(2n-1)) / \Gamma(1+1/(2n))`::
|
787 |
+
|
788 |
+
>>> A = []
|
789 |
+
>>> AC = mp.cohen_alt()
|
790 |
+
>>> n = 1
|
791 |
+
>>> while 1:
|
792 |
+
... A.append( mp.loggamma(1 + mp.one / (2 * n - 1)))
|
793 |
+
... A.append(-mp.loggamma(1 + mp.one / (2 * n)))
|
794 |
+
... n += 1
|
795 |
+
... v, e = AC.update(A)
|
796 |
+
... if e < mp.eps:
|
797 |
+
... break
|
798 |
+
... if n > 1000: raise RuntimeError("iteration limit exceeded")
|
799 |
+
>>> v = mp.exp(v)
|
800 |
+
>>> print(mp.chop(v - 1.06215090557106, tol = 1e-12))
|
801 |
+
0.0
|
802 |
+
|
803 |
+
``cohen_alt`` is also accessible through the :func:`~mpmath.nsum` interface::
|
804 |
+
|
805 |
+
>>> v = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "a")
|
806 |
+
>>> print(mp.chop(v - mp.log(2)))
|
807 |
+
0.0
|
808 |
+
>>> v = mp.nsum(lambda n: (-1)**n / (2 * n + 1), [0, mp.inf], method = "a")
|
809 |
+
>>> print(mp.chop(v - mp.pi / 4))
|
810 |
+
0.0
|
811 |
+
>>> v = mp.nsum(lambda n: (-1)**n * mp.log(n) * n, [1, mp.inf], method = "a")
|
812 |
+
>>> print(mp.chop(v - mp.diff(lambda s: mp.altzeta(s), -1)))
|
813 |
+
0.0
|
814 |
+
|
815 |
+
"""
|
816 |
+
|
817 |
+
def __init__(self):
|
818 |
+
self.last=0
|
819 |
+
|
820 |
+
def update(self, A):
|
821 |
+
"""
|
822 |
+
This routine applies the convergence acceleration to the list of individual terms.
|
823 |
+
|
824 |
+
A = sum(a_k, k = 0..infinity)
|
825 |
+
|
826 |
+
v, e = ...update([a_0, a_1,..., a_k])
|
827 |
+
|
828 |
+
output:
|
829 |
+
v current estimate of the series A
|
830 |
+
e an error estimate which is simply the difference between the current
|
831 |
+
estimate and the last estimate.
|
832 |
+
"""
|
833 |
+
|
834 |
+
n = len(A)
|
835 |
+
d = (3 + self.ctx.sqrt(8)) ** n
|
836 |
+
d = (d + 1 / d) / 2
|
837 |
+
b = -self.ctx.one
|
838 |
+
c = -d
|
839 |
+
s = 0
|
840 |
+
|
841 |
+
for k in xrange(n):
|
842 |
+
c = b - c
|
843 |
+
if k % 2 == 0:
|
844 |
+
s = s + c * A[k]
|
845 |
+
else:
|
846 |
+
s = s - c * A[k]
|
847 |
+
b = 2 * (k + n) * (k - n) * b / ((2 * k + 1) * (k + self.ctx.one))
|
848 |
+
|
849 |
+
value = s / d
|
850 |
+
|
851 |
+
err = abs(value - self.last)
|
852 |
+
self.last = value
|
853 |
+
|
854 |
+
return value, err
|
855 |
+
|
856 |
+
def update_psum(self, S):
|
857 |
+
"""
|
858 |
+
This routine applies the convergence acceleration to the list of partial sums.
|
859 |
+
|
860 |
+
A = sum(a_k, k = 0..infinity)
|
861 |
+
s_n = sum(a_k ,k = 0..n)
|
862 |
+
|
863 |
+
v, e = ...update_psum([s_0, s_1,..., s_k])
|
864 |
+
|
865 |
+
output:
|
866 |
+
v current estimate of the series A
|
867 |
+
e an error estimate which is simply the difference between the current
|
868 |
+
estimate and the last estimate.
|
869 |
+
"""
|
870 |
+
|
871 |
+
n = len(S)
|
872 |
+
d = (3 + self.ctx.sqrt(8)) ** n
|
873 |
+
d = (d + 1 / d) / 2
|
874 |
+
b = self.ctx.one
|
875 |
+
s = 0
|
876 |
+
|
877 |
+
for k in xrange(n):
|
878 |
+
b = 2 * (n + k) * (n - k) * b / ((2 * k + 1) * (k + self.ctx.one))
|
879 |
+
s += b * S[k]
|
880 |
+
|
881 |
+
value = s / d
|
882 |
+
|
883 |
+
err = abs(value - self.last)
|
884 |
+
self.last = value
|
885 |
+
|
886 |
+
return value, err
|
887 |
+
|
888 |
+
def cohen_alt(ctx):
|
889 |
+
L = cohen_alt_class()
|
890 |
+
L.ctx = ctx
|
891 |
+
return L
|
892 |
+
|
893 |
+
cohen_alt.__doc__ = cohen_alt_class.__doc__
|
894 |
+
defun(cohen_alt)
|
895 |
+
|
896 |
+
|
897 |
+
@defun
|
898 |
+
def sumap(ctx, f, interval, integral=None, error=False):
|
899 |
+
r"""
|
900 |
+
Evaluates an infinite series of an analytic summand *f* using the
|
901 |
+
Abel-Plana formula
|
902 |
+
|
903 |
+
.. math ::
|
904 |
+
|
905 |
+
\sum_{k=0}^{\infty} f(k) = \int_0^{\infty} f(t) dt + \frac{1}{2} f(0) +
|
906 |
+
i \int_0^{\infty} \frac{f(it)-f(-it)}{e^{2\pi t}-1} dt.
|
907 |
+
|
908 |
+
Unlike the Euler-Maclaurin formula (see :func:`~mpmath.sumem`),
|
909 |
+
the Abel-Plana formula does not require derivatives. However,
|
910 |
+
it only works when `|f(it)-f(-it)|` does not
|
911 |
+
increase too rapidly with `t`.
|
912 |
+
|
913 |
+
**Examples**
|
914 |
+
|
915 |
+
The Abel-Plana formula is particularly useful when the summand
|
916 |
+
decreases like a power of `k`; for example when the sum is a pure
|
917 |
+
zeta function::
|
918 |
+
|
919 |
+
>>> from mpmath import *
|
920 |
+
>>> mp.dps = 25; mp.pretty = True
|
921 |
+
>>> sumap(lambda k: 1/k**2.5, [1,inf])
|
922 |
+
1.34148725725091717975677
|
923 |
+
>>> zeta(2.5)
|
924 |
+
1.34148725725091717975677
|
925 |
+
>>> sumap(lambda k: 1/(k+1j)**(2.5+2.5j), [1,inf])
|
926 |
+
(-3.385361068546473342286084 - 0.7432082105196321803869551j)
|
927 |
+
>>> zeta(2.5+2.5j, 1+1j)
|
928 |
+
(-3.385361068546473342286084 - 0.7432082105196321803869551j)
|
929 |
+
|
930 |
+
If the series is alternating, numerical quadrature along the real
|
931 |
+
line is likely to give poor results, so it is better to evaluate
|
932 |
+
the first term symbolically whenever possible:
|
933 |
+
|
934 |
+
>>> n=3; z=-0.75
|
935 |
+
>>> I = expint(n,-log(z))
|
936 |
+
>>> chop(sumap(lambda k: z**k / k**n, [1,inf], integral=I))
|
937 |
+
-0.6917036036904594510141448
|
938 |
+
>>> polylog(n,z)
|
939 |
+
-0.6917036036904594510141448
|
940 |
+
|
941 |
+
"""
|
942 |
+
prec = ctx.prec
|
943 |
+
try:
|
944 |
+
ctx.prec += 10
|
945 |
+
a, b = interval
|
946 |
+
if b != ctx.inf:
|
947 |
+
raise ValueError("b should be equal to ctx.inf")
|
948 |
+
g = lambda x: f(x+a)
|
949 |
+
if integral is None:
|
950 |
+
i1, err1 = ctx.quad(g, [0,ctx.inf], error=True)
|
951 |
+
else:
|
952 |
+
i1, err1 = integral, 0
|
953 |
+
j = ctx.j
|
954 |
+
p = ctx.pi * 2
|
955 |
+
if ctx._is_real_type(i1):
|
956 |
+
h = lambda t: -2 * ctx.im(g(j*t)) / ctx.expm1(p*t)
|
957 |
+
else:
|
958 |
+
h = lambda t: j*(g(j*t)-g(-j*t)) / ctx.expm1(p*t)
|
959 |
+
i2, err2 = ctx.quad(h, [0,ctx.inf], error=True)
|
960 |
+
err = err1+err2
|
961 |
+
v = i1+i2+0.5*g(ctx.mpf(0))
|
962 |
+
finally:
|
963 |
+
ctx.prec = prec
|
964 |
+
if error:
|
965 |
+
return +v, err
|
966 |
+
return +v
|
967 |
+
|
968 |
+
|
969 |
+
@defun
|
970 |
+
def sumem(ctx, f, interval, tol=None, reject=10, integral=None,
|
971 |
+
adiffs=None, bdiffs=None, verbose=False, error=False,
|
972 |
+
_fast_abort=False):
|
973 |
+
r"""
|
974 |
+
Uses the Euler-Maclaurin formula to compute an approximation accurate
|
975 |
+
to within ``tol`` (which defaults to the present epsilon) of the sum
|
976 |
+
|
977 |
+
.. math ::
|
978 |
+
|
979 |
+
S = \sum_{k=a}^b f(k)
|
980 |
+
|
981 |
+
where `(a,b)` are given by ``interval`` and `a` or `b` may be
|
982 |
+
infinite. The approximation is
|
983 |
+
|
984 |
+
.. math ::
|
985 |
+
|
986 |
+
S \sim \int_a^b f(x) \,dx + \frac{f(a)+f(b)}{2} +
|
987 |
+
\sum_{k=1}^{\infty} \frac{B_{2k}}{(2k)!}
|
988 |
+
\left(f^{(2k-1)}(b)-f^{(2k-1)}(a)\right).
|
989 |
+
|
990 |
+
The last sum in the Euler-Maclaurin formula is not generally
|
991 |
+
convergent (a notable exception is if `f` is a polynomial, in
|
992 |
+
which case Euler-Maclaurin actually gives an exact result).
|
993 |
+
|
994 |
+
The summation is stopped as soon as the quotient between two
|
995 |
+
consecutive terms falls below *reject*. That is, by default
|
996 |
+
(*reject* = 10), the summation is continued as long as each
|
997 |
+
term adds at least one decimal.
|
998 |
+
|
999 |
+
Although not convergent, convergence to a given tolerance can
|
1000 |
+
often be "forced" if `b = \infty` by summing up to `a+N` and then
|
1001 |
+
applying the Euler-Maclaurin formula to the sum over the range
|
1002 |
+
`(a+N+1, \ldots, \infty)`. This procedure is implemented by
|
1003 |
+
:func:`~mpmath.nsum`.
|
1004 |
+
|
1005 |
+
By default numerical quadrature and differentiation is used.
|
1006 |
+
If the symbolic values of the integral and endpoint derivatives
|
1007 |
+
are known, it is more efficient to pass the value of the
|
1008 |
+
integral explicitly as ``integral`` and the derivatives
|
1009 |
+
explicitly as ``adiffs`` and ``bdiffs``. The derivatives
|
1010 |
+
should be given as iterables that yield
|
1011 |
+
`f(a), f'(a), f''(a), \ldots` (and the equivalent for `b`).
|
1012 |
+
|
1013 |
+
**Examples**
|
1014 |
+
|
1015 |
+
Summation of an infinite series, with automatic and symbolic
|
1016 |
+
integral and derivative values (the second should be much faster)::
|
1017 |
+
|
1018 |
+
>>> from mpmath import *
|
1019 |
+
>>> mp.dps = 50; mp.pretty = True
|
1020 |
+
>>> sumem(lambda n: 1/n**2, [32, inf])
|
1021 |
+
0.03174336652030209012658168043874142714132886413417
|
1022 |
+
>>> I = mpf(1)/32
|
1023 |
+
>>> D = adiffs=((-1)**n*fac(n+1)*32**(-2-n) for n in range(999))
|
1024 |
+
>>> sumem(lambda n: 1/n**2, [32, inf], integral=I, adiffs=D)
|
1025 |
+
0.03174336652030209012658168043874142714132886413417
|
1026 |
+
|
1027 |
+
An exact evaluation of a finite polynomial sum::
|
1028 |
+
|
1029 |
+
>>> sumem(lambda n: n**5-12*n**2+3*n, [-100000, 200000])
|
1030 |
+
10500155000624963999742499550000.0
|
1031 |
+
>>> print(sum(n**5-12*n**2+3*n for n in range(-100000, 200001)))
|
1032 |
+
10500155000624963999742499550000
|
1033 |
+
|
1034 |
+
"""
|
1035 |
+
tol = tol or +ctx.eps
|
1036 |
+
interval = ctx._as_points(interval)
|
1037 |
+
a = ctx.convert(interval[0])
|
1038 |
+
b = ctx.convert(interval[-1])
|
1039 |
+
err = ctx.zero
|
1040 |
+
prev = 0
|
1041 |
+
M = 10000
|
1042 |
+
if a == ctx.ninf: adiffs = (0 for n in xrange(M))
|
1043 |
+
else: adiffs = adiffs or ctx.diffs(f, a)
|
1044 |
+
if b == ctx.inf: bdiffs = (0 for n in xrange(M))
|
1045 |
+
else: bdiffs = bdiffs or ctx.diffs(f, b)
|
1046 |
+
orig = ctx.prec
|
1047 |
+
#verbose = 1
|
1048 |
+
try:
|
1049 |
+
ctx.prec += 10
|
1050 |
+
s = ctx.zero
|
1051 |
+
for k, (da, db) in enumerate(izip(adiffs, bdiffs)):
|
1052 |
+
if k & 1:
|
1053 |
+
term = (db-da) * ctx.bernoulli(k+1) / ctx.factorial(k+1)
|
1054 |
+
mag = abs(term)
|
1055 |
+
if verbose:
|
1056 |
+
print("term", k, "magnitude =", ctx.nstr(mag))
|
1057 |
+
if k > 4 and mag < tol:
|
1058 |
+
s += term
|
1059 |
+
break
|
1060 |
+
elif k > 4 and abs(prev) / mag < reject:
|
1061 |
+
err += mag
|
1062 |
+
if _fast_abort:
|
1063 |
+
return [s, (s, err)][error]
|
1064 |
+
if verbose:
|
1065 |
+
print("Failed to converge")
|
1066 |
+
break
|
1067 |
+
else:
|
1068 |
+
s += term
|
1069 |
+
prev = term
|
1070 |
+
# Endpoint correction
|
1071 |
+
if a != ctx.ninf: s += f(a)/2
|
1072 |
+
if b != ctx.inf: s += f(b)/2
|
1073 |
+
# Tail integral
|
1074 |
+
if verbose:
|
1075 |
+
print("Integrating f(x) from x = %s to %s" % (ctx.nstr(a), ctx.nstr(b)))
|
1076 |
+
if integral:
|
1077 |
+
s += integral
|
1078 |
+
else:
|
1079 |
+
integral, ierr = ctx.quad(f, interval, error=True)
|
1080 |
+
if verbose:
|
1081 |
+
print("Integration error:", ierr)
|
1082 |
+
s += integral
|
1083 |
+
err += ierr
|
1084 |
+
finally:
|
1085 |
+
ctx.prec = orig
|
1086 |
+
if error:
|
1087 |
+
return s, err
|
1088 |
+
else:
|
1089 |
+
return s
|
1090 |
+
|
1091 |
+
@defun
|
1092 |
+
def adaptive_extrapolation(ctx, update, emfun, kwargs):
|
1093 |
+
option = kwargs.get
|
1094 |
+
if ctx._fixed_precision:
|
1095 |
+
tol = option('tol', ctx.eps*2**10)
|
1096 |
+
else:
|
1097 |
+
tol = option('tol', ctx.eps/2**10)
|
1098 |
+
verbose = option('verbose', False)
|
1099 |
+
maxterms = option('maxterms', ctx.dps*10)
|
1100 |
+
method = set(option('method', 'r+s').split('+'))
|
1101 |
+
skip = option('skip', 0)
|
1102 |
+
steps = iter(option('steps', xrange(10, 10**9, 10)))
|
1103 |
+
strict = option('strict')
|
1104 |
+
#steps = (10 for i in xrange(1000))
|
1105 |
+
summer=[]
|
1106 |
+
if 'd' in method or 'direct' in method:
|
1107 |
+
TRY_RICHARDSON = TRY_SHANKS = TRY_EULER_MACLAURIN = False
|
1108 |
+
else:
|
1109 |
+
TRY_RICHARDSON = ('r' in method) or ('richardson' in method)
|
1110 |
+
TRY_SHANKS = ('s' in method) or ('shanks' in method)
|
1111 |
+
TRY_EULER_MACLAURIN = ('e' in method) or \
|
1112 |
+
('euler-maclaurin' in method)
|
1113 |
+
|
1114 |
+
def init_levin(m):
|
1115 |
+
variant = kwargs.get("levin_variant", "u")
|
1116 |
+
if isinstance(variant, str):
|
1117 |
+
if variant == "all":
|
1118 |
+
variant = ["u", "v", "t"]
|
1119 |
+
else:
|
1120 |
+
variant = [variant]
|
1121 |
+
for s in variant:
|
1122 |
+
L = levin_class(method = m, variant = s)
|
1123 |
+
L.ctx = ctx
|
1124 |
+
L.name = m + "(" + s + ")"
|
1125 |
+
summer.append(L)
|
1126 |
+
|
1127 |
+
if ('l' in method) or ('levin' in method):
|
1128 |
+
init_levin("levin")
|
1129 |
+
|
1130 |
+
if ('sidi' in method):
|
1131 |
+
init_levin("sidi")
|
1132 |
+
|
1133 |
+
if ('a' in method) or ('alternating' in method):
|
1134 |
+
L = cohen_alt_class()
|
1135 |
+
L.ctx = ctx
|
1136 |
+
L.name = "alternating"
|
1137 |
+
summer.append(L)
|
1138 |
+
|
1139 |
+
last_richardson_value = 0
|
1140 |
+
shanks_table = []
|
1141 |
+
index = 0
|
1142 |
+
step = 10
|
1143 |
+
partial = []
|
1144 |
+
best = ctx.zero
|
1145 |
+
orig = ctx.prec
|
1146 |
+
try:
|
1147 |
+
if 'workprec' in kwargs:
|
1148 |
+
ctx.prec = kwargs['workprec']
|
1149 |
+
elif TRY_RICHARDSON or TRY_SHANKS or len(summer)!=0:
|
1150 |
+
ctx.prec = (ctx.prec+10) * 4
|
1151 |
+
else:
|
1152 |
+
ctx.prec += 30
|
1153 |
+
while 1:
|
1154 |
+
if index >= maxterms:
|
1155 |
+
break
|
1156 |
+
|
1157 |
+
# Get new batch of terms
|
1158 |
+
try:
|
1159 |
+
step = next(steps)
|
1160 |
+
except StopIteration:
|
1161 |
+
pass
|
1162 |
+
if verbose:
|
1163 |
+
print("-"*70)
|
1164 |
+
print("Adding terms #%i-#%i" % (index, index+step))
|
1165 |
+
update(partial, xrange(index, index+step))
|
1166 |
+
index += step
|
1167 |
+
|
1168 |
+
# Check direct error
|
1169 |
+
best = partial[-1]
|
1170 |
+
error = abs(best - partial[-2])
|
1171 |
+
if verbose:
|
1172 |
+
print("Direct error: %s" % ctx.nstr(error))
|
1173 |
+
if error <= tol:
|
1174 |
+
return best
|
1175 |
+
|
1176 |
+
# Check each extrapolation method
|
1177 |
+
if TRY_RICHARDSON:
|
1178 |
+
value, maxc = ctx.richardson(partial)
|
1179 |
+
# Convergence
|
1180 |
+
richardson_error = abs(value - last_richardson_value)
|
1181 |
+
if verbose:
|
1182 |
+
print("Richardson error: %s" % ctx.nstr(richardson_error))
|
1183 |
+
# Convergence
|
1184 |
+
if richardson_error <= tol:
|
1185 |
+
return value
|
1186 |
+
last_richardson_value = value
|
1187 |
+
# Unreliable due to cancellation
|
1188 |
+
if ctx.eps*maxc > tol:
|
1189 |
+
if verbose:
|
1190 |
+
print("Ran out of precision for Richardson")
|
1191 |
+
TRY_RICHARDSON = False
|
1192 |
+
if richardson_error < error:
|
1193 |
+
error = richardson_error
|
1194 |
+
best = value
|
1195 |
+
if TRY_SHANKS:
|
1196 |
+
shanks_table = ctx.shanks(partial, shanks_table, randomized=True)
|
1197 |
+
row = shanks_table[-1]
|
1198 |
+
if len(row) == 2:
|
1199 |
+
est1 = row[-1]
|
1200 |
+
shanks_error = 0
|
1201 |
+
else:
|
1202 |
+
est1, maxc, est2 = row[-1], abs(row[-2]), row[-3]
|
1203 |
+
shanks_error = abs(est1-est2)
|
1204 |
+
if verbose:
|
1205 |
+
print("Shanks error: %s" % ctx.nstr(shanks_error))
|
1206 |
+
if shanks_error <= tol:
|
1207 |
+
return est1
|
1208 |
+
if ctx.eps*maxc > tol:
|
1209 |
+
if verbose:
|
1210 |
+
print("Ran out of precision for Shanks")
|
1211 |
+
TRY_SHANKS = False
|
1212 |
+
if shanks_error < error:
|
1213 |
+
error = shanks_error
|
1214 |
+
best = est1
|
1215 |
+
for L in summer:
|
1216 |
+
est, lerror = L.update_psum(partial)
|
1217 |
+
if verbose:
|
1218 |
+
print("%s error: %s" % (L.name, ctx.nstr(lerror)))
|
1219 |
+
if lerror <= tol:
|
1220 |
+
return est
|
1221 |
+
if lerror < error:
|
1222 |
+
error = lerror
|
1223 |
+
best = est
|
1224 |
+
if TRY_EULER_MACLAURIN:
|
1225 |
+
if ctx.almosteq(ctx.mpc(ctx.sign(partial[-1]) / ctx.sign(partial[-2])), -1):
|
1226 |
+
if verbose:
|
1227 |
+
print ("NOT using Euler-Maclaurin: the series appears"
|
1228 |
+
" to be alternating, so numerical\n quadrature"
|
1229 |
+
" will most likely fail")
|
1230 |
+
TRY_EULER_MACLAURIN = False
|
1231 |
+
else:
|
1232 |
+
value, em_error = emfun(index, tol)
|
1233 |
+
value += partial[-1]
|
1234 |
+
if verbose:
|
1235 |
+
print("Euler-Maclaurin error: %s" % ctx.nstr(em_error))
|
1236 |
+
if em_error <= tol:
|
1237 |
+
return value
|
1238 |
+
if em_error < error:
|
1239 |
+
best = value
|
1240 |
+
finally:
|
1241 |
+
ctx.prec = orig
|
1242 |
+
if strict:
|
1243 |
+
raise ctx.NoConvergence
|
1244 |
+
if verbose:
|
1245 |
+
print("Warning: failed to converge to target accuracy")
|
1246 |
+
return best
|
1247 |
+
|
1248 |
+
@defun
|
1249 |
+
def nsum(ctx, f, *intervals, **options):
|
1250 |
+
r"""
|
1251 |
+
Computes the sum
|
1252 |
+
|
1253 |
+
.. math :: S = \sum_{k=a}^b f(k)
|
1254 |
+
|
1255 |
+
where `(a, b)` = *interval*, and where `a = -\infty` and/or
|
1256 |
+
`b = \infty` are allowed, or more generally
|
1257 |
+
|
1258 |
+
.. math :: S = \sum_{k_1=a_1}^{b_1} \cdots
|
1259 |
+
\sum_{k_n=a_n}^{b_n} f(k_1,\ldots,k_n)
|
1260 |
+
|
1261 |
+
if multiple intervals are given.
|
1262 |
+
|
1263 |
+
Two examples of infinite series that can be summed by :func:`~mpmath.nsum`,
|
1264 |
+
where the first converges rapidly and the second converges slowly,
|
1265 |
+
are::
|
1266 |
+
|
1267 |
+
>>> from mpmath import *
|
1268 |
+
>>> mp.dps = 15; mp.pretty = True
|
1269 |
+
>>> nsum(lambda n: 1/fac(n), [0, inf])
|
1270 |
+
2.71828182845905
|
1271 |
+
>>> nsum(lambda n: 1/n**2, [1, inf])
|
1272 |
+
1.64493406684823
|
1273 |
+
|
1274 |
+
When appropriate, :func:`~mpmath.nsum` applies convergence acceleration to
|
1275 |
+
accurately estimate the sums of slowly convergent series. If the series is
|
1276 |
+
finite, :func:`~mpmath.nsum` currently does not attempt to perform any
|
1277 |
+
extrapolation, and simply calls :func:`~mpmath.fsum`.
|
1278 |
+
|
1279 |
+
Multidimensional infinite series are reduced to a single-dimensional
|
1280 |
+
series over expanding hypercubes; if both infinite and finite dimensions
|
1281 |
+
are present, the finite ranges are moved innermost. For more advanced
|
1282 |
+
control over the summation order, use nested calls to :func:`~mpmath.nsum`,
|
1283 |
+
or manually rewrite the sum as a single-dimensional series.
|
1284 |
+
|
1285 |
+
**Options**
|
1286 |
+
|
1287 |
+
*tol*
|
1288 |
+
Desired maximum final error. Defaults roughly to the
|
1289 |
+
epsilon of the working precision.
|
1290 |
+
|
1291 |
+
*method*
|
1292 |
+
Which summation algorithm to use (described below).
|
1293 |
+
Default: ``'richardson+shanks'``.
|
1294 |
+
|
1295 |
+
*maxterms*
|
1296 |
+
Cancel after at most this many terms. Default: 10*dps.
|
1297 |
+
|
1298 |
+
*steps*
|
1299 |
+
An iterable giving the number of terms to add between
|
1300 |
+
each extrapolation attempt. The default sequence is
|
1301 |
+
[10, 20, 30, 40, ...]. For example, if you know that
|
1302 |
+
approximately 100 terms will be required, efficiency might be
|
1303 |
+
improved by setting this to [100, 10]. Then the first
|
1304 |
+
extrapolation will be performed after 100 terms, the second
|
1305 |
+
after 110, etc.
|
1306 |
+
|
1307 |
+
*verbose*
|
1308 |
+
Print details about progress.
|
1309 |
+
|
1310 |
+
*ignore*
|
1311 |
+
If enabled, any term that raises ``ArithmeticError``
|
1312 |
+
or ``ValueError`` (e.g. through division by zero) is replaced
|
1313 |
+
by a zero. This is convenient for lattice sums with
|
1314 |
+
a singular term near the origin.
|
1315 |
+
|
1316 |
+
**Methods**
|
1317 |
+
|
1318 |
+
Unfortunately, an algorithm that can efficiently sum any infinite
|
1319 |
+
series does not exist. :func:`~mpmath.nsum` implements several different
|
1320 |
+
algorithms that each work well in different cases. The *method*
|
1321 |
+
keyword argument selects a method.
|
1322 |
+
|
1323 |
+
The default method is ``'r+s'``, i.e. both Richardson extrapolation
|
1324 |
+
and Shanks transformation is attempted. A slower method that
|
1325 |
+
handles more cases is ``'r+s+e'``. For very high precision
|
1326 |
+
summation, or if the summation needs to be fast (for example if
|
1327 |
+
multiple sums need to be evaluated), it is a good idea to
|
1328 |
+
investigate which one method works best and only use that.
|
1329 |
+
|
1330 |
+
``'richardson'`` / ``'r'``:
|
1331 |
+
Uses Richardson extrapolation. Provides useful extrapolation
|
1332 |
+
when `f(k) \sim P(k)/Q(k)` or when `f(k) \sim (-1)^k P(k)/Q(k)`
|
1333 |
+
for polynomials `P` and `Q`. See :func:`~mpmath.richardson` for
|
1334 |
+
additional information.
|
1335 |
+
|
1336 |
+
``'shanks'`` / ``'s'``:
|
1337 |
+
Uses Shanks transformation. Typically provides useful
|
1338 |
+
extrapolation when `f(k) \sim c^k` or when successive terms
|
1339 |
+
alternate signs. Is able to sum some divergent series.
|
1340 |
+
See :func:`~mpmath.shanks` for additional information.
|
1341 |
+
|
1342 |
+
``'levin'`` / ``'l'``:
|
1343 |
+
Uses the Levin transformation. It performs better than the Shanks
|
1344 |
+
transformation for logarithmic convergent or alternating divergent
|
1345 |
+
series. The ``'levin_variant'``-keyword selects the variant. Valid
|
1346 |
+
choices are "u", "t", "v" and "all" whereby "all" uses all three
|
1347 |
+
u,t and v simultanously (This is good for performance comparison in
|
1348 |
+
conjunction with "verbose=True"). Instead of the Levin transform one can
|
1349 |
+
also use the Sidi-S transform by selecting the method ``'sidi'``.
|
1350 |
+
See :func:`~mpmath.levin` for additional details.
|
1351 |
+
|
1352 |
+
``'alternating'`` / ``'a'``:
|
1353 |
+
This is the convergence acceleration of alternating series developped
|
1354 |
+
by Cohen, Villegras and Zagier.
|
1355 |
+
See :func:`~mpmath.cohen_alt` for additional details.
|
1356 |
+
|
1357 |
+
``'euler-maclaurin'`` / ``'e'``:
|
1358 |
+
Uses the Euler-Maclaurin summation formula to approximate
|
1359 |
+
the remainder sum by an integral. This requires high-order
|
1360 |
+
numerical derivatives and numerical integration. The advantage
|
1361 |
+
of this algorithm is that it works regardless of the
|
1362 |
+
decay rate of `f`, as long as `f` is sufficiently smooth.
|
1363 |
+
See :func:`~mpmath.sumem` for additional information.
|
1364 |
+
|
1365 |
+
``'direct'`` / ``'d'``:
|
1366 |
+
Does not perform any extrapolation. This can be used
|
1367 |
+
(and should only be used for) rapidly convergent series.
|
1368 |
+
The summation automatically stops when the terms
|
1369 |
+
decrease below the target tolerance.
|
1370 |
+
|
1371 |
+
**Basic examples**
|
1372 |
+
|
1373 |
+
A finite sum::
|
1374 |
+
|
1375 |
+
>>> nsum(lambda k: 1/k, [1, 6])
|
1376 |
+
2.45
|
1377 |
+
|
1378 |
+
Summation of a series going to negative infinity and a doubly
|
1379 |
+
infinite series::
|
1380 |
+
|
1381 |
+
>>> nsum(lambda k: 1/k**2, [-inf, -1])
|
1382 |
+
1.64493406684823
|
1383 |
+
>>> nsum(lambda k: 1/(1+k**2), [-inf, inf])
|
1384 |
+
3.15334809493716
|
1385 |
+
|
1386 |
+
:func:`~mpmath.nsum` handles sums of complex numbers::
|
1387 |
+
|
1388 |
+
>>> nsum(lambda k: (0.5+0.25j)**k, [0, inf])
|
1389 |
+
(1.6 + 0.8j)
|
1390 |
+
|
1391 |
+
The following sum converges very rapidly, so it is most
|
1392 |
+
efficient to sum it by disabling convergence acceleration::
|
1393 |
+
|
1394 |
+
>>> mp.dps = 1000
|
1395 |
+
>>> a = nsum(lambda k: -(-1)**k * k**2 / fac(2*k), [1, inf],
|
1396 |
+
... method='direct')
|
1397 |
+
>>> b = (cos(1)+sin(1))/4
|
1398 |
+
>>> abs(a-b) < mpf('1e-998')
|
1399 |
+
True
|
1400 |
+
|
1401 |
+
**Examples with Richardson extrapolation**
|
1402 |
+
|
1403 |
+
Richardson extrapolation works well for sums over rational
|
1404 |
+
functions, as well as their alternating counterparts::
|
1405 |
+
|
1406 |
+
>>> mp.dps = 50
|
1407 |
+
>>> nsum(lambda k: 1 / k**3, [1, inf],
|
1408 |
+
... method='richardson')
|
1409 |
+
1.2020569031595942853997381615114499907649862923405
|
1410 |
+
>>> zeta(3)
|
1411 |
+
1.2020569031595942853997381615114499907649862923405
|
1412 |
+
|
1413 |
+
>>> nsum(lambda n: (n + 3)/(n**3 + n**2), [1, inf],
|
1414 |
+
... method='richardson')
|
1415 |
+
2.9348022005446793094172454999380755676568497036204
|
1416 |
+
>>> pi**2/2-2
|
1417 |
+
2.9348022005446793094172454999380755676568497036204
|
1418 |
+
|
1419 |
+
>>> nsum(lambda k: (-1)**k / k**3, [1, inf],
|
1420 |
+
... method='richardson')
|
1421 |
+
-0.90154267736969571404980362113358749307373971925537
|
1422 |
+
>>> -3*zeta(3)/4
|
1423 |
+
-0.90154267736969571404980362113358749307373971925538
|
1424 |
+
|
1425 |
+
**Examples with Shanks transformation**
|
1426 |
+
|
1427 |
+
The Shanks transformation works well for geometric series
|
1428 |
+
and typically provides excellent acceleration for Taylor
|
1429 |
+
series near the border of their disk of convergence.
|
1430 |
+
Here we apply it to a series for `\log(2)`, which can be
|
1431 |
+
seen as the Taylor series for `\log(1+x)` with `x = 1`::
|
1432 |
+
|
1433 |
+
>>> nsum(lambda k: -(-1)**k/k, [1, inf],
|
1434 |
+
... method='shanks')
|
1435 |
+
0.69314718055994530941723212145817656807550013436025
|
1436 |
+
>>> log(2)
|
1437 |
+
0.69314718055994530941723212145817656807550013436025
|
1438 |
+
|
1439 |
+
Here we apply it to a slowly convergent geometric series::
|
1440 |
+
|
1441 |
+
>>> nsum(lambda k: mpf('0.995')**k, [0, inf],
|
1442 |
+
... method='shanks')
|
1443 |
+
200.0
|
1444 |
+
|
1445 |
+
Finally, Shanks' method works very well for alternating series
|
1446 |
+
where `f(k) = (-1)^k g(k)`, and often does so regardless of
|
1447 |
+
the exact decay rate of `g(k)`::
|
1448 |
+
|
1449 |
+
>>> mp.dps = 15
|
1450 |
+
>>> nsum(lambda k: (-1)**(k+1) / k**1.5, [1, inf],
|
1451 |
+
... method='shanks')
|
1452 |
+
0.765147024625408
|
1453 |
+
>>> (2-sqrt(2))*zeta(1.5)/2
|
1454 |
+
0.765147024625408
|
1455 |
+
|
1456 |
+
The following slowly convergent alternating series has no known
|
1457 |
+
closed-form value. Evaluating the sum a second time at higher
|
1458 |
+
precision indicates that the value is probably correct::
|
1459 |
+
|
1460 |
+
>>> nsum(lambda k: (-1)**k / log(k), [2, inf],
|
1461 |
+
... method='shanks')
|
1462 |
+
0.924299897222939
|
1463 |
+
>>> mp.dps = 30
|
1464 |
+
>>> nsum(lambda k: (-1)**k / log(k), [2, inf],
|
1465 |
+
... method='shanks')
|
1466 |
+
0.92429989722293885595957018136
|
1467 |
+
|
1468 |
+
**Examples with Levin transformation**
|
1469 |
+
|
1470 |
+
The following example calculates Euler's constant as the constant term in
|
1471 |
+
the Laurent expansion of zeta(s) at s=1. This sum converges extremly slow
|
1472 |
+
because of the logarithmic convergence behaviour of the Dirichlet series
|
1473 |
+
for zeta.
|
1474 |
+
|
1475 |
+
>>> mp.dps = 30
|
1476 |
+
>>> z = mp.mpf(10) ** (-10)
|
1477 |
+
>>> a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "levin") - 1 / z
|
1478 |
+
>>> print(mp.chop(a - mp.euler, tol = 1e-10))
|
1479 |
+
0.0
|
1480 |
+
|
1481 |
+
Now we sum the zeta function outside its range of convergence
|
1482 |
+
(attention: This does not work at the negative integers!):
|
1483 |
+
|
1484 |
+
>>> mp.dps = 15
|
1485 |
+
>>> w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v")
|
1486 |
+
>>> print(mp.chop(w - mp.zeta(-2-3j)))
|
1487 |
+
0.0
|
1488 |
+
|
1489 |
+
The next example resummates an asymptotic series expansion of an integral
|
1490 |
+
related to the exponential integral.
|
1491 |
+
|
1492 |
+
>>> mp.dps = 15
|
1493 |
+
>>> z = mp.mpf(10)
|
1494 |
+
>>> # exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf])
|
1495 |
+
>>> exact = z * mp.exp(z) * mp.expint(1,z) # this is the symbolic expression for the integral
|
1496 |
+
>>> w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t")
|
1497 |
+
>>> print(mp.chop(w - exact))
|
1498 |
+
0.0
|
1499 |
+
|
1500 |
+
Following highly divergent asymptotic expansion needs some care. Firstly we
|
1501 |
+
need copious amount of working precision. Secondly the stepsize must not be
|
1502 |
+
chosen to large, otherwise nsum may miss the point where the Levin transform
|
1503 |
+
converges and reach the point where only numerical garbage is produced due to
|
1504 |
+
numerical cancellation.
|
1505 |
+
|
1506 |
+
>>> mp.dps = 15
|
1507 |
+
>>> z = mp.mpf(2)
|
1508 |
+
>>> # exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi)
|
1509 |
+
>>> exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi)) # this is the symbolic expression for the integral
|
1510 |
+
>>> w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)),
|
1511 |
+
... [0, mp.inf], method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in xrange(1000)])
|
1512 |
+
>>> print(mp.chop(w - exact))
|
1513 |
+
0.0
|
1514 |
+
|
1515 |
+
The hypergeoemtric function can also be summed outside its range of convergence:
|
1516 |
+
|
1517 |
+
>>> mp.dps = 15
|
1518 |
+
>>> z = 2 + 1j
|
1519 |
+
>>> exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z)
|
1520 |
+
>>> f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n))
|
1521 |
+
>>> v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in xrange(1000)])
|
1522 |
+
>>> print(mp.chop(exact-v))
|
1523 |
+
0.0
|
1524 |
+
|
1525 |
+
**Examples with Cohen's alternating series resummation**
|
1526 |
+
|
1527 |
+
The next example sums the alternating zeta function:
|
1528 |
+
|
1529 |
+
>>> v = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "a")
|
1530 |
+
>>> print(mp.chop(v - mp.log(2)))
|
1531 |
+
0.0
|
1532 |
+
|
1533 |
+
The derivate of the alternating zeta function outside its range of
|
1534 |
+
convergence:
|
1535 |
+
|
1536 |
+
>>> v = mp.nsum(lambda n: (-1)**n * mp.log(n) * n, [1, mp.inf], method = "a")
|
1537 |
+
>>> print(mp.chop(v - mp.diff(lambda s: mp.altzeta(s), -1)))
|
1538 |
+
0.0
|
1539 |
+
|
1540 |
+
**Examples with Euler-Maclaurin summation**
|
1541 |
+
|
1542 |
+
The sum in the following example has the wrong rate of convergence
|
1543 |
+
for either Richardson or Shanks to be effective.
|
1544 |
+
|
1545 |
+
>>> f = lambda k: log(k)/k**2.5
|
1546 |
+
>>> mp.dps = 15
|
1547 |
+
>>> nsum(f, [1, inf], method='euler-maclaurin')
|
1548 |
+
0.38734195032621
|
1549 |
+
>>> -diff(zeta, 2.5)
|
1550 |
+
0.38734195032621
|
1551 |
+
|
1552 |
+
Increasing ``steps`` improves speed at higher precision::
|
1553 |
+
|
1554 |
+
>>> mp.dps = 50
|
1555 |
+
>>> nsum(f, [1, inf], method='euler-maclaurin', steps=[250])
|
1556 |
+
0.38734195032620997271199237593105101319948228874688
|
1557 |
+
>>> -diff(zeta, 2.5)
|
1558 |
+
0.38734195032620997271199237593105101319948228874688
|
1559 |
+
|
1560 |
+
**Divergent series**
|
1561 |
+
|
1562 |
+
The Shanks transformation is able to sum some *divergent*
|
1563 |
+
series. In particular, it is often able to sum Taylor series
|
1564 |
+
beyond their radius of convergence (this is due to a relation
|
1565 |
+
between the Shanks transformation and Pade approximations;
|
1566 |
+
see :func:`~mpmath.pade` for an alternative way to evaluate divergent
|
1567 |
+
Taylor series). Furthermore the Levin-transform examples above
|
1568 |
+
contain some divergent series resummation.
|
1569 |
+
|
1570 |
+
Here we apply it to `\log(1+x)` far outside the region of
|
1571 |
+
convergence::
|
1572 |
+
|
1573 |
+
>>> mp.dps = 50
|
1574 |
+
>>> nsum(lambda k: -(-9)**k/k, [1, inf],
|
1575 |
+
... method='shanks')
|
1576 |
+
2.3025850929940456840179914546843642076011014886288
|
1577 |
+
>>> log(10)
|
1578 |
+
2.3025850929940456840179914546843642076011014886288
|
1579 |
+
|
1580 |
+
A particular type of divergent series that can be summed
|
1581 |
+
using the Shanks transformation is geometric series.
|
1582 |
+
The result is the same as using the closed-form formula
|
1583 |
+
for an infinite geometric series::
|
1584 |
+
|
1585 |
+
>>> mp.dps = 15
|
1586 |
+
>>> for n in range(-8, 8):
|
1587 |
+
... if n == 1:
|
1588 |
+
... continue
|
1589 |
+
... print("%s %s %s" % (mpf(n), mpf(1)/(1-n),
|
1590 |
+
... nsum(lambda k: n**k, [0, inf], method='shanks')))
|
1591 |
+
...
|
1592 |
+
-8.0 0.111111111111111 0.111111111111111
|
1593 |
+
-7.0 0.125 0.125
|
1594 |
+
-6.0 0.142857142857143 0.142857142857143
|
1595 |
+
-5.0 0.166666666666667 0.166666666666667
|
1596 |
+
-4.0 0.2 0.2
|
1597 |
+
-3.0 0.25 0.25
|
1598 |
+
-2.0 0.333333333333333 0.333333333333333
|
1599 |
+
-1.0 0.5 0.5
|
1600 |
+
0.0 1.0 1.0
|
1601 |
+
2.0 -1.0 -1.0
|
1602 |
+
3.0 -0.5 -0.5
|
1603 |
+
4.0 -0.333333333333333 -0.333333333333333
|
1604 |
+
5.0 -0.25 -0.25
|
1605 |
+
6.0 -0.2 -0.2
|
1606 |
+
7.0 -0.166666666666667 -0.166666666666667
|
1607 |
+
|
1608 |
+
**Multidimensional sums**
|
1609 |
+
|
1610 |
+
Any combination of finite and infinite ranges is allowed for the
|
1611 |
+
summation indices::
|
1612 |
+
|
1613 |
+
>>> mp.dps = 15
|
1614 |
+
>>> nsum(lambda x,y: x+y, [2,3], [4,5])
|
1615 |
+
28.0
|
1616 |
+
>>> nsum(lambda x,y: x/2**y, [1,3], [1,inf])
|
1617 |
+
6.0
|
1618 |
+
>>> nsum(lambda x,y: y/2**x, [1,inf], [1,3])
|
1619 |
+
6.0
|
1620 |
+
>>> nsum(lambda x,y,z: z/(2**x*2**y), [1,inf], [1,inf], [3,4])
|
1621 |
+
7.0
|
1622 |
+
>>> nsum(lambda x,y,z: y/(2**x*2**z), [1,inf], [3,4], [1,inf])
|
1623 |
+
7.0
|
1624 |
+
>>> nsum(lambda x,y,z: x/(2**z*2**y), [3,4], [1,inf], [1,inf])
|
1625 |
+
7.0
|
1626 |
+
|
1627 |
+
Some nice examples of double series with analytic solutions or
|
1628 |
+
reductions to single-dimensional series (see [1])::
|
1629 |
+
|
1630 |
+
>>> nsum(lambda m, n: 1/2**(m*n), [1,inf], [1,inf])
|
1631 |
+
1.60669515241529
|
1632 |
+
>>> nsum(lambda n: 1/(2**n-1), [1,inf])
|
1633 |
+
1.60669515241529
|
1634 |
+
|
1635 |
+
>>> nsum(lambda i,j: (-1)**(i+j)/(i**2+j**2), [1,inf], [1,inf])
|
1636 |
+
0.278070510848213
|
1637 |
+
>>> pi*(pi-3*ln2)/12
|
1638 |
+
0.278070510848213
|
1639 |
+
|
1640 |
+
>>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**2, [1,inf], [1,inf])
|
1641 |
+
0.129319852864168
|
1642 |
+
>>> altzeta(2) - altzeta(1)
|
1643 |
+
0.129319852864168
|
1644 |
+
|
1645 |
+
>>> nsum(lambda i,j: (-1)**(i+j)/(i+j)**3, [1,inf], [1,inf])
|
1646 |
+
0.0790756439455825
|
1647 |
+
>>> altzeta(3) - altzeta(2)
|
1648 |
+
0.0790756439455825
|
1649 |
+
|
1650 |
+
>>> nsum(lambda m,n: m**2*n/(3**m*(n*3**m+m*3**n)),
|
1651 |
+
... [1,inf], [1,inf])
|
1652 |
+
0.28125
|
1653 |
+
>>> mpf(9)/32
|
1654 |
+
0.28125
|
1655 |
+
|
1656 |
+
>>> nsum(lambda i,j: fac(i-1)*fac(j-1)/fac(i+j),
|
1657 |
+
... [1,inf], [1,inf], workprec=400)
|
1658 |
+
1.64493406684823
|
1659 |
+
>>> zeta(2)
|
1660 |
+
1.64493406684823
|
1661 |
+
|
1662 |
+
A hard example of a multidimensional sum is the Madelung constant
|
1663 |
+
in three dimensions (see [2]). The defining sum converges very
|
1664 |
+
slowly and only conditionally, so :func:`~mpmath.nsum` is lucky to
|
1665 |
+
obtain an accurate value through convergence acceleration. The
|
1666 |
+
second evaluation below uses a much more efficient, rapidly
|
1667 |
+
convergent 2D sum::
|
1668 |
+
|
1669 |
+
>>> nsum(lambda x,y,z: (-1)**(x+y+z)/(x*x+y*y+z*z)**0.5,
|
1670 |
+
... [-inf,inf], [-inf,inf], [-inf,inf], ignore=True)
|
1671 |
+
-1.74756459463318
|
1672 |
+
>>> nsum(lambda x,y: -12*pi*sech(0.5*pi * \
|
1673 |
+
... sqrt((2*x+1)**2+(2*y+1)**2))**2, [0,inf], [0,inf])
|
1674 |
+
-1.74756459463318
|
1675 |
+
|
1676 |
+
Another example of a lattice sum in 2D::
|
1677 |
+
|
1678 |
+
>>> nsum(lambda x,y: (-1)**(x+y) / (x**2+y**2), [-inf,inf],
|
1679 |
+
... [-inf,inf], ignore=True)
|
1680 |
+
-2.1775860903036
|
1681 |
+
>>> -pi*ln2
|
1682 |
+
-2.1775860903036
|
1683 |
+
|
1684 |
+
An example of an Eisenstein series::
|
1685 |
+
|
1686 |
+
>>> nsum(lambda m,n: (m+n*1j)**(-4), [-inf,inf], [-inf,inf],
|
1687 |
+
... ignore=True)
|
1688 |
+
(3.1512120021539 + 0.0j)
|
1689 |
+
|
1690 |
+
**References**
|
1691 |
+
|
1692 |
+
1. [Weisstein]_ http://mathworld.wolfram.com/DoubleSeries.html,
|
1693 |
+
2. [Weisstein]_ http://mathworld.wolfram.com/MadelungConstants.html
|
1694 |
+
|
1695 |
+
"""
|
1696 |
+
infinite, g = standardize(ctx, f, intervals, options)
|
1697 |
+
if not infinite:
|
1698 |
+
return +g()
|
1699 |
+
|
1700 |
+
def update(partial_sums, indices):
|
1701 |
+
if partial_sums:
|
1702 |
+
psum = partial_sums[-1]
|
1703 |
+
else:
|
1704 |
+
psum = ctx.zero
|
1705 |
+
for k in indices:
|
1706 |
+
psum = psum + g(ctx.mpf(k))
|
1707 |
+
partial_sums.append(psum)
|
1708 |
+
|
1709 |
+
prec = ctx.prec
|
1710 |
+
|
1711 |
+
def emfun(point, tol):
|
1712 |
+
workprec = ctx.prec
|
1713 |
+
ctx.prec = prec + 10
|
1714 |
+
v = ctx.sumem(g, [point, ctx.inf], tol, error=1)
|
1715 |
+
ctx.prec = workprec
|
1716 |
+
return v
|
1717 |
+
|
1718 |
+
return +ctx.adaptive_extrapolation(update, emfun, options)
|
1719 |
+
|
1720 |
+
|
1721 |
+
def wrapsafe(f):
|
1722 |
+
def g(*args):
|
1723 |
+
try:
|
1724 |
+
return f(*args)
|
1725 |
+
except (ArithmeticError, ValueError):
|
1726 |
+
return 0
|
1727 |
+
return g
|
1728 |
+
|
1729 |
+
def standardize(ctx, f, intervals, options):
|
1730 |
+
if options.get("ignore"):
|
1731 |
+
f = wrapsafe(f)
|
1732 |
+
finite = []
|
1733 |
+
infinite = []
|
1734 |
+
for k, points in enumerate(intervals):
|
1735 |
+
a, b = ctx._as_points(points)
|
1736 |
+
if b < a:
|
1737 |
+
return False, (lambda: ctx.zero)
|
1738 |
+
if a == ctx.ninf or b == ctx.inf:
|
1739 |
+
infinite.append((k, (a,b)))
|
1740 |
+
else:
|
1741 |
+
finite.append((k, (int(a), int(b))))
|
1742 |
+
if finite:
|
1743 |
+
f = fold_finite(ctx, f, finite)
|
1744 |
+
if not infinite:
|
1745 |
+
return False, lambda: f(*([0]*len(intervals)))
|
1746 |
+
if infinite:
|
1747 |
+
f = standardize_infinite(ctx, f, infinite)
|
1748 |
+
f = fold_infinite(ctx, f, infinite)
|
1749 |
+
args = [0] * len(intervals)
|
1750 |
+
d = infinite[0][0]
|
1751 |
+
def g(k):
|
1752 |
+
args[d] = k
|
1753 |
+
return f(*args)
|
1754 |
+
return True, g
|
1755 |
+
|
1756 |
+
# backwards compatible itertools.product
|
1757 |
+
def cartesian_product(args):
|
1758 |
+
pools = map(tuple, args)
|
1759 |
+
result = [[]]
|
1760 |
+
for pool in pools:
|
1761 |
+
result = [x+[y] for x in result for y in pool]
|
1762 |
+
for prod in result:
|
1763 |
+
yield tuple(prod)
|
1764 |
+
|
1765 |
+
def fold_finite(ctx, f, intervals):
|
1766 |
+
if not intervals:
|
1767 |
+
return f
|
1768 |
+
indices = [v[0] for v in intervals]
|
1769 |
+
points = [v[1] for v in intervals]
|
1770 |
+
ranges = [xrange(a, b+1) for (a,b) in points]
|
1771 |
+
def g(*args):
|
1772 |
+
args = list(args)
|
1773 |
+
s = ctx.zero
|
1774 |
+
for xs in cartesian_product(ranges):
|
1775 |
+
for dim, x in zip(indices, xs):
|
1776 |
+
args[dim] = ctx.mpf(x)
|
1777 |
+
s += f(*args)
|
1778 |
+
return s
|
1779 |
+
#print "Folded finite", indices
|
1780 |
+
return g
|
1781 |
+
|
1782 |
+
# Standardize each interval to [0,inf]
|
1783 |
+
def standardize_infinite(ctx, f, intervals):
|
1784 |
+
if not intervals:
|
1785 |
+
return f
|
1786 |
+
dim, [a,b] = intervals[-1]
|
1787 |
+
if a == ctx.ninf:
|
1788 |
+
if b == ctx.inf:
|
1789 |
+
def g(*args):
|
1790 |
+
args = list(args)
|
1791 |
+
k = args[dim]
|
1792 |
+
if k:
|
1793 |
+
s = f(*args)
|
1794 |
+
args[dim] = -k
|
1795 |
+
s += f(*args)
|
1796 |
+
return s
|
1797 |
+
else:
|
1798 |
+
return f(*args)
|
1799 |
+
else:
|
1800 |
+
def g(*args):
|
1801 |
+
args = list(args)
|
1802 |
+
args[dim] = b - args[dim]
|
1803 |
+
return f(*args)
|
1804 |
+
else:
|
1805 |
+
def g(*args):
|
1806 |
+
args = list(args)
|
1807 |
+
args[dim] += a
|
1808 |
+
return f(*args)
|
1809 |
+
#print "Standardized infinity along dimension", dim, a, b
|
1810 |
+
return standardize_infinite(ctx, g, intervals[:-1])
|
1811 |
+
|
1812 |
+
def fold_infinite(ctx, f, intervals):
|
1813 |
+
if len(intervals) < 2:
|
1814 |
+
return f
|
1815 |
+
dim1 = intervals[-2][0]
|
1816 |
+
dim2 = intervals[-1][0]
|
1817 |
+
# Assume intervals are [0,inf] x [0,inf] x ...
|
1818 |
+
def g(*args):
|
1819 |
+
args = list(args)
|
1820 |
+
#args.insert(dim2, None)
|
1821 |
+
n = int(args[dim1])
|
1822 |
+
s = ctx.zero
|
1823 |
+
#y = ctx.mpf(n)
|
1824 |
+
args[dim2] = ctx.mpf(n) #y
|
1825 |
+
for x in xrange(n+1):
|
1826 |
+
args[dim1] = ctx.mpf(x)
|
1827 |
+
s += f(*args)
|
1828 |
+
args[dim1] = ctx.mpf(n) #ctx.mpf(n)
|
1829 |
+
for y in xrange(n):
|
1830 |
+
args[dim2] = ctx.mpf(y)
|
1831 |
+
s += f(*args)
|
1832 |
+
return s
|
1833 |
+
#print "Folded infinite from", len(intervals), "to", (len(intervals)-1)
|
1834 |
+
return fold_infinite(ctx, g, intervals[:-1])
|
1835 |
+
|
1836 |
+
@defun
|
1837 |
+
def nprod(ctx, f, interval, nsum=False, **kwargs):
|
1838 |
+
r"""
|
1839 |
+
Computes the product
|
1840 |
+
|
1841 |
+
.. math ::
|
1842 |
+
|
1843 |
+
P = \prod_{k=a}^b f(k)
|
1844 |
+
|
1845 |
+
where `(a, b)` = *interval*, and where `a = -\infty` and/or
|
1846 |
+
`b = \infty` are allowed.
|
1847 |
+
|
1848 |
+
By default, :func:`~mpmath.nprod` uses the same extrapolation methods as
|
1849 |
+
:func:`~mpmath.nsum`, except applied to the partial products rather than
|
1850 |
+
partial sums, and the same keyword options as for :func:`~mpmath.nsum` are
|
1851 |
+
supported. If ``nsum=True``, the product is instead computed via
|
1852 |
+
:func:`~mpmath.nsum` as
|
1853 |
+
|
1854 |
+
.. math ::
|
1855 |
+
|
1856 |
+
P = \exp\left( \sum_{k=a}^b \log(f(k)) \right).
|
1857 |
+
|
1858 |
+
This is slower, but can sometimes yield better results. It is
|
1859 |
+
also required (and used automatically) when Euler-Maclaurin
|
1860 |
+
summation is requested.
|
1861 |
+
|
1862 |
+
**Examples**
|
1863 |
+
|
1864 |
+
A simple finite product::
|
1865 |
+
|
1866 |
+
>>> from mpmath import *
|
1867 |
+
>>> mp.dps = 25; mp.pretty = True
|
1868 |
+
>>> nprod(lambda k: k, [1, 4])
|
1869 |
+
24.0
|
1870 |
+
|
1871 |
+
A large number of infinite products have known exact values,
|
1872 |
+
and can therefore be used as a reference. Most of the following
|
1873 |
+
examples are taken from MathWorld [1].
|
1874 |
+
|
1875 |
+
A few infinite products with simple values are::
|
1876 |
+
|
1877 |
+
>>> 2*nprod(lambda k: (4*k**2)/(4*k**2-1), [1, inf])
|
1878 |
+
3.141592653589793238462643
|
1879 |
+
>>> nprod(lambda k: (1+1/k)**2/(1+2/k), [1, inf])
|
1880 |
+
2.0
|
1881 |
+
>>> nprod(lambda k: (k**3-1)/(k**3+1), [2, inf])
|
1882 |
+
0.6666666666666666666666667
|
1883 |
+
>>> nprod(lambda k: (1-1/k**2), [2, inf])
|
1884 |
+
0.5
|
1885 |
+
|
1886 |
+
Next, several more infinite products with more complicated
|
1887 |
+
values::
|
1888 |
+
|
1889 |
+
>>> nprod(lambda k: exp(1/k**2), [1, inf]); exp(pi**2/6)
|
1890 |
+
5.180668317897115748416626
|
1891 |
+
5.180668317897115748416626
|
1892 |
+
|
1893 |
+
>>> nprod(lambda k: (k**2-1)/(k**2+1), [2, inf]); pi*csch(pi)
|
1894 |
+
0.2720290549821331629502366
|
1895 |
+
0.2720290549821331629502366
|
1896 |
+
|
1897 |
+
>>> nprod(lambda k: (k**4-1)/(k**4+1), [2, inf])
|
1898 |
+
0.8480540493529003921296502
|
1899 |
+
>>> pi*sinh(pi)/(cosh(sqrt(2)*pi)-cos(sqrt(2)*pi))
|
1900 |
+
0.8480540493529003921296502
|
1901 |
+
|
1902 |
+
>>> nprod(lambda k: (1+1/k+1/k**2)**2/(1+2/k+3/k**2), [1, inf])
|
1903 |
+
1.848936182858244485224927
|
1904 |
+
>>> 3*sqrt(2)*cosh(pi*sqrt(3)/2)**2*csch(pi*sqrt(2))/pi
|
1905 |
+
1.848936182858244485224927
|
1906 |
+
|
1907 |
+
>>> nprod(lambda k: (1-1/k**4), [2, inf]); sinh(pi)/(4*pi)
|
1908 |
+
0.9190194775937444301739244
|
1909 |
+
0.9190194775937444301739244
|
1910 |
+
|
1911 |
+
>>> nprod(lambda k: (1-1/k**6), [2, inf])
|
1912 |
+
0.9826842777421925183244759
|
1913 |
+
>>> (1+cosh(pi*sqrt(3)))/(12*pi**2)
|
1914 |
+
0.9826842777421925183244759
|
1915 |
+
|
1916 |
+
>>> nprod(lambda k: (1+1/k**2), [2, inf]); sinh(pi)/(2*pi)
|
1917 |
+
1.838038955187488860347849
|
1918 |
+
1.838038955187488860347849
|
1919 |
+
|
1920 |
+
>>> nprod(lambda n: (1+1/n)**n * exp(1/(2*n)-1), [1, inf])
|
1921 |
+
1.447255926890365298959138
|
1922 |
+
>>> exp(1+euler/2)/sqrt(2*pi)
|
1923 |
+
1.447255926890365298959138
|
1924 |
+
|
1925 |
+
The following two products are equivalent and can be evaluated in
|
1926 |
+
terms of a Jacobi theta function. Pi can be replaced by any value
|
1927 |
+
(as long as convergence is preserved)::
|
1928 |
+
|
1929 |
+
>>> nprod(lambda k: (1-pi**-k)/(1+pi**-k), [1, inf])
|
1930 |
+
0.3838451207481672404778686
|
1931 |
+
>>> nprod(lambda k: tanh(k*log(pi)/2), [1, inf])
|
1932 |
+
0.3838451207481672404778686
|
1933 |
+
>>> jtheta(4,0,1/pi)
|
1934 |
+
0.3838451207481672404778686
|
1935 |
+
|
1936 |
+
This product does not have a known closed form value::
|
1937 |
+
|
1938 |
+
>>> nprod(lambda k: (1-1/2**k), [1, inf])
|
1939 |
+
0.2887880950866024212788997
|
1940 |
+
|
1941 |
+
A product taken from `-\infty`::
|
1942 |
+
|
1943 |
+
>>> nprod(lambda k: 1-k**(-3), [-inf,-2])
|
1944 |
+
0.8093965973662901095786805
|
1945 |
+
>>> cosh(pi*sqrt(3)/2)/(3*pi)
|
1946 |
+
0.8093965973662901095786805
|
1947 |
+
|
1948 |
+
A doubly infinite product::
|
1949 |
+
|
1950 |
+
>>> nprod(lambda k: exp(1/(1+k**2)), [-inf, inf])
|
1951 |
+
23.41432688231864337420035
|
1952 |
+
>>> exp(pi/tanh(pi))
|
1953 |
+
23.41432688231864337420035
|
1954 |
+
|
1955 |
+
A product requiring the use of Euler-Maclaurin summation to compute
|
1956 |
+
an accurate value::
|
1957 |
+
|
1958 |
+
>>> nprod(lambda k: (1-1/k**2.5), [2, inf], method='e')
|
1959 |
+
0.696155111336231052898125
|
1960 |
+
|
1961 |
+
**References**
|
1962 |
+
|
1963 |
+
1. [Weisstein]_ http://mathworld.wolfram.com/InfiniteProduct.html
|
1964 |
+
|
1965 |
+
"""
|
1966 |
+
if nsum or ('e' in kwargs.get('method', '')):
|
1967 |
+
orig = ctx.prec
|
1968 |
+
try:
|
1969 |
+
# TODO: we are evaluating log(1+eps) -> eps, which is
|
1970 |
+
# inaccurate. This currently works because nsum greatly
|
1971 |
+
# increases the working precision. But we should be
|
1972 |
+
# more intelligent and handle the precision here.
|
1973 |
+
ctx.prec += 10
|
1974 |
+
v = ctx.nsum(lambda n: ctx.ln(f(n)), interval, **kwargs)
|
1975 |
+
finally:
|
1976 |
+
ctx.prec = orig
|
1977 |
+
return +ctx.exp(v)
|
1978 |
+
|
1979 |
+
a, b = ctx._as_points(interval)
|
1980 |
+
if a == ctx.ninf:
|
1981 |
+
if b == ctx.inf:
|
1982 |
+
return f(0) * ctx.nprod(lambda k: f(-k) * f(k), [1, ctx.inf], **kwargs)
|
1983 |
+
return ctx.nprod(f, [-b, ctx.inf], **kwargs)
|
1984 |
+
elif b != ctx.inf:
|
1985 |
+
return ctx.fprod(f(ctx.mpf(k)) for k in xrange(int(a), int(b)+1))
|
1986 |
+
|
1987 |
+
a = int(a)
|
1988 |
+
|
1989 |
+
def update(partial_products, indices):
|
1990 |
+
if partial_products:
|
1991 |
+
pprod = partial_products[-1]
|
1992 |
+
else:
|
1993 |
+
pprod = ctx.one
|
1994 |
+
for k in indices:
|
1995 |
+
pprod = pprod * f(a + ctx.mpf(k))
|
1996 |
+
partial_products.append(pprod)
|
1997 |
+
|
1998 |
+
return +ctx.adaptive_extrapolation(update, None, kwargs)
|
1999 |
+
|
2000 |
+
|
2001 |
+
@defun
|
2002 |
+
def limit(ctx, f, x, direction=1, exp=False, **kwargs):
|
2003 |
+
r"""
|
2004 |
+
Computes an estimate of the limit
|
2005 |
+
|
2006 |
+
.. math ::
|
2007 |
+
|
2008 |
+
\lim_{t \to x} f(t)
|
2009 |
+
|
2010 |
+
where `x` may be finite or infinite.
|
2011 |
+
|
2012 |
+
For finite `x`, :func:`~mpmath.limit` evaluates `f(x + d/n)` for
|
2013 |
+
consecutive integer values of `n`, where the approach direction
|
2014 |
+
`d` may be specified using the *direction* keyword argument.
|
2015 |
+
For infinite `x`, :func:`~mpmath.limit` evaluates values of
|
2016 |
+
`f(\mathrm{sign}(x) \cdot n)`.
|
2017 |
+
|
2018 |
+
If the approach to the limit is not sufficiently fast to give
|
2019 |
+
an accurate estimate directly, :func:`~mpmath.limit` attempts to find
|
2020 |
+
the limit using Richardson extrapolation or the Shanks
|
2021 |
+
transformation. You can select between these methods using
|
2022 |
+
the *method* keyword (see documentation of :func:`~mpmath.nsum` for
|
2023 |
+
more information).
|
2024 |
+
|
2025 |
+
**Options**
|
2026 |
+
|
2027 |
+
The following options are available with essentially the
|
2028 |
+
same meaning as for :func:`~mpmath.nsum`: *tol*, *method*, *maxterms*,
|
2029 |
+
*steps*, *verbose*.
|
2030 |
+
|
2031 |
+
If the option *exp=True* is set, `f` will be
|
2032 |
+
sampled at exponentially spaced points `n = 2^1, 2^2, 2^3, \ldots`
|
2033 |
+
instead of the linearly spaced points `n = 1, 2, 3, \ldots`.
|
2034 |
+
This can sometimes improve the rate of convergence so that
|
2035 |
+
:func:`~mpmath.limit` may return a more accurate answer (and faster).
|
2036 |
+
However, do note that this can only be used if `f`
|
2037 |
+
supports fast and accurate evaluation for arguments that
|
2038 |
+
are extremely close to the limit point (or if infinite,
|
2039 |
+
very large arguments).
|
2040 |
+
|
2041 |
+
**Examples**
|
2042 |
+
|
2043 |
+
A basic evaluation of a removable singularity::
|
2044 |
+
|
2045 |
+
>>> from mpmath import *
|
2046 |
+
>>> mp.dps = 30; mp.pretty = True
|
2047 |
+
>>> limit(lambda x: (x-sin(x))/x**3, 0)
|
2048 |
+
0.166666666666666666666666666667
|
2049 |
+
|
2050 |
+
Computing the exponential function using its limit definition::
|
2051 |
+
|
2052 |
+
>>> limit(lambda n: (1+3/n)**n, inf)
|
2053 |
+
20.0855369231876677409285296546
|
2054 |
+
>>> exp(3)
|
2055 |
+
20.0855369231876677409285296546
|
2056 |
+
|
2057 |
+
A limit for `\pi`::
|
2058 |
+
|
2059 |
+
>>> f = lambda n: 2**(4*n+1)*fac(n)**4/(2*n+1)/fac(2*n)**2
|
2060 |
+
>>> limit(f, inf)
|
2061 |
+
3.14159265358979323846264338328
|
2062 |
+
|
2063 |
+
Calculating the coefficient in Stirling's formula::
|
2064 |
+
|
2065 |
+
>>> limit(lambda n: fac(n) / (sqrt(n)*(n/e)**n), inf)
|
2066 |
+
2.50662827463100050241576528481
|
2067 |
+
>>> sqrt(2*pi)
|
2068 |
+
2.50662827463100050241576528481
|
2069 |
+
|
2070 |
+
Evaluating Euler's constant `\gamma` using the limit representation
|
2071 |
+
|
2072 |
+
.. math ::
|
2073 |
+
|
2074 |
+
\gamma = \lim_{n \rightarrow \infty } \left[ \left(
|
2075 |
+
\sum_{k=1}^n \frac{1}{k} \right) - \log(n) \right]
|
2076 |
+
|
2077 |
+
(which converges notoriously slowly)::
|
2078 |
+
|
2079 |
+
>>> f = lambda n: sum([mpf(1)/k for k in range(1,int(n)+1)]) - log(n)
|
2080 |
+
>>> limit(f, inf)
|
2081 |
+
0.577215664901532860606512090082
|
2082 |
+
>>> +euler
|
2083 |
+
0.577215664901532860606512090082
|
2084 |
+
|
2085 |
+
With default settings, the following limit converges too slowly
|
2086 |
+
to be evaluated accurately. Changing to exponential sampling
|
2087 |
+
however gives a perfect result::
|
2088 |
+
|
2089 |
+
>>> f = lambda x: sqrt(x**3+x**2)/(sqrt(x**3)+x)
|
2090 |
+
>>> limit(f, inf)
|
2091 |
+
0.992831158558330281129249686491
|
2092 |
+
>>> limit(f, inf, exp=True)
|
2093 |
+
1.0
|
2094 |
+
|
2095 |
+
"""
|
2096 |
+
|
2097 |
+
if ctx.isinf(x):
|
2098 |
+
direction = ctx.sign(x)
|
2099 |
+
g = lambda k: f(ctx.mpf(k+1)*direction)
|
2100 |
+
else:
|
2101 |
+
direction *= ctx.one
|
2102 |
+
g = lambda k: f(x + direction/(k+1))
|
2103 |
+
if exp:
|
2104 |
+
h = g
|
2105 |
+
g = lambda k: h(2**k)
|
2106 |
+
|
2107 |
+
def update(values, indices):
|
2108 |
+
for k in indices:
|
2109 |
+
values.append(g(k+1))
|
2110 |
+
|
2111 |
+
# XXX: steps used by nsum don't work well
|
2112 |
+
if not 'steps' in kwargs:
|
2113 |
+
kwargs['steps'] = [10]
|
2114 |
+
|
2115 |
+
return +ctx.adaptive_extrapolation(update, None, kwargs)
|
MLPY/Lib/site-packages/mpmath/calculus/inverselaplace.py
ADDED
@@ -0,0 +1,973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# contributed to mpmath by Kristopher L. Kuhlman, February 2017
|
2 |
+
# contributed to mpmath by Guillermo Navas-Palencia, February 2022
|
3 |
+
|
4 |
+
class InverseLaplaceTransform(object):
|
5 |
+
r"""
|
6 |
+
Inverse Laplace transform methods are implemented using this
|
7 |
+
class, in order to simplify the code and provide a common
|
8 |
+
infrastructure.
|
9 |
+
|
10 |
+
Implement a custom inverse Laplace transform algorithm by
|
11 |
+
subclassing :class:`InverseLaplaceTransform` and implementing the
|
12 |
+
appropriate methods. The subclass can then be used by
|
13 |
+
:func:`~mpmath.invertlaplace` by passing it as the *method*
|
14 |
+
argument.
|
15 |
+
"""
|
16 |
+
|
17 |
+
def __init__(self, ctx):
|
18 |
+
self.ctx = ctx
|
19 |
+
|
20 |
+
def calc_laplace_parameter(self, t, **kwargs):
|
21 |
+
r"""
|
22 |
+
Determine the vector of Laplace parameter values needed for an
|
23 |
+
algorithm, this will depend on the choice of algorithm (de
|
24 |
+
Hoog is default), the algorithm-specific parameters passed (or
|
25 |
+
default ones), and desired time.
|
26 |
+
"""
|
27 |
+
raise NotImplementedError
|
28 |
+
|
29 |
+
def calc_time_domain_solution(self, fp):
|
30 |
+
r"""
|
31 |
+
Compute the time domain solution, after computing the
|
32 |
+
Laplace-space function evaluations at the abscissa required
|
33 |
+
for the algorithm. Abscissa computed for one algorithm are
|
34 |
+
typically not useful for another algorithm.
|
35 |
+
"""
|
36 |
+
raise NotImplementedError
|
37 |
+
|
38 |
+
|
39 |
+
class FixedTalbot(InverseLaplaceTransform):
|
40 |
+
|
41 |
+
def calc_laplace_parameter(self, t, **kwargs):
|
42 |
+
r"""The "fixed" Talbot method deforms the Bromwich contour towards
|
43 |
+
`-\infty` in the shape of a parabola. Traditionally the Talbot
|
44 |
+
algorithm has adjustable parameters, but the "fixed" version
|
45 |
+
does not. The `r` parameter could be passed in as a parameter,
|
46 |
+
if you want to override the default given by (Abate & Valko,
|
47 |
+
2004).
|
48 |
+
|
49 |
+
The Laplace parameter is sampled along a parabola opening
|
50 |
+
along the negative imaginary axis, with the base of the
|
51 |
+
parabola along the real axis at
|
52 |
+
`p=\frac{r}{t_\mathrm{max}}`. As the number of terms used in
|
53 |
+
the approximation (degree) grows, the abscissa required for
|
54 |
+
function evaluation tend towards `-\infty`, requiring high
|
55 |
+
precision to prevent overflow. If any poles, branch cuts or
|
56 |
+
other singularities exist such that the deformed Bromwich
|
57 |
+
contour lies to the left of the singularity, the method will
|
58 |
+
fail.
|
59 |
+
|
60 |
+
**Optional arguments**
|
61 |
+
|
62 |
+
:class:`~mpmath.calculus.inverselaplace.FixedTalbot.calc_laplace_parameter`
|
63 |
+
recognizes the following keywords
|
64 |
+
|
65 |
+
*tmax*
|
66 |
+
maximum time associated with vector of times
|
67 |
+
(typically just the time requested)
|
68 |
+
*degree*
|
69 |
+
integer order of approximation (M = number of terms)
|
70 |
+
*r*
|
71 |
+
abscissa for `p_0` (otherwise computed using rule
|
72 |
+
of thumb `2M/5`)
|
73 |
+
|
74 |
+
The working precision will be increased according to a rule of
|
75 |
+
thumb. If 'degree' is not specified, the working precision and
|
76 |
+
degree are chosen to hopefully achieve the dps of the calling
|
77 |
+
context. If 'degree' is specified, the working precision is
|
78 |
+
chosen to achieve maximum resulting precision for the
|
79 |
+
specified degree.
|
80 |
+
|
81 |
+
.. math ::
|
82 |
+
|
83 |
+
p_0=\frac{r}{t}
|
84 |
+
|
85 |
+
.. math ::
|
86 |
+
|
87 |
+
p_i=\frac{i r \pi}{Mt_\mathrm{max}}\left[\cot\left(
|
88 |
+
\frac{i\pi}{M}\right) + j \right] \qquad 1\le i <M
|
89 |
+
|
90 |
+
where `j=\sqrt{-1}`, `r=2M/5`, and `t_\mathrm{max}` is the
|
91 |
+
maximum specified time.
|
92 |
+
|
93 |
+
"""
|
94 |
+
|
95 |
+
# required
|
96 |
+
# ------------------------------
|
97 |
+
# time of desired approximation
|
98 |
+
self.t = self.ctx.convert(t)
|
99 |
+
|
100 |
+
# optional
|
101 |
+
# ------------------------------
|
102 |
+
# maximum time desired (used for scaling) default is requested
|
103 |
+
# time.
|
104 |
+
self.tmax = self.ctx.convert(kwargs.get('tmax', self.t))
|
105 |
+
|
106 |
+
# empirical relationships used here based on a linear fit of
|
107 |
+
# requested and delivered dps for exponentially decaying time
|
108 |
+
# functions for requested dps up to 512.
|
109 |
+
|
110 |
+
if 'degree' in kwargs:
|
111 |
+
self.degree = kwargs['degree']
|
112 |
+
self.dps_goal = self.degree
|
113 |
+
else:
|
114 |
+
self.dps_goal = int(1.72*self.ctx.dps)
|
115 |
+
self.degree = max(12, int(1.38*self.dps_goal))
|
116 |
+
|
117 |
+
M = self.degree
|
118 |
+
|
119 |
+
# this is adjusting the dps of the calling context hopefully
|
120 |
+
# the caller doesn't monkey around with it between calling
|
121 |
+
# this routine and calc_time_domain_solution()
|
122 |
+
self.dps_orig = self.ctx.dps
|
123 |
+
self.ctx.dps = self.dps_goal
|
124 |
+
|
125 |
+
# Abate & Valko rule of thumb for r parameter
|
126 |
+
self.r = kwargs.get('r', self.ctx.fraction(2, 5)*M)
|
127 |
+
|
128 |
+
self.theta = self.ctx.linspace(0.0, self.ctx.pi, M+1)
|
129 |
+
|
130 |
+
self.cot_theta = self.ctx.matrix(M, 1)
|
131 |
+
self.cot_theta[0] = 0 # not used
|
132 |
+
|
133 |
+
# all but time-dependent part of p
|
134 |
+
self.delta = self.ctx.matrix(M, 1)
|
135 |
+
self.delta[0] = self.r
|
136 |
+
|
137 |
+
for i in range(1, M):
|
138 |
+
self.cot_theta[i] = self.ctx.cot(self.theta[i])
|
139 |
+
self.delta[i] = self.r*self.theta[i]*(self.cot_theta[i] + 1j)
|
140 |
+
|
141 |
+
self.p = self.ctx.matrix(M, 1)
|
142 |
+
self.p = self.delta/self.tmax
|
143 |
+
|
144 |
+
# NB: p is complex (mpc)
|
145 |
+
|
146 |
+
def calc_time_domain_solution(self, fp, t, manual_prec=False):
|
147 |
+
r"""The fixed Talbot time-domain solution is computed from the
|
148 |
+
Laplace-space function evaluations using
|
149 |
+
|
150 |
+
.. math ::
|
151 |
+
|
152 |
+
f(t,M)=\frac{2}{5t}\sum_{k=0}^{M-1}\Re \left[
|
153 |
+
\gamma_k \bar{f}(p_k)\right]
|
154 |
+
|
155 |
+
where
|
156 |
+
|
157 |
+
.. math ::
|
158 |
+
|
159 |
+
\gamma_0 = \frac{1}{2}e^{r}\bar{f}(p_0)
|
160 |
+
|
161 |
+
.. math ::
|
162 |
+
|
163 |
+
\gamma_k = e^{tp_k}\left\lbrace 1 + \frac{jk\pi}{M}\left[1 +
|
164 |
+
\cot \left( \frac{k \pi}{M} \right)^2 \right] - j\cot\left(
|
165 |
+
\frac{k \pi}{M}\right)\right \rbrace \qquad 1\le k<M.
|
166 |
+
|
167 |
+
Again, `j=\sqrt{-1}`.
|
168 |
+
|
169 |
+
Before calling this function, call
|
170 |
+
:class:`~mpmath.calculus.inverselaplace.FixedTalbot.calc_laplace_parameter`
|
171 |
+
to set the parameters and compute the required coefficients.
|
172 |
+
|
173 |
+
**References**
|
174 |
+
|
175 |
+
1. Abate, J., P. Valko (2004). Multi-precision Laplace
|
176 |
+
transform inversion. *International Journal for Numerical
|
177 |
+
Methods in Engineering* 60:979-993,
|
178 |
+
http://dx.doi.org/10.1002/nme.995
|
179 |
+
2. Talbot, A. (1979). The accurate numerical inversion of
|
180 |
+
Laplace transforms. *IMA Journal of Applied Mathematics*
|
181 |
+
23(1):97, http://dx.doi.org/10.1093/imamat/23.1.97
|
182 |
+
"""
|
183 |
+
|
184 |
+
# required
|
185 |
+
# ------------------------------
|
186 |
+
self.t = self.ctx.convert(t)
|
187 |
+
|
188 |
+
# assume fp was computed from p matrix returned from
|
189 |
+
# calc_laplace_parameter(), so is already a list or matrix of
|
190 |
+
# mpmath 'mpc' types
|
191 |
+
|
192 |
+
# these were computed in previous call to
|
193 |
+
# calc_laplace_parameter()
|
194 |
+
theta = self.theta
|
195 |
+
delta = self.delta
|
196 |
+
M = self.degree
|
197 |
+
p = self.p
|
198 |
+
r = self.r
|
199 |
+
|
200 |
+
ans = self.ctx.matrix(M, 1)
|
201 |
+
ans[0] = self.ctx.exp(delta[0])*fp[0]/2
|
202 |
+
|
203 |
+
for i in range(1, M):
|
204 |
+
ans[i] = self.ctx.exp(delta[i])*fp[i]*(
|
205 |
+
1 + 1j*theta[i]*(1 + self.cot_theta[i]**2) -
|
206 |
+
1j*self.cot_theta[i])
|
207 |
+
|
208 |
+
result = self.ctx.fraction(2, 5)*self.ctx.fsum(ans)/self.t
|
209 |
+
|
210 |
+
# setting dps back to value when calc_laplace_parameter was
|
211 |
+
# called, unless flag is set.
|
212 |
+
if not manual_prec:
|
213 |
+
self.ctx.dps = self.dps_orig
|
214 |
+
|
215 |
+
return result.real
|
216 |
+
|
217 |
+
|
218 |
+
# ****************************************
|
219 |
+
|
220 |
+
class Stehfest(InverseLaplaceTransform):
|
221 |
+
|
222 |
+
def calc_laplace_parameter(self, t, **kwargs):
|
223 |
+
r"""
|
224 |
+
The Gaver-Stehfest method is a discrete approximation of the
|
225 |
+
Widder-Post inversion algorithm, rather than a direct
|
226 |
+
approximation of the Bromwich contour integral.
|
227 |
+
|
228 |
+
The method abscissa along the real axis, and therefore has
|
229 |
+
issues inverting oscillatory functions (which have poles in
|
230 |
+
pairs away from the real axis).
|
231 |
+
|
232 |
+
The working precision will be increased according to a rule of
|
233 |
+
thumb. If 'degree' is not specified, the working precision and
|
234 |
+
degree are chosen to hopefully achieve the dps of the calling
|
235 |
+
context. If 'degree' is specified, the working precision is
|
236 |
+
chosen to achieve maximum resulting precision for the
|
237 |
+
specified degree.
|
238 |
+
|
239 |
+
.. math ::
|
240 |
+
|
241 |
+
p_k = \frac{k \log 2}{t} \qquad 1 \le k \le M
|
242 |
+
"""
|
243 |
+
|
244 |
+
# required
|
245 |
+
# ------------------------------
|
246 |
+
# time of desired approximation
|
247 |
+
self.t = self.ctx.convert(t)
|
248 |
+
|
249 |
+
# optional
|
250 |
+
# ------------------------------
|
251 |
+
|
252 |
+
# empirical relationships used here based on a linear fit of
|
253 |
+
# requested and delivered dps for exponentially decaying time
|
254 |
+
# functions for requested dps up to 512.
|
255 |
+
|
256 |
+
if 'degree' in kwargs:
|
257 |
+
self.degree = kwargs['degree']
|
258 |
+
self.dps_goal = int(1.38*self.degree)
|
259 |
+
else:
|
260 |
+
self.dps_goal = int(2.93*self.ctx.dps)
|
261 |
+
self.degree = max(16, self.dps_goal)
|
262 |
+
|
263 |
+
# _coeff routine requires even degree
|
264 |
+
if self.degree % 2 > 0:
|
265 |
+
self.degree += 1
|
266 |
+
|
267 |
+
M = self.degree
|
268 |
+
|
269 |
+
# this is adjusting the dps of the calling context
|
270 |
+
# hopefully the caller doesn't monkey around with it
|
271 |
+
# between calling this routine and calc_time_domain_solution()
|
272 |
+
self.dps_orig = self.ctx.dps
|
273 |
+
self.ctx.dps = self.dps_goal
|
274 |
+
|
275 |
+
self.V = self._coeff()
|
276 |
+
self.p = self.ctx.matrix(self.ctx.arange(1, M+1))*self.ctx.ln2/self.t
|
277 |
+
|
278 |
+
# NB: p is real (mpf)
|
279 |
+
|
280 |
+
def _coeff(self):
|
281 |
+
r"""Salzer summation weights (aka, "Stehfest coefficients")
|
282 |
+
only depend on the approximation order (M) and the precision"""
|
283 |
+
|
284 |
+
M = self.degree
|
285 |
+
M2 = int(M/2) # checked earlier that M is even
|
286 |
+
|
287 |
+
V = self.ctx.matrix(M, 1)
|
288 |
+
|
289 |
+
# Salzer summation weights
|
290 |
+
# get very large in magnitude and oscillate in sign,
|
291 |
+
# if the precision is not high enough, there will be
|
292 |
+
# catastrophic cancellation
|
293 |
+
for k in range(1, M+1):
|
294 |
+
z = self.ctx.matrix(min(k, M2)+1, 1)
|
295 |
+
for j in range(int((k+1)/2), min(k, M2)+1):
|
296 |
+
z[j] = (self.ctx.power(j, M2)*self.ctx.fac(2*j)/
|
297 |
+
(self.ctx.fac(M2-j)*self.ctx.fac(j)*
|
298 |
+
self.ctx.fac(j-1)*self.ctx.fac(k-j)*
|
299 |
+
self.ctx.fac(2*j-k)))
|
300 |
+
V[k-1] = self.ctx.power(-1, k+M2)*self.ctx.fsum(z)
|
301 |
+
|
302 |
+
return V
|
303 |
+
|
304 |
+
def calc_time_domain_solution(self, fp, t, manual_prec=False):
|
305 |
+
r"""Compute time-domain Stehfest algorithm solution.
|
306 |
+
|
307 |
+
.. math ::
|
308 |
+
|
309 |
+
f(t,M) = \frac{\log 2}{t} \sum_{k=1}^{M} V_k \bar{f}\left(
|
310 |
+
p_k \right)
|
311 |
+
|
312 |
+
where
|
313 |
+
|
314 |
+
.. math ::
|
315 |
+
|
316 |
+
V_k = (-1)^{k + N/2} \sum^{\min(k,N/2)}_{i=\lfloor(k+1)/2 \rfloor}
|
317 |
+
\frac{i^{\frac{N}{2}}(2i)!}{\left(\frac{N}{2}-i \right)! \, i! \,
|
318 |
+
\left(i-1 \right)! \, \left(k-i\right)! \, \left(2i-k \right)!}
|
319 |
+
|
320 |
+
As the degree increases, the abscissa (`p_k`) only increase
|
321 |
+
linearly towards `\infty`, but the Stehfest coefficients
|
322 |
+
(`V_k`) alternate in sign and increase rapidly in sign,
|
323 |
+
requiring high precision to prevent overflow or loss of
|
324 |
+
significance when evaluating the sum.
|
325 |
+
|
326 |
+
**References**
|
327 |
+
|
328 |
+
1. Widder, D. (1941). *The Laplace Transform*. Princeton.
|
329 |
+
2. Stehfest, H. (1970). Algorithm 368: numerical inversion of
|
330 |
+
Laplace transforms. *Communications of the ACM* 13(1):47-49,
|
331 |
+
http://dx.doi.org/10.1145/361953.361969
|
332 |
+
|
333 |
+
"""
|
334 |
+
|
335 |
+
# required
|
336 |
+
self.t = self.ctx.convert(t)
|
337 |
+
|
338 |
+
# assume fp was computed from p matrix returned from
|
339 |
+
# calc_laplace_parameter(), so is already
|
340 |
+
# a list or matrix of mpmath 'mpf' types
|
341 |
+
|
342 |
+
result = self.ctx.fdot(self.V, fp)*self.ctx.ln2/self.t
|
343 |
+
|
344 |
+
# setting dps back to value when calc_laplace_parameter was called
|
345 |
+
if not manual_prec:
|
346 |
+
self.ctx.dps = self.dps_orig
|
347 |
+
|
348 |
+
# ignore any small imaginary part
|
349 |
+
return result.real
|
350 |
+
|
351 |
+
|
352 |
+
# ****************************************
|
353 |
+
|
354 |
+
class deHoog(InverseLaplaceTransform):
|
355 |
+
|
356 |
+
def calc_laplace_parameter(self, t, **kwargs):
|
357 |
+
r"""the de Hoog, Knight & Stokes algorithm is an
|
358 |
+
accelerated form of the Fourier series numerical
|
359 |
+
inverse Laplace transform algorithms.
|
360 |
+
|
361 |
+
.. math ::
|
362 |
+
|
363 |
+
p_k = \gamma + \frac{jk}{T} \qquad 0 \le k < 2M+1
|
364 |
+
|
365 |
+
where
|
366 |
+
|
367 |
+
.. math ::
|
368 |
+
|
369 |
+
\gamma = \alpha - \frac{\log \mathrm{tol}}{2T},
|
370 |
+
|
371 |
+
`j=\sqrt{-1}`, `T = 2t_\mathrm{max}` is a scaled time,
|
372 |
+
`\alpha=10^{-\mathrm{dps\_goal}}` is the real part of the
|
373 |
+
rightmost pole or singularity, which is chosen based on the
|
374 |
+
desired accuracy (assuming the rightmost singularity is 0),
|
375 |
+
and `\mathrm{tol}=10\alpha` is the desired tolerance, which is
|
376 |
+
chosen in relation to `\alpha`.`
|
377 |
+
|
378 |
+
When increasing the degree, the abscissa increase towards
|
379 |
+
`j\infty`, but more slowly than the fixed Talbot
|
380 |
+
algorithm. The de Hoog et al. algorithm typically does better
|
381 |
+
with oscillatory functions of time, and less well-behaved
|
382 |
+
functions. The method tends to be slower than the Talbot and
|
383 |
+
Stehfest algorithsm, especially so at very high precision
|
384 |
+
(e.g., `>500` digits precision).
|
385 |
+
|
386 |
+
"""
|
387 |
+
|
388 |
+
# required
|
389 |
+
# ------------------------------
|
390 |
+
self.t = self.ctx.convert(t)
|
391 |
+
|
392 |
+
# optional
|
393 |
+
# ------------------------------
|
394 |
+
self.tmax = kwargs.get('tmax', self.t)
|
395 |
+
|
396 |
+
# empirical relationships used here based on a linear fit of
|
397 |
+
# requested and delivered dps for exponentially decaying time
|
398 |
+
# functions for requested dps up to 512.
|
399 |
+
|
400 |
+
if 'degree' in kwargs:
|
401 |
+
self.degree = kwargs['degree']
|
402 |
+
self.dps_goal = int(1.38*self.degree)
|
403 |
+
else:
|
404 |
+
self.dps_goal = int(self.ctx.dps*1.36)
|
405 |
+
self.degree = max(10, self.dps_goal)
|
406 |
+
|
407 |
+
# 2*M+1 terms in approximation
|
408 |
+
M = self.degree
|
409 |
+
|
410 |
+
# adjust alpha component of abscissa of convergence for higher
|
411 |
+
# precision
|
412 |
+
tmp = self.ctx.power(10.0, -self.dps_goal)
|
413 |
+
self.alpha = self.ctx.convert(kwargs.get('alpha', tmp))
|
414 |
+
|
415 |
+
# desired tolerance (here simply related to alpha)
|
416 |
+
self.tol = self.ctx.convert(kwargs.get('tol', self.alpha*10.0))
|
417 |
+
self.np = 2*self.degree+1 # number of terms in approximation
|
418 |
+
|
419 |
+
# this is adjusting the dps of the calling context
|
420 |
+
# hopefully the caller doesn't monkey around with it
|
421 |
+
# between calling this routine and calc_time_domain_solution()
|
422 |
+
self.dps_orig = self.ctx.dps
|
423 |
+
self.ctx.dps = self.dps_goal
|
424 |
+
|
425 |
+
# scaling factor (likely tun-able, but 2 is typical)
|
426 |
+
self.scale = kwargs.get('scale', 2)
|
427 |
+
self.T = self.ctx.convert(kwargs.get('T', self.scale*self.tmax))
|
428 |
+
|
429 |
+
self.p = self.ctx.matrix(2*M+1, 1)
|
430 |
+
self.gamma = self.alpha - self.ctx.log(self.tol)/(self.scale*self.T)
|
431 |
+
self.p = (self.gamma + self.ctx.pi*
|
432 |
+
self.ctx.matrix(self.ctx.arange(self.np))/self.T*1j)
|
433 |
+
|
434 |
+
# NB: p is complex (mpc)
|
435 |
+
|
436 |
+
def calc_time_domain_solution(self, fp, t, manual_prec=False):
|
437 |
+
r"""Calculate time-domain solution for
|
438 |
+
de Hoog, Knight & Stokes algorithm.
|
439 |
+
|
440 |
+
The un-accelerated Fourier series approach is:
|
441 |
+
|
442 |
+
.. math ::
|
443 |
+
|
444 |
+
f(t,2M+1) = \frac{e^{\gamma t}}{T} \sum_{k=0}^{2M}{}^{'}
|
445 |
+
\Re\left[\bar{f}\left( p_k \right)
|
446 |
+
e^{i\pi t/T} \right],
|
447 |
+
|
448 |
+
where the prime on the summation indicates the first term is halved.
|
449 |
+
|
450 |
+
This simplistic approach requires so many function evaluations
|
451 |
+
that it is not practical. Non-linear acceleration is
|
452 |
+
accomplished via Pade-approximation and an analytic expression
|
453 |
+
for the remainder of the continued fraction. See the original
|
454 |
+
paper (reference 2 below) a detailed description of the
|
455 |
+
numerical approach.
|
456 |
+
|
457 |
+
**References**
|
458 |
+
|
459 |
+
1. Davies, B. (2005). *Integral Transforms and their
|
460 |
+
Applications*, Third Edition. Springer.
|
461 |
+
2. de Hoog, F., J. Knight, A. Stokes (1982). An improved
|
462 |
+
method for numerical inversion of Laplace transforms. *SIAM
|
463 |
+
Journal of Scientific and Statistical Computing* 3:357-366,
|
464 |
+
http://dx.doi.org/10.1137/0903022
|
465 |
+
|
466 |
+
"""
|
467 |
+
|
468 |
+
M = self.degree
|
469 |
+
np = self.np
|
470 |
+
T = self.T
|
471 |
+
|
472 |
+
self.t = self.ctx.convert(t)
|
473 |
+
|
474 |
+
# would it be useful to try re-using
|
475 |
+
# space between e&q and A&B?
|
476 |
+
e = self.ctx.zeros(np, M+1)
|
477 |
+
q = self.ctx.matrix(2*M, M)
|
478 |
+
d = self.ctx.matrix(np, 1)
|
479 |
+
A = self.ctx.zeros(np+1, 1)
|
480 |
+
B = self.ctx.ones(np+1, 1)
|
481 |
+
|
482 |
+
# initialize Q-D table
|
483 |
+
e[:, 0] = 0.0 + 0j
|
484 |
+
q[0, 0] = fp[1]/(fp[0]/2)
|
485 |
+
for i in range(1, 2*M):
|
486 |
+
q[i, 0] = fp[i+1]/fp[i]
|
487 |
+
|
488 |
+
# rhombus rule for filling triangular Q-D table (e & q)
|
489 |
+
for r in range(1, M+1):
|
490 |
+
# start with e, column 1, 0:2*M-2
|
491 |
+
mr = 2*(M-r) + 1
|
492 |
+
e[0:mr, r] = q[1:mr+1, r-1] - q[0:mr, r-1] + e[1:mr+1, r-1]
|
493 |
+
if not r == M:
|
494 |
+
rq = r+1
|
495 |
+
mr = 2*(M-rq)+1 + 2
|
496 |
+
for i in range(mr):
|
497 |
+
q[i, rq-1] = q[i+1, rq-2]*e[i+1, rq-1]/e[i, rq-1]
|
498 |
+
|
499 |
+
# build up continued fraction coefficients (d)
|
500 |
+
d[0] = fp[0]/2
|
501 |
+
for r in range(1, M+1):
|
502 |
+
d[2*r-1] = -q[0, r-1] # even terms
|
503 |
+
d[2*r] = -e[0, r] # odd terms
|
504 |
+
|
505 |
+
# seed A and B for recurrence
|
506 |
+
A[0] = 0.0 + 0.0j
|
507 |
+
A[1] = d[0]
|
508 |
+
B[0:2] = 1.0 + 0.0j
|
509 |
+
|
510 |
+
# base of the power series
|
511 |
+
z = self.ctx.expjpi(self.t/T) # i*pi is already in fcn
|
512 |
+
|
513 |
+
# coefficients of Pade approximation (A & B)
|
514 |
+
# using recurrence for all but last term
|
515 |
+
for i in range(1, 2*M):
|
516 |
+
A[i+1] = A[i] + d[i]*A[i-1]*z
|
517 |
+
B[i+1] = B[i] + d[i]*B[i-1]*z
|
518 |
+
|
519 |
+
# "improved remainder" to continued fraction
|
520 |
+
brem = (1 + (d[2*M-1] - d[2*M])*z)/2
|
521 |
+
# powm1(x,y) computes x^y - 1 more accurately near zero
|
522 |
+
rem = brem*self.ctx.powm1(1 + d[2*M]*z/brem,
|
523 |
+
self.ctx.fraction(1, 2))
|
524 |
+
|
525 |
+
# last term of recurrence using new remainder
|
526 |
+
A[np] = A[2*M] + rem*A[2*M-1]
|
527 |
+
B[np] = B[2*M] + rem*B[2*M-1]
|
528 |
+
|
529 |
+
# diagonal Pade approximation
|
530 |
+
# F=A/B represents accelerated trapezoid rule
|
531 |
+
result = self.ctx.exp(self.gamma*self.t)/T*(A[np]/B[np]).real
|
532 |
+
|
533 |
+
# setting dps back to value when calc_laplace_parameter was called
|
534 |
+
if not manual_prec:
|
535 |
+
self.ctx.dps = self.dps_orig
|
536 |
+
|
537 |
+
return result
|
538 |
+
|
539 |
+
|
540 |
+
# ****************************************
|
541 |
+
|
542 |
+
class Cohen(InverseLaplaceTransform):
|
543 |
+
|
544 |
+
def calc_laplace_parameter(self, t, **kwargs):
|
545 |
+
r"""The Cohen algorithm accelerates the convergence of the nearly
|
546 |
+
alternating series resulting from the application of the trapezoidal
|
547 |
+
rule to the Bromwich contour inversion integral.
|
548 |
+
|
549 |
+
.. math ::
|
550 |
+
|
551 |
+
p_k = \frac{\gamma}{2 t} + \frac{\pi i k}{t} \qquad 0 \le k < M
|
552 |
+
|
553 |
+
where
|
554 |
+
|
555 |
+
.. math ::
|
556 |
+
|
557 |
+
\gamma = \frac{2}{3} (d + \log(10) + \log(2 t)),
|
558 |
+
|
559 |
+
`d = \mathrm{dps\_goal}`, which is chosen based on the desired
|
560 |
+
accuracy using the method developed in [1] to improve numerical
|
561 |
+
stability. The Cohen algorithm shows robustness similar to the de Hoog
|
562 |
+
et al. algorithm, but it is faster than the fixed Talbot algorithm.
|
563 |
+
|
564 |
+
**Optional arguments**
|
565 |
+
|
566 |
+
*degree*
|
567 |
+
integer order of the approximation (M = number of terms)
|
568 |
+
*alpha*
|
569 |
+
abscissa for `p_0` (controls the discretization error)
|
570 |
+
|
571 |
+
The working precision will be increased according to a rule of
|
572 |
+
thumb. If 'degree' is not specified, the working precision and
|
573 |
+
degree are chosen to hopefully achieve the dps of the calling
|
574 |
+
context. If 'degree' is specified, the working precision is
|
575 |
+
chosen to achieve maximum resulting precision for the
|
576 |
+
specified degree.
|
577 |
+
|
578 |
+
**References**
|
579 |
+
|
580 |
+
1. P. Glasserman, J. Ruiz-Mata (2006). Computing the credit loss
|
581 |
+
distribution in the Gaussian copula model: a comparison of methods.
|
582 |
+
*Journal of Credit Risk* 2(4):33-66, 10.21314/JCR.2006.057
|
583 |
+
|
584 |
+
"""
|
585 |
+
self.t = self.ctx.convert(t)
|
586 |
+
|
587 |
+
if 'degree' in kwargs:
|
588 |
+
self.degree = kwargs['degree']
|
589 |
+
self.dps_goal = int(1.5 * self.degree)
|
590 |
+
else:
|
591 |
+
self.dps_goal = int(self.ctx.dps * 1.74)
|
592 |
+
self.degree = max(22, int(1.31 * self.dps_goal))
|
593 |
+
|
594 |
+
M = self.degree + 1
|
595 |
+
|
596 |
+
# this is adjusting the dps of the calling context hopefully
|
597 |
+
# the caller doesn't monkey around with it between calling
|
598 |
+
# this routine and calc_time_domain_solution()
|
599 |
+
self.dps_orig = self.ctx.dps
|
600 |
+
self.ctx.dps = self.dps_goal
|
601 |
+
|
602 |
+
ttwo = 2 * self.t
|
603 |
+
tmp = self.ctx.dps * self.ctx.log(10) + self.ctx.log(ttwo)
|
604 |
+
tmp = self.ctx.fraction(2, 3) * tmp
|
605 |
+
self.alpha = self.ctx.convert(kwargs.get('alpha', tmp))
|
606 |
+
|
607 |
+
# all but time-dependent part of p
|
608 |
+
a_t = self.alpha / ttwo
|
609 |
+
p_t = self.ctx.pi * 1j / self.t
|
610 |
+
|
611 |
+
self.p = self.ctx.matrix(M, 1)
|
612 |
+
self.p[0] = a_t
|
613 |
+
|
614 |
+
for i in range(1, M):
|
615 |
+
self.p[i] = a_t + i * p_t
|
616 |
+
|
617 |
+
def calc_time_domain_solution(self, fp, t, manual_prec=False):
|
618 |
+
r"""Calculate time-domain solution for Cohen algorithm.
|
619 |
+
|
620 |
+
The accelerated nearly alternating series is:
|
621 |
+
|
622 |
+
.. math ::
|
623 |
+
|
624 |
+
f(t, M) = \frac{e^{\gamma / 2}}{t} \left[\frac{1}{2}
|
625 |
+
\Re\left(\bar{f}\left(\frac{\gamma}{2t}\right) \right) -
|
626 |
+
\sum_{k=0}^{M-1}\frac{c_{M,k}}{d_M}\Re\left(\bar{f}
|
627 |
+
\left(\frac{\gamma + 2(k+1) \pi i}{2t}\right)\right)\right],
|
628 |
+
|
629 |
+
where coefficients `\frac{c_{M, k}}{d_M}` are described in [1].
|
630 |
+
|
631 |
+
1. H. Cohen, F. Rodriguez Villegas, D. Zagier (2000). Convergence
|
632 |
+
acceleration of alternating series. *Experiment. Math* 9(1):3-12
|
633 |
+
|
634 |
+
"""
|
635 |
+
self.t = self.ctx.convert(t)
|
636 |
+
|
637 |
+
n = self.degree
|
638 |
+
M = n + 1
|
639 |
+
|
640 |
+
A = self.ctx.matrix(M, 1)
|
641 |
+
for i in range(M):
|
642 |
+
A[i] = fp[i].real
|
643 |
+
|
644 |
+
d = (3 + self.ctx.sqrt(8)) ** n
|
645 |
+
d = (d + 1 / d) / 2
|
646 |
+
b = -self.ctx.one
|
647 |
+
c = -d
|
648 |
+
s = 0
|
649 |
+
|
650 |
+
for k in range(n):
|
651 |
+
c = b - c
|
652 |
+
s = s + c * A[k + 1]
|
653 |
+
b = 2 * (k + n) * (k - n) * b / ((2 * k + 1) * (k + self.ctx.one))
|
654 |
+
|
655 |
+
result = self.ctx.exp(self.alpha / 2) / self.t * (A[0] / 2 - s / d)
|
656 |
+
|
657 |
+
# setting dps back to value when calc_laplace_parameter was
|
658 |
+
# called, unless flag is set.
|
659 |
+
if not manual_prec:
|
660 |
+
self.ctx.dps = self.dps_orig
|
661 |
+
|
662 |
+
return result
|
663 |
+
|
664 |
+
|
665 |
+
# ****************************************
|
666 |
+
|
667 |
+
class LaplaceTransformInversionMethods(object):
|
668 |
+
def __init__(ctx, *args, **kwargs):
|
669 |
+
ctx._fixed_talbot = FixedTalbot(ctx)
|
670 |
+
ctx._stehfest = Stehfest(ctx)
|
671 |
+
ctx._de_hoog = deHoog(ctx)
|
672 |
+
ctx._cohen = Cohen(ctx)
|
673 |
+
|
674 |
+
def invertlaplace(ctx, f, t, **kwargs):
|
675 |
+
r"""Computes the numerical inverse Laplace transform for a
|
676 |
+
Laplace-space function at a given time. The function being
|
677 |
+
evaluated is assumed to be a real-valued function of time.
|
678 |
+
|
679 |
+
The user must supply a Laplace-space function `\bar{f}(p)`,
|
680 |
+
and a desired time at which to estimate the time-domain
|
681 |
+
solution `f(t)`.
|
682 |
+
|
683 |
+
A few basic examples of Laplace-space functions with known
|
684 |
+
inverses (see references [1,2]) :
|
685 |
+
|
686 |
+
.. math ::
|
687 |
+
|
688 |
+
\mathcal{L}\left\lbrace f(t) \right\rbrace=\bar{f}(p)
|
689 |
+
|
690 |
+
.. math ::
|
691 |
+
|
692 |
+
\mathcal{L}^{-1}\left\lbrace \bar{f}(p) \right\rbrace = f(t)
|
693 |
+
|
694 |
+
.. math ::
|
695 |
+
|
696 |
+
\bar{f}(p) = \frac{1}{(p+1)^2}
|
697 |
+
|
698 |
+
.. math ::
|
699 |
+
|
700 |
+
f(t) = t e^{-t}
|
701 |
+
|
702 |
+
>>> from mpmath import *
|
703 |
+
>>> mp.dps = 15; mp.pretty = True
|
704 |
+
>>> tt = [0.001, 0.01, 0.1, 1, 10]
|
705 |
+
>>> fp = lambda p: 1/(p+1)**2
|
706 |
+
>>> ft = lambda t: t*exp(-t)
|
707 |
+
>>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='talbot')
|
708 |
+
(0.000999000499833375, 8.57923043561212e-20)
|
709 |
+
>>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='talbot')
|
710 |
+
(0.00990049833749168, 3.27007646698047e-19)
|
711 |
+
>>> ft(tt[2]),ft(tt[2])-invertlaplace(fp,tt[2],method='talbot')
|
712 |
+
(0.090483741803596, -1.75215800052168e-18)
|
713 |
+
>>> ft(tt[3]),ft(tt[3])-invertlaplace(fp,tt[3],method='talbot')
|
714 |
+
(0.367879441171442, 1.2428864009344e-17)
|
715 |
+
>>> ft(tt[4]),ft(tt[4])-invertlaplace(fp,tt[4],method='talbot')
|
716 |
+
(0.000453999297624849, 4.04513489306658e-20)
|
717 |
+
|
718 |
+
The methods also work for higher precision:
|
719 |
+
|
720 |
+
>>> mp.dps = 100; mp.pretty = True
|
721 |
+
>>> nstr(ft(tt[0]),15),nstr(ft(tt[0])-invertlaplace(fp,tt[0],method='talbot'),15)
|
722 |
+
('0.000999000499833375', '-4.96868310693356e-105')
|
723 |
+
>>> nstr(ft(tt[1]),15),nstr(ft(tt[1])-invertlaplace(fp,tt[1],method='talbot'),15)
|
724 |
+
('0.00990049833749168', '1.23032291513122e-104')
|
725 |
+
|
726 |
+
.. math ::
|
727 |
+
|
728 |
+
\bar{f}(p) = \frac{1}{p^2+1}
|
729 |
+
|
730 |
+
.. math ::
|
731 |
+
|
732 |
+
f(t) = \mathrm{J}_0(t)
|
733 |
+
|
734 |
+
>>> mp.dps = 15; mp.pretty = True
|
735 |
+
>>> fp = lambda p: 1/sqrt(p*p + 1)
|
736 |
+
>>> ft = lambda t: besselj(0,t)
|
737 |
+
>>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='dehoog')
|
738 |
+
(0.999999750000016, -6.09717765032273e-18)
|
739 |
+
>>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='dehoog')
|
740 |
+
(0.99997500015625, -5.61756281076169e-17)
|
741 |
+
|
742 |
+
.. math ::
|
743 |
+
|
744 |
+
\bar{f}(p) = \frac{\log p}{p}
|
745 |
+
|
746 |
+
.. math ::
|
747 |
+
|
748 |
+
f(t) = -\gamma -\log t
|
749 |
+
|
750 |
+
>>> mp.dps = 15; mp.pretty = True
|
751 |
+
>>> fp = lambda p: log(p)/p
|
752 |
+
>>> ft = lambda t: -euler-log(t)
|
753 |
+
>>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='stehfest')
|
754 |
+
(6.3305396140806, -1.92126634837863e-16)
|
755 |
+
>>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='stehfest')
|
756 |
+
(4.02795452108656, -4.81486093200704e-16)
|
757 |
+
|
758 |
+
**Options**
|
759 |
+
|
760 |
+
:func:`~mpmath.invertlaplace` recognizes the following optional
|
761 |
+
keywords valid for all methods:
|
762 |
+
|
763 |
+
*method*
|
764 |
+
Chooses numerical inverse Laplace transform algorithm
|
765 |
+
(described below).
|
766 |
+
*degree*
|
767 |
+
Number of terms used in the approximation
|
768 |
+
|
769 |
+
**Algorithms**
|
770 |
+
|
771 |
+
Mpmath implements four numerical inverse Laplace transform
|
772 |
+
algorithms, attributed to: Talbot, Stehfest, and de Hoog,
|
773 |
+
Knight and Stokes. These can be selected by using
|
774 |
+
*method='talbot'*, *method='stehfest'*, *method='dehoog'* or
|
775 |
+
*method='cohen'* or by passing the classes *method=FixedTalbot*,
|
776 |
+
*method=Stehfest*, *method=deHoog*, or *method=Cohen*. The functions
|
777 |
+
:func:`~mpmath.invlaptalbot`, :func:`~mpmath.invlapstehfest`,
|
778 |
+
:func:`~mpmath.invlapdehoog`, and :func:`~mpmath.invlapcohen`
|
779 |
+
are also available as shortcuts.
|
780 |
+
|
781 |
+
All four algorithms implement a heuristic balance between the
|
782 |
+
requested precision and the precision used internally for the
|
783 |
+
calculations. This has been tuned for a typical exponentially
|
784 |
+
decaying function and precision up to few hundred decimal
|
785 |
+
digits.
|
786 |
+
|
787 |
+
The Laplace transform converts the variable time (i.e., along
|
788 |
+
a line) into a parameter given by the right half of the
|
789 |
+
complex `p`-plane. Singularities, poles, and branch cuts in
|
790 |
+
the complex `p`-plane contain all the information regarding
|
791 |
+
the time behavior of the corresponding function. Any numerical
|
792 |
+
method must therefore sample `p`-plane "close enough" to the
|
793 |
+
singularities to accurately characterize them, while not
|
794 |
+
getting too close to have catastrophic cancellation, overflow,
|
795 |
+
or underflow issues. Most significantly, if one or more of the
|
796 |
+
singularities in the `p`-plane is not on the left side of the
|
797 |
+
Bromwich contour, its effects will be left out of the computed
|
798 |
+
solution, and the answer will be completely wrong.
|
799 |
+
|
800 |
+
*Talbot*
|
801 |
+
|
802 |
+
The fixed Talbot method is high accuracy and fast, but the
|
803 |
+
method can catastrophically fail for certain classes of time-domain
|
804 |
+
behavior, including a Heaviside step function for positive
|
805 |
+
time (e.g., `H(t-2)`), or some oscillatory behaviors. The
|
806 |
+
Talbot method usually has adjustable parameters, but the
|
807 |
+
"fixed" variety implemented here does not. This method
|
808 |
+
deforms the Bromwich integral contour in the shape of a
|
809 |
+
parabola towards `-\infty`, which leads to problems
|
810 |
+
when the solution has a decaying exponential in it (e.g., a
|
811 |
+
Heaviside step function is equivalent to multiplying by a
|
812 |
+
decaying exponential in Laplace space).
|
813 |
+
|
814 |
+
*Stehfest*
|
815 |
+
|
816 |
+
The Stehfest algorithm only uses abscissa along the real axis
|
817 |
+
of the complex `p`-plane to estimate the time-domain
|
818 |
+
function. Oscillatory time-domain functions have poles away
|
819 |
+
from the real axis, so this method does not work well with
|
820 |
+
oscillatory functions, especially high-frequency ones. This
|
821 |
+
method also depends on summation of terms in a series that
|
822 |
+
grows very large, and will have catastrophic cancellation
|
823 |
+
during summation if the working precision is too low.
|
824 |
+
|
825 |
+
*de Hoog et al.*
|
826 |
+
|
827 |
+
The de Hoog, Knight, and Stokes method is essentially a
|
828 |
+
Fourier-series quadrature-type approximation to the Bromwich
|
829 |
+
contour integral, with non-linear series acceleration and an
|
830 |
+
analytical expression for the remainder term. This method is
|
831 |
+
typically one of the most robust. This method also involves the
|
832 |
+
greatest amount of overhead, so it is typically the slowest of the
|
833 |
+
four methods at high precision.
|
834 |
+
|
835 |
+
*Cohen*
|
836 |
+
|
837 |
+
The Cohen method is a trapezoidal rule approximation to the Bromwich
|
838 |
+
contour integral, with linear acceleration for alternating
|
839 |
+
series. This method is as robust as the de Hoog et al method and the
|
840 |
+
fastest of the four methods at high precision, and is therefore the
|
841 |
+
default method.
|
842 |
+
|
843 |
+
**Singularities**
|
844 |
+
|
845 |
+
All numerical inverse Laplace transform methods have problems
|
846 |
+
at large time when the Laplace-space function has poles,
|
847 |
+
singularities, or branch cuts to the right of the origin in
|
848 |
+
the complex plane. For simple poles in `\bar{f}(p)` at the
|
849 |
+
`p`-plane origin, the time function is constant in time (e.g.,
|
850 |
+
`\mathcal{L}\left\lbrace 1 \right\rbrace=1/p` has a pole at
|
851 |
+
`p=0`). A pole in `\bar{f}(p)` to the left of the origin is a
|
852 |
+
decreasing function of time (e.g., `\mathcal{L}\left\lbrace
|
853 |
+
e^{-t/2} \right\rbrace=1/(p+1/2)` has a pole at `p=-1/2`), and
|
854 |
+
a pole to the right of the origin leads to an increasing
|
855 |
+
function in time (e.g., `\mathcal{L}\left\lbrace t e^{t/4}
|
856 |
+
\right\rbrace = 1/(p-1/4)^2` has a pole at `p=1/4`). When
|
857 |
+
singularities occur off the real `p` axis, the time-domain
|
858 |
+
function is oscillatory. For example `\mathcal{L}\left\lbrace
|
859 |
+
\mathrm{J}_0(t) \right\rbrace=1/\sqrt{p^2+1}` has a branch cut
|
860 |
+
starting at `p=j=\sqrt{-1}` and is a decaying oscillatory
|
861 |
+
function, This range of behaviors is illustrated in Duffy [3]
|
862 |
+
Figure 4.10.4, p. 228.
|
863 |
+
|
864 |
+
In general as `p \rightarrow \infty` `t \rightarrow 0` and
|
865 |
+
vice-versa. All numerical inverse Laplace transform methods
|
866 |
+
require their abscissa to shift closer to the origin for
|
867 |
+
larger times. If the abscissa shift left of the rightmost
|
868 |
+
singularity in the Laplace domain, the answer will be
|
869 |
+
completely wrong (the effect of singularities to the right of
|
870 |
+
the Bromwich contour are not included in the results).
|
871 |
+
|
872 |
+
For example, the following exponentially growing function has
|
873 |
+
a pole at `p=3`:
|
874 |
+
|
875 |
+
.. math ::
|
876 |
+
|
877 |
+
\bar{f}(p)=\frac{1}{p^2-9}
|
878 |
+
|
879 |
+
.. math ::
|
880 |
+
|
881 |
+
f(t)=\frac{1}{3}\sinh 3t
|
882 |
+
|
883 |
+
>>> mp.dps = 15; mp.pretty = True
|
884 |
+
>>> fp = lambda p: 1/(p*p-9)
|
885 |
+
>>> ft = lambda t: sinh(3*t)/3
|
886 |
+
>>> tt = [0.01,0.1,1.0,10.0]
|
887 |
+
>>> ft(tt[0]),invertlaplace(fp,tt[0],method='talbot')
|
888 |
+
(0.0100015000675014, 0.0100015000675014)
|
889 |
+
>>> ft(tt[1]),invertlaplace(fp,tt[1],method='talbot')
|
890 |
+
(0.101506764482381, 0.101506764482381)
|
891 |
+
>>> ft(tt[2]),invertlaplace(fp,tt[2],method='talbot')
|
892 |
+
(3.33929164246997, 3.33929164246997)
|
893 |
+
>>> ft(tt[3]),invertlaplace(fp,tt[3],method='talbot')
|
894 |
+
(1781079096920.74, -1.61331069624091e-14)
|
895 |
+
|
896 |
+
**References**
|
897 |
+
|
898 |
+
1. [DLMF]_ section 1.14 (http://dlmf.nist.gov/1.14T4)
|
899 |
+
2. Cohen, A.M. (2007). Numerical Methods for Laplace Transform
|
900 |
+
Inversion, Springer.
|
901 |
+
3. Duffy, D.G. (1998). Advanced Engineering Mathematics, CRC Press.
|
902 |
+
|
903 |
+
**Numerical Inverse Laplace Transform Reviews**
|
904 |
+
|
905 |
+
1. Bellman, R., R.E. Kalaba, J.A. Lockett (1966). *Numerical
|
906 |
+
inversion of the Laplace transform: Applications to Biology,
|
907 |
+
Economics, Engineering, and Physics*. Elsevier.
|
908 |
+
2. Davies, B., B. Martin (1979). Numerical inversion of the
|
909 |
+
Laplace transform: a survey and comparison of methods. *Journal
|
910 |
+
of Computational Physics* 33:1-32,
|
911 |
+
http://dx.doi.org/10.1016/0021-9991(79)90025-1
|
912 |
+
3. Duffy, D.G. (1993). On the numerical inversion of Laplace
|
913 |
+
transforms: Comparison of three new methods on characteristic
|
914 |
+
problems from applications. *ACM Transactions on Mathematical
|
915 |
+
Software* 19(3):333-359, http://dx.doi.org/10.1145/155743.155788
|
916 |
+
4. Kuhlman, K.L., (2013). Review of Inverse Laplace Transform
|
917 |
+
Algorithms for Laplace-Space Numerical Approaches, *Numerical
|
918 |
+
Algorithms*, 63(2):339-355.
|
919 |
+
http://dx.doi.org/10.1007/s11075-012-9625-3
|
920 |
+
|
921 |
+
"""
|
922 |
+
|
923 |
+
rule = kwargs.get('method', 'cohen')
|
924 |
+
if type(rule) is str:
|
925 |
+
lrule = rule.lower()
|
926 |
+
if lrule == 'talbot':
|
927 |
+
rule = ctx._fixed_talbot
|
928 |
+
elif lrule == 'stehfest':
|
929 |
+
rule = ctx._stehfest
|
930 |
+
elif lrule == 'dehoog':
|
931 |
+
rule = ctx._de_hoog
|
932 |
+
elif rule == 'cohen':
|
933 |
+
rule = ctx._cohen
|
934 |
+
else:
|
935 |
+
raise ValueError("unknown invlap algorithm: %s" % rule)
|
936 |
+
else:
|
937 |
+
rule = rule(ctx)
|
938 |
+
|
939 |
+
# determine the vector of Laplace-space parameter
|
940 |
+
# needed for the requested method and desired time
|
941 |
+
rule.calc_laplace_parameter(t, **kwargs)
|
942 |
+
|
943 |
+
# compute the Laplace-space function evalutations
|
944 |
+
# at the required abscissa.
|
945 |
+
fp = [f(p) for p in rule.p]
|
946 |
+
|
947 |
+
# compute the time-domain solution from the
|
948 |
+
# Laplace-space function evaluations
|
949 |
+
return rule.calc_time_domain_solution(fp, t)
|
950 |
+
|
951 |
+
# shortcuts for the above function for specific methods
|
952 |
+
def invlaptalbot(ctx, *args, **kwargs):
|
953 |
+
kwargs['method'] = 'talbot'
|
954 |
+
return ctx.invertlaplace(*args, **kwargs)
|
955 |
+
|
956 |
+
def invlapstehfest(ctx, *args, **kwargs):
|
957 |
+
kwargs['method'] = 'stehfest'
|
958 |
+
return ctx.invertlaplace(*args, **kwargs)
|
959 |
+
|
960 |
+
def invlapdehoog(ctx, *args, **kwargs):
|
961 |
+
kwargs['method'] = 'dehoog'
|
962 |
+
return ctx.invertlaplace(*args, **kwargs)
|
963 |
+
|
964 |
+
def invlapcohen(ctx, *args, **kwargs):
|
965 |
+
kwargs['method'] = 'cohen'
|
966 |
+
return ctx.invertlaplace(*args, **kwargs)
|
967 |
+
|
968 |
+
|
969 |
+
# ****************************************
|
970 |
+
|
971 |
+
if __name__ == '__main__':
|
972 |
+
import doctest
|
973 |
+
doctest.testmod()
|
MLPY/Lib/site-packages/mpmath/calculus/odes.py
ADDED
@@ -0,0 +1,288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from bisect import bisect
|
2 |
+
from ..libmp.backend import xrange
|
3 |
+
|
4 |
+
class ODEMethods(object):
|
5 |
+
pass
|
6 |
+
|
7 |
+
def ode_taylor(ctx, derivs, x0, y0, tol_prec, n):
|
8 |
+
h = tol = ctx.ldexp(1, -tol_prec)
|
9 |
+
dim = len(y0)
|
10 |
+
xs = [x0]
|
11 |
+
ys = [y0]
|
12 |
+
x = x0
|
13 |
+
y = y0
|
14 |
+
orig = ctx.prec
|
15 |
+
try:
|
16 |
+
ctx.prec = orig*(1+n)
|
17 |
+
# Use n steps with Euler's method to get
|
18 |
+
# evaluation points for derivatives
|
19 |
+
for i in range(n):
|
20 |
+
fxy = derivs(x, y)
|
21 |
+
y = [y[i]+h*fxy[i] for i in xrange(len(y))]
|
22 |
+
x += h
|
23 |
+
xs.append(x)
|
24 |
+
ys.append(y)
|
25 |
+
# Compute derivatives
|
26 |
+
ser = [[] for d in range(dim)]
|
27 |
+
for j in range(n+1):
|
28 |
+
s = [0]*dim
|
29 |
+
b = (-1) ** (j & 1)
|
30 |
+
k = 1
|
31 |
+
for i in range(j+1):
|
32 |
+
for d in range(dim):
|
33 |
+
s[d] += b * ys[i][d]
|
34 |
+
b = (b * (j-k+1)) // (-k)
|
35 |
+
k += 1
|
36 |
+
scale = h**(-j) / ctx.fac(j)
|
37 |
+
for d in range(dim):
|
38 |
+
s[d] = s[d] * scale
|
39 |
+
ser[d].append(s[d])
|
40 |
+
finally:
|
41 |
+
ctx.prec = orig
|
42 |
+
# Estimate radius for which we can get full accuracy.
|
43 |
+
# XXX: do this right for zeros
|
44 |
+
radius = ctx.one
|
45 |
+
for ts in ser:
|
46 |
+
if ts[-1]:
|
47 |
+
radius = min(radius, ctx.nthroot(tol/abs(ts[-1]), n))
|
48 |
+
radius /= 2 # XXX
|
49 |
+
return ser, x0+radius
|
50 |
+
|
51 |
+
def odefun(ctx, F, x0, y0, tol=None, degree=None, method='taylor', verbose=False):
|
52 |
+
r"""
|
53 |
+
Returns a function `y(x) = [y_0(x), y_1(x), \ldots, y_n(x)]`
|
54 |
+
that is a numerical solution of the `n+1`-dimensional first-order
|
55 |
+
ordinary differential equation (ODE) system
|
56 |
+
|
57 |
+
.. math ::
|
58 |
+
|
59 |
+
y_0'(x) = F_0(x, [y_0(x), y_1(x), \ldots, y_n(x)])
|
60 |
+
|
61 |
+
y_1'(x) = F_1(x, [y_0(x), y_1(x), \ldots, y_n(x)])
|
62 |
+
|
63 |
+
\vdots
|
64 |
+
|
65 |
+
y_n'(x) = F_n(x, [y_0(x), y_1(x), \ldots, y_n(x)])
|
66 |
+
|
67 |
+
The derivatives are specified by the vector-valued function
|
68 |
+
*F* that evaluates
|
69 |
+
`[y_0', \ldots, y_n'] = F(x, [y_0, \ldots, y_n])`.
|
70 |
+
The initial point `x_0` is specified by the scalar argument *x0*,
|
71 |
+
and the initial value `y(x_0) = [y_0(x_0), \ldots, y_n(x_0)]` is
|
72 |
+
specified by the vector argument *y0*.
|
73 |
+
|
74 |
+
For convenience, if the system is one-dimensional, you may optionally
|
75 |
+
provide just a scalar value for *y0*. In this case, *F* should accept
|
76 |
+
a scalar *y* argument and return a scalar. The solution function
|
77 |
+
*y* will return scalar values instead of length-1 vectors.
|
78 |
+
|
79 |
+
Evaluation of the solution function `y(x)` is permitted
|
80 |
+
for any `x \ge x_0`.
|
81 |
+
|
82 |
+
A high-order ODE can be solved by transforming it into first-order
|
83 |
+
vector form. This transformation is described in standard texts
|
84 |
+
on ODEs. Examples will also be given below.
|
85 |
+
|
86 |
+
**Options, speed and accuracy**
|
87 |
+
|
88 |
+
By default, :func:`~mpmath.odefun` uses a high-order Taylor series
|
89 |
+
method. For reasonably well-behaved problems, the solution will
|
90 |
+
be fully accurate to within the working precision. Note that
|
91 |
+
*F* must be possible to evaluate to very high precision
|
92 |
+
for the generation of Taylor series to work.
|
93 |
+
|
94 |
+
To get a faster but less accurate solution, you can set a large
|
95 |
+
value for *tol* (which defaults roughly to *eps*). If you just
|
96 |
+
want to plot the solution or perform a basic simulation,
|
97 |
+
*tol = 0.01* is likely sufficient.
|
98 |
+
|
99 |
+
The *degree* argument controls the degree of the solver (with
|
100 |
+
*method='taylor'*, this is the degree of the Taylor series
|
101 |
+
expansion). A higher degree means that a longer step can be taken
|
102 |
+
before a new local solution must be generated from *F*,
|
103 |
+
meaning that fewer steps are required to get from `x_0` to a given
|
104 |
+
`x_1`. On the other hand, a higher degree also means that each
|
105 |
+
local solution becomes more expensive (i.e., more evaluations of
|
106 |
+
*F* are required per step, and at higher precision).
|
107 |
+
|
108 |
+
The optimal setting therefore involves a tradeoff. Generally,
|
109 |
+
decreasing the *degree* for Taylor series is likely to give faster
|
110 |
+
solution at low precision, while increasing is likely to be better
|
111 |
+
at higher precision.
|
112 |
+
|
113 |
+
The function
|
114 |
+
object returned by :func:`~mpmath.odefun` caches the solutions at all step
|
115 |
+
points and uses polynomial interpolation between step points.
|
116 |
+
Therefore, once `y(x_1)` has been evaluated for some `x_1`,
|
117 |
+
`y(x)` can be evaluated very quickly for any `x_0 \le x \le x_1`.
|
118 |
+
and continuing the evaluation up to `x_2 > x_1` is also fast.
|
119 |
+
|
120 |
+
**Examples of first-order ODEs**
|
121 |
+
|
122 |
+
We will solve the standard test problem `y'(x) = y(x), y(0) = 1`
|
123 |
+
which has explicit solution `y(x) = \exp(x)`::
|
124 |
+
|
125 |
+
>>> from mpmath import *
|
126 |
+
>>> mp.dps = 15; mp.pretty = True
|
127 |
+
>>> f = odefun(lambda x, y: y, 0, 1)
|
128 |
+
>>> for x in [0, 1, 2.5]:
|
129 |
+
... print((f(x), exp(x)))
|
130 |
+
...
|
131 |
+
(1.0, 1.0)
|
132 |
+
(2.71828182845905, 2.71828182845905)
|
133 |
+
(12.1824939607035, 12.1824939607035)
|
134 |
+
|
135 |
+
The solution with high precision::
|
136 |
+
|
137 |
+
>>> mp.dps = 50
|
138 |
+
>>> f = odefun(lambda x, y: y, 0, 1)
|
139 |
+
>>> f(1)
|
140 |
+
2.7182818284590452353602874713526624977572470937
|
141 |
+
>>> exp(1)
|
142 |
+
2.7182818284590452353602874713526624977572470937
|
143 |
+
|
144 |
+
Using the more general vectorized form, the test problem
|
145 |
+
can be input as (note that *f* returns a 1-element vector)::
|
146 |
+
|
147 |
+
>>> mp.dps = 15
|
148 |
+
>>> f = odefun(lambda x, y: [y[0]], 0, [1])
|
149 |
+
>>> f(1)
|
150 |
+
[2.71828182845905]
|
151 |
+
|
152 |
+
:func:`~mpmath.odefun` can solve nonlinear ODEs, which are generally
|
153 |
+
impossible (and at best difficult) to solve analytically. As
|
154 |
+
an example of a nonlinear ODE, we will solve `y'(x) = x \sin(y(x))`
|
155 |
+
for `y(0) = \pi/2`. An exact solution happens to be known
|
156 |
+
for this problem, and is given by
|
157 |
+
`y(x) = 2 \tan^{-1}\left(\exp\left(x^2/2\right)\right)`::
|
158 |
+
|
159 |
+
>>> f = odefun(lambda x, y: x*sin(y), 0, pi/2)
|
160 |
+
>>> for x in [2, 5, 10]:
|
161 |
+
... print((f(x), 2*atan(exp(mpf(x)**2/2))))
|
162 |
+
...
|
163 |
+
(2.87255666284091, 2.87255666284091)
|
164 |
+
(3.14158520028345, 3.14158520028345)
|
165 |
+
(3.14159265358979, 3.14159265358979)
|
166 |
+
|
167 |
+
If `F` is independent of `y`, an ODE can be solved using direct
|
168 |
+
integration. We can therefore obtain a reference solution with
|
169 |
+
:func:`~mpmath.quad`::
|
170 |
+
|
171 |
+
>>> f = lambda x: (1+x**2)/(1+x**3)
|
172 |
+
>>> g = odefun(lambda x, y: f(x), pi, 0)
|
173 |
+
>>> g(2*pi)
|
174 |
+
0.72128263801696
|
175 |
+
>>> quad(f, [pi, 2*pi])
|
176 |
+
0.72128263801696
|
177 |
+
|
178 |
+
**Examples of second-order ODEs**
|
179 |
+
|
180 |
+
We will solve the harmonic oscillator equation `y''(x) + y(x) = 0`.
|
181 |
+
To do this, we introduce the helper functions `y_0 = y, y_1 = y_0'`
|
182 |
+
whereby the original equation can be written as `y_1' + y_0' = 0`. Put
|
183 |
+
together, we get the first-order, two-dimensional vector ODE
|
184 |
+
|
185 |
+
.. math ::
|
186 |
+
|
187 |
+
\begin{cases}
|
188 |
+
y_0' = y_1 \\
|
189 |
+
y_1' = -y_0
|
190 |
+
\end{cases}
|
191 |
+
|
192 |
+
To get a well-defined IVP, we need two initial values. With
|
193 |
+
`y(0) = y_0(0) = 1` and `-y'(0) = y_1(0) = 0`, the problem will of
|
194 |
+
course be solved by `y(x) = y_0(x) = \cos(x)` and
|
195 |
+
`-y'(x) = y_1(x) = \sin(x)`. We check this::
|
196 |
+
|
197 |
+
>>> f = odefun(lambda x, y: [-y[1], y[0]], 0, [1, 0])
|
198 |
+
>>> for x in [0, 1, 2.5, 10]:
|
199 |
+
... nprint(f(x), 15)
|
200 |
+
... nprint([cos(x), sin(x)], 15)
|
201 |
+
... print("---")
|
202 |
+
...
|
203 |
+
[1.0, 0.0]
|
204 |
+
[1.0, 0.0]
|
205 |
+
---
|
206 |
+
[0.54030230586814, 0.841470984807897]
|
207 |
+
[0.54030230586814, 0.841470984807897]
|
208 |
+
---
|
209 |
+
[-0.801143615546934, 0.598472144103957]
|
210 |
+
[-0.801143615546934, 0.598472144103957]
|
211 |
+
---
|
212 |
+
[-0.839071529076452, -0.54402111088937]
|
213 |
+
[-0.839071529076452, -0.54402111088937]
|
214 |
+
---
|
215 |
+
|
216 |
+
Note that we get both the sine and the cosine solutions
|
217 |
+
simultaneously.
|
218 |
+
|
219 |
+
**TODO**
|
220 |
+
|
221 |
+
* Better automatic choice of degree and step size
|
222 |
+
* Make determination of Taylor series convergence radius
|
223 |
+
more robust
|
224 |
+
* Allow solution for `x < x_0`
|
225 |
+
* Allow solution for complex `x`
|
226 |
+
* Test for difficult (ill-conditioned) problems
|
227 |
+
* Implement Runge-Kutta and other algorithms
|
228 |
+
|
229 |
+
"""
|
230 |
+
if tol:
|
231 |
+
tol_prec = int(-ctx.log(tol, 2))+10
|
232 |
+
else:
|
233 |
+
tol_prec = ctx.prec+10
|
234 |
+
degree = degree or (3 + int(3*ctx.dps/2.))
|
235 |
+
workprec = ctx.prec + 40
|
236 |
+
try:
|
237 |
+
len(y0)
|
238 |
+
return_vector = True
|
239 |
+
except TypeError:
|
240 |
+
F_ = F
|
241 |
+
F = lambda x, y: [F_(x, y[0])]
|
242 |
+
y0 = [y0]
|
243 |
+
return_vector = False
|
244 |
+
ser, xb = ode_taylor(ctx, F, x0, y0, tol_prec, degree)
|
245 |
+
series_boundaries = [x0, xb]
|
246 |
+
series_data = [(ser, x0, xb)]
|
247 |
+
# We will be working with vectors of Taylor series
|
248 |
+
def mpolyval(ser, a):
|
249 |
+
return [ctx.polyval(s[::-1], a) for s in ser]
|
250 |
+
# Find nearest expansion point; compute if necessary
|
251 |
+
def get_series(x):
|
252 |
+
if x < x0:
|
253 |
+
raise ValueError
|
254 |
+
n = bisect(series_boundaries, x)
|
255 |
+
if n < len(series_boundaries):
|
256 |
+
return series_data[n-1]
|
257 |
+
while 1:
|
258 |
+
ser, xa, xb = series_data[-1]
|
259 |
+
if verbose:
|
260 |
+
print("Computing Taylor series for [%f, %f]" % (xa, xb))
|
261 |
+
y = mpolyval(ser, xb-xa)
|
262 |
+
xa = xb
|
263 |
+
ser, xb = ode_taylor(ctx, F, xb, y, tol_prec, degree)
|
264 |
+
series_boundaries.append(xb)
|
265 |
+
series_data.append((ser, xa, xb))
|
266 |
+
if x <= xb:
|
267 |
+
return series_data[-1]
|
268 |
+
# Evaluation function
|
269 |
+
def interpolant(x):
|
270 |
+
x = ctx.convert(x)
|
271 |
+
orig = ctx.prec
|
272 |
+
try:
|
273 |
+
ctx.prec = workprec
|
274 |
+
ser, xa, xb = get_series(x)
|
275 |
+
y = mpolyval(ser, x-xa)
|
276 |
+
finally:
|
277 |
+
ctx.prec = orig
|
278 |
+
if return_vector:
|
279 |
+
return [+yk for yk in y]
|
280 |
+
else:
|
281 |
+
return +y[0]
|
282 |
+
return interpolant
|
283 |
+
|
284 |
+
ODEMethods.odefun = odefun
|
285 |
+
|
286 |
+
if __name__ == "__main__":
|
287 |
+
import doctest
|
288 |
+
doctest.testmod()
|
MLPY/Lib/site-packages/mpmath/calculus/optimization.py
ADDED
@@ -0,0 +1,1102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import print_function
|
2 |
+
|
3 |
+
from copy import copy
|
4 |
+
|
5 |
+
from ..libmp.backend import xrange
|
6 |
+
|
7 |
+
class OptimizationMethods(object):
|
8 |
+
def __init__(ctx):
|
9 |
+
pass
|
10 |
+
|
11 |
+
##############
|
12 |
+
# 1D-SOLVERS #
|
13 |
+
##############
|
14 |
+
|
15 |
+
class Newton:
|
16 |
+
"""
|
17 |
+
1d-solver generating pairs of approximative root and error.
|
18 |
+
|
19 |
+
Needs starting points x0 close to the root.
|
20 |
+
|
21 |
+
Pro:
|
22 |
+
|
23 |
+
* converges fast
|
24 |
+
* sometimes more robust than secant with bad second starting point
|
25 |
+
|
26 |
+
Contra:
|
27 |
+
|
28 |
+
* converges slowly for multiple roots
|
29 |
+
* needs first derivative
|
30 |
+
* 2 function evaluations per iteration
|
31 |
+
"""
|
32 |
+
maxsteps = 20
|
33 |
+
|
34 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
35 |
+
self.ctx = ctx
|
36 |
+
if len(x0) == 1:
|
37 |
+
self.x0 = x0[0]
|
38 |
+
else:
|
39 |
+
raise ValueError('expected 1 starting point, got %i' % len(x0))
|
40 |
+
self.f = f
|
41 |
+
if not 'df' in kwargs:
|
42 |
+
def df(x):
|
43 |
+
return self.ctx.diff(f, x)
|
44 |
+
else:
|
45 |
+
df = kwargs['df']
|
46 |
+
self.df = df
|
47 |
+
|
48 |
+
def __iter__(self):
|
49 |
+
f = self.f
|
50 |
+
df = self.df
|
51 |
+
x0 = self.x0
|
52 |
+
while True:
|
53 |
+
x1 = x0 - f(x0) / df(x0)
|
54 |
+
error = abs(x1 - x0)
|
55 |
+
x0 = x1
|
56 |
+
yield (x1, error)
|
57 |
+
|
58 |
+
class Secant:
|
59 |
+
"""
|
60 |
+
1d-solver generating pairs of approximative root and error.
|
61 |
+
|
62 |
+
Needs starting points x0 and x1 close to the root.
|
63 |
+
x1 defaults to x0 + 0.25.
|
64 |
+
|
65 |
+
Pro:
|
66 |
+
|
67 |
+
* converges fast
|
68 |
+
|
69 |
+
Contra:
|
70 |
+
|
71 |
+
* converges slowly for multiple roots
|
72 |
+
"""
|
73 |
+
maxsteps = 30
|
74 |
+
|
75 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
76 |
+
self.ctx = ctx
|
77 |
+
if len(x0) == 1:
|
78 |
+
self.x0 = x0[0]
|
79 |
+
self.x1 = self.x0 + 0.25
|
80 |
+
elif len(x0) == 2:
|
81 |
+
self.x0 = x0[0]
|
82 |
+
self.x1 = x0[1]
|
83 |
+
else:
|
84 |
+
raise ValueError('expected 1 or 2 starting points, got %i' % len(x0))
|
85 |
+
self.f = f
|
86 |
+
|
87 |
+
def __iter__(self):
|
88 |
+
f = self.f
|
89 |
+
x0 = self.x0
|
90 |
+
x1 = self.x1
|
91 |
+
f0 = f(x0)
|
92 |
+
while True:
|
93 |
+
f1 = f(x1)
|
94 |
+
l = x1 - x0
|
95 |
+
if not l:
|
96 |
+
break
|
97 |
+
s = (f1 - f0) / l
|
98 |
+
if not s:
|
99 |
+
break
|
100 |
+
x0, x1 = x1, x1 - f1/s
|
101 |
+
f0 = f1
|
102 |
+
yield x1, abs(l)
|
103 |
+
|
104 |
+
class MNewton:
|
105 |
+
"""
|
106 |
+
1d-solver generating pairs of approximative root and error.
|
107 |
+
|
108 |
+
Needs starting point x0 close to the root.
|
109 |
+
Uses modified Newton's method that converges fast regardless of the
|
110 |
+
multiplicity of the root.
|
111 |
+
|
112 |
+
Pro:
|
113 |
+
|
114 |
+
* converges fast for multiple roots
|
115 |
+
|
116 |
+
Contra:
|
117 |
+
|
118 |
+
* needs first and second derivative of f
|
119 |
+
* 3 function evaluations per iteration
|
120 |
+
"""
|
121 |
+
maxsteps = 20
|
122 |
+
|
123 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
124 |
+
self.ctx = ctx
|
125 |
+
if not len(x0) == 1:
|
126 |
+
raise ValueError('expected 1 starting point, got %i' % len(x0))
|
127 |
+
self.x0 = x0[0]
|
128 |
+
self.f = f
|
129 |
+
if not 'df' in kwargs:
|
130 |
+
def df(x):
|
131 |
+
return self.ctx.diff(f, x)
|
132 |
+
else:
|
133 |
+
df = kwargs['df']
|
134 |
+
self.df = df
|
135 |
+
if not 'd2f' in kwargs:
|
136 |
+
def d2f(x):
|
137 |
+
return self.ctx.diff(df, x)
|
138 |
+
else:
|
139 |
+
d2f = kwargs['df']
|
140 |
+
self.d2f = d2f
|
141 |
+
|
142 |
+
def __iter__(self):
|
143 |
+
x = self.x0
|
144 |
+
f = self.f
|
145 |
+
df = self.df
|
146 |
+
d2f = self.d2f
|
147 |
+
while True:
|
148 |
+
prevx = x
|
149 |
+
fx = f(x)
|
150 |
+
if fx == 0:
|
151 |
+
break
|
152 |
+
dfx = df(x)
|
153 |
+
d2fx = d2f(x)
|
154 |
+
# x = x - F(x)/F'(x) with F(x) = f(x)/f'(x)
|
155 |
+
x -= fx / (dfx - fx * d2fx / dfx)
|
156 |
+
error = abs(x - prevx)
|
157 |
+
yield x, error
|
158 |
+
|
159 |
+
class Halley:
|
160 |
+
"""
|
161 |
+
1d-solver generating pairs of approximative root and error.
|
162 |
+
|
163 |
+
Needs a starting point x0 close to the root.
|
164 |
+
Uses Halley's method with cubic convergence rate.
|
165 |
+
|
166 |
+
Pro:
|
167 |
+
|
168 |
+
* converges even faster the Newton's method
|
169 |
+
* useful when computing with *many* digits
|
170 |
+
|
171 |
+
Contra:
|
172 |
+
|
173 |
+
* needs first and second derivative of f
|
174 |
+
* 3 function evaluations per iteration
|
175 |
+
* converges slowly for multiple roots
|
176 |
+
"""
|
177 |
+
|
178 |
+
maxsteps = 20
|
179 |
+
|
180 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
181 |
+
self.ctx = ctx
|
182 |
+
if not len(x0) == 1:
|
183 |
+
raise ValueError('expected 1 starting point, got %i' % len(x0))
|
184 |
+
self.x0 = x0[0]
|
185 |
+
self.f = f
|
186 |
+
if not 'df' in kwargs:
|
187 |
+
def df(x):
|
188 |
+
return self.ctx.diff(f, x)
|
189 |
+
else:
|
190 |
+
df = kwargs['df']
|
191 |
+
self.df = df
|
192 |
+
if not 'd2f' in kwargs:
|
193 |
+
def d2f(x):
|
194 |
+
return self.ctx.diff(df, x)
|
195 |
+
else:
|
196 |
+
d2f = kwargs['df']
|
197 |
+
self.d2f = d2f
|
198 |
+
|
199 |
+
def __iter__(self):
|
200 |
+
x = self.x0
|
201 |
+
f = self.f
|
202 |
+
df = self.df
|
203 |
+
d2f = self.d2f
|
204 |
+
while True:
|
205 |
+
prevx = x
|
206 |
+
fx = f(x)
|
207 |
+
dfx = df(x)
|
208 |
+
d2fx = d2f(x)
|
209 |
+
x -= 2*fx*dfx / (2*dfx**2 - fx*d2fx)
|
210 |
+
error = abs(x - prevx)
|
211 |
+
yield x, error
|
212 |
+
|
213 |
+
class Muller:
|
214 |
+
"""
|
215 |
+
1d-solver generating pairs of approximative root and error.
|
216 |
+
|
217 |
+
Needs starting points x0, x1 and x2 close to the root.
|
218 |
+
x1 defaults to x0 + 0.25; x2 to x1 + 0.25.
|
219 |
+
Uses Muller's method that converges towards complex roots.
|
220 |
+
|
221 |
+
Pro:
|
222 |
+
|
223 |
+
* converges fast (somewhat faster than secant)
|
224 |
+
* can find complex roots
|
225 |
+
|
226 |
+
Contra:
|
227 |
+
|
228 |
+
* converges slowly for multiple roots
|
229 |
+
* may have complex values for real starting points and real roots
|
230 |
+
|
231 |
+
http://en.wikipedia.org/wiki/Muller's_method
|
232 |
+
"""
|
233 |
+
maxsteps = 30
|
234 |
+
|
235 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
236 |
+
self.ctx = ctx
|
237 |
+
if len(x0) == 1:
|
238 |
+
self.x0 = x0[0]
|
239 |
+
self.x1 = self.x0 + 0.25
|
240 |
+
self.x2 = self.x1 + 0.25
|
241 |
+
elif len(x0) == 2:
|
242 |
+
self.x0 = x0[0]
|
243 |
+
self.x1 = x0[1]
|
244 |
+
self.x2 = self.x1 + 0.25
|
245 |
+
elif len(x0) == 3:
|
246 |
+
self.x0 = x0[0]
|
247 |
+
self.x1 = x0[1]
|
248 |
+
self.x2 = x0[2]
|
249 |
+
else:
|
250 |
+
raise ValueError('expected 1, 2 or 3 starting points, got %i'
|
251 |
+
% len(x0))
|
252 |
+
self.f = f
|
253 |
+
self.verbose = kwargs['verbose']
|
254 |
+
|
255 |
+
def __iter__(self):
|
256 |
+
f = self.f
|
257 |
+
x0 = self.x0
|
258 |
+
x1 = self.x1
|
259 |
+
x2 = self.x2
|
260 |
+
fx0 = f(x0)
|
261 |
+
fx1 = f(x1)
|
262 |
+
fx2 = f(x2)
|
263 |
+
while True:
|
264 |
+
# TODO: maybe refactoring with function for divided differences
|
265 |
+
# calculate divided differences
|
266 |
+
fx2x1 = (fx1 - fx2) / (x1 - x2)
|
267 |
+
fx2x0 = (fx0 - fx2) / (x0 - x2)
|
268 |
+
fx1x0 = (fx0 - fx1) / (x0 - x1)
|
269 |
+
w = fx2x1 + fx2x0 - fx1x0
|
270 |
+
fx2x1x0 = (fx1x0 - fx2x1) / (x0 - x2)
|
271 |
+
if w == 0 and fx2x1x0 == 0:
|
272 |
+
if self.verbose:
|
273 |
+
print('canceled with')
|
274 |
+
print('x0 =', x0, ', x1 =', x1, 'and x2 =', x2)
|
275 |
+
break
|
276 |
+
x0 = x1
|
277 |
+
fx0 = fx1
|
278 |
+
x1 = x2
|
279 |
+
fx1 = fx2
|
280 |
+
# denominator should be as large as possible => choose sign
|
281 |
+
r = self.ctx.sqrt(w**2 - 4*fx2*fx2x1x0)
|
282 |
+
if abs(w - r) > abs(w + r):
|
283 |
+
r = -r
|
284 |
+
x2 -= 2*fx2 / (w + r)
|
285 |
+
fx2 = f(x2)
|
286 |
+
error = abs(x2 - x1)
|
287 |
+
yield x2, error
|
288 |
+
|
289 |
+
# TODO: consider raising a ValueError when there's no sign change in a and b
|
290 |
+
class Bisection:
|
291 |
+
"""
|
292 |
+
1d-solver generating pairs of approximative root and error.
|
293 |
+
|
294 |
+
Uses bisection method to find a root of f in [a, b].
|
295 |
+
Might fail for multiple roots (needs sign change).
|
296 |
+
|
297 |
+
Pro:
|
298 |
+
|
299 |
+
* robust and reliable
|
300 |
+
|
301 |
+
Contra:
|
302 |
+
|
303 |
+
* converges slowly
|
304 |
+
* needs sign change
|
305 |
+
"""
|
306 |
+
maxsteps = 100
|
307 |
+
|
308 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
309 |
+
self.ctx = ctx
|
310 |
+
if len(x0) != 2:
|
311 |
+
raise ValueError('expected interval of 2 points, got %i' % len(x0))
|
312 |
+
self.f = f
|
313 |
+
self.a = x0[0]
|
314 |
+
self.b = x0[1]
|
315 |
+
|
316 |
+
def __iter__(self):
|
317 |
+
f = self.f
|
318 |
+
a = self.a
|
319 |
+
b = self.b
|
320 |
+
l = b - a
|
321 |
+
fb = f(b)
|
322 |
+
while True:
|
323 |
+
m = self.ctx.ldexp(a + b, -1)
|
324 |
+
fm = f(m)
|
325 |
+
sign = fm * fb
|
326 |
+
if sign < 0:
|
327 |
+
a = m
|
328 |
+
elif sign > 0:
|
329 |
+
b = m
|
330 |
+
fb = fm
|
331 |
+
else:
|
332 |
+
yield m, self.ctx.zero
|
333 |
+
l /= 2
|
334 |
+
yield (a + b)/2, abs(l)
|
335 |
+
|
336 |
+
def _getm(method):
|
337 |
+
"""
|
338 |
+
Return a function to calculate m for Illinois-like methods.
|
339 |
+
"""
|
340 |
+
if method == 'illinois':
|
341 |
+
def getm(fz, fb):
|
342 |
+
return 0.5
|
343 |
+
elif method == 'pegasus':
|
344 |
+
def getm(fz, fb):
|
345 |
+
return fb/(fb + fz)
|
346 |
+
elif method == 'anderson':
|
347 |
+
def getm(fz, fb):
|
348 |
+
m = 1 - fz/fb
|
349 |
+
if m > 0:
|
350 |
+
return m
|
351 |
+
else:
|
352 |
+
return 0.5
|
353 |
+
else:
|
354 |
+
raise ValueError("method '%s' not recognized" % method)
|
355 |
+
return getm
|
356 |
+
|
357 |
+
class Illinois:
|
358 |
+
"""
|
359 |
+
1d-solver generating pairs of approximative root and error.
|
360 |
+
|
361 |
+
Uses Illinois method or similar to find a root of f in [a, b].
|
362 |
+
Might fail for multiple roots (needs sign change).
|
363 |
+
Combines bisect with secant (improved regula falsi).
|
364 |
+
|
365 |
+
The only difference between the methods is the scaling factor m, which is
|
366 |
+
used to ensure convergence (you can choose one using the 'method' keyword):
|
367 |
+
|
368 |
+
Illinois method ('illinois'):
|
369 |
+
m = 0.5
|
370 |
+
|
371 |
+
Pegasus method ('pegasus'):
|
372 |
+
m = fb/(fb + fz)
|
373 |
+
|
374 |
+
Anderson-Bjoerk method ('anderson'):
|
375 |
+
m = 1 - fz/fb if positive else 0.5
|
376 |
+
|
377 |
+
Pro:
|
378 |
+
|
379 |
+
* converges very fast
|
380 |
+
|
381 |
+
Contra:
|
382 |
+
|
383 |
+
* has problems with multiple roots
|
384 |
+
* needs sign change
|
385 |
+
"""
|
386 |
+
maxsteps = 30
|
387 |
+
|
388 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
389 |
+
self.ctx = ctx
|
390 |
+
if len(x0) != 2:
|
391 |
+
raise ValueError('expected interval of 2 points, got %i' % len(x0))
|
392 |
+
self.a = x0[0]
|
393 |
+
self.b = x0[1]
|
394 |
+
self.f = f
|
395 |
+
self.tol = kwargs['tol']
|
396 |
+
self.verbose = kwargs['verbose']
|
397 |
+
self.method = kwargs.get('method', 'illinois')
|
398 |
+
self.getm = _getm(self.method)
|
399 |
+
if self.verbose:
|
400 |
+
print('using %s method' % self.method)
|
401 |
+
|
402 |
+
def __iter__(self):
|
403 |
+
method = self.method
|
404 |
+
f = self.f
|
405 |
+
a = self.a
|
406 |
+
b = self.b
|
407 |
+
fa = f(a)
|
408 |
+
fb = f(b)
|
409 |
+
m = None
|
410 |
+
while True:
|
411 |
+
l = b - a
|
412 |
+
if l == 0:
|
413 |
+
break
|
414 |
+
s = (fb - fa) / l
|
415 |
+
z = a - fa/s
|
416 |
+
fz = f(z)
|
417 |
+
if abs(fz) < self.tol:
|
418 |
+
# TODO: better condition (when f is very flat)
|
419 |
+
if self.verbose:
|
420 |
+
print('canceled with z =', z)
|
421 |
+
yield z, l
|
422 |
+
break
|
423 |
+
if fz * fb < 0: # root in [z, b]
|
424 |
+
a = b
|
425 |
+
fa = fb
|
426 |
+
b = z
|
427 |
+
fb = fz
|
428 |
+
else: # root in [a, z]
|
429 |
+
m = self.getm(fz, fb)
|
430 |
+
b = z
|
431 |
+
fb = fz
|
432 |
+
fa = m*fa # scale down to ensure convergence
|
433 |
+
if self.verbose and m and not method == 'illinois':
|
434 |
+
print('m:', m)
|
435 |
+
yield (a + b)/2, abs(l)
|
436 |
+
|
437 |
+
def Pegasus(*args, **kwargs):
|
438 |
+
"""
|
439 |
+
1d-solver generating pairs of approximative root and error.
|
440 |
+
|
441 |
+
Uses Pegasus method to find a root of f in [a, b].
|
442 |
+
Wrapper for illinois to use method='pegasus'.
|
443 |
+
"""
|
444 |
+
kwargs['method'] = 'pegasus'
|
445 |
+
return Illinois(*args, **kwargs)
|
446 |
+
|
447 |
+
def Anderson(*args, **kwargs):
|
448 |
+
"""
|
449 |
+
1d-solver generating pairs of approximative root and error.
|
450 |
+
|
451 |
+
Uses Anderson-Bjoerk method to find a root of f in [a, b].
|
452 |
+
Wrapper for illinois to use method='pegasus'.
|
453 |
+
"""
|
454 |
+
kwargs['method'] = 'anderson'
|
455 |
+
return Illinois(*args, **kwargs)
|
456 |
+
|
457 |
+
# TODO: check whether it's possible to combine it with Illinois stuff
|
458 |
+
class Ridder:
|
459 |
+
"""
|
460 |
+
1d-solver generating pairs of approximative root and error.
|
461 |
+
|
462 |
+
Ridders' method to find a root of f in [a, b].
|
463 |
+
Is told to perform as well as Brent's method while being simpler.
|
464 |
+
|
465 |
+
Pro:
|
466 |
+
|
467 |
+
* very fast
|
468 |
+
* simpler than Brent's method
|
469 |
+
|
470 |
+
Contra:
|
471 |
+
|
472 |
+
* two function evaluations per step
|
473 |
+
* has problems with multiple roots
|
474 |
+
* needs sign change
|
475 |
+
|
476 |
+
http://en.wikipedia.org/wiki/Ridders'_method
|
477 |
+
"""
|
478 |
+
maxsteps = 30
|
479 |
+
|
480 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
481 |
+
self.ctx = ctx
|
482 |
+
self.f = f
|
483 |
+
if len(x0) != 2:
|
484 |
+
raise ValueError('expected interval of 2 points, got %i' % len(x0))
|
485 |
+
self.x1 = x0[0]
|
486 |
+
self.x2 = x0[1]
|
487 |
+
self.verbose = kwargs['verbose']
|
488 |
+
self.tol = kwargs['tol']
|
489 |
+
|
490 |
+
def __iter__(self):
|
491 |
+
ctx = self.ctx
|
492 |
+
f = self.f
|
493 |
+
x1 = self.x1
|
494 |
+
fx1 = f(x1)
|
495 |
+
x2 = self.x2
|
496 |
+
fx2 = f(x2)
|
497 |
+
while True:
|
498 |
+
x3 = 0.5*(x1 + x2)
|
499 |
+
fx3 = f(x3)
|
500 |
+
x4 = x3 + (x3 - x1) * ctx.sign(fx1 - fx2) * fx3 / ctx.sqrt(fx3**2 - fx1*fx2)
|
501 |
+
fx4 = f(x4)
|
502 |
+
if abs(fx4) < self.tol:
|
503 |
+
# TODO: better condition (when f is very flat)
|
504 |
+
if self.verbose:
|
505 |
+
print('canceled with f(x4) =', fx4)
|
506 |
+
yield x4, abs(x1 - x2)
|
507 |
+
break
|
508 |
+
if fx4 * fx2 < 0: # root in [x4, x2]
|
509 |
+
x1 = x4
|
510 |
+
fx1 = fx4
|
511 |
+
else: # root in [x1, x4]
|
512 |
+
x2 = x4
|
513 |
+
fx2 = fx4
|
514 |
+
error = abs(x1 - x2)
|
515 |
+
yield (x1 + x2)/2, error
|
516 |
+
|
517 |
+
class ANewton:
|
518 |
+
"""
|
519 |
+
EXPERIMENTAL 1d-solver generating pairs of approximative root and error.
|
520 |
+
|
521 |
+
Uses Newton's method modified to use Steffensens method when convergence is
|
522 |
+
slow. (I.e. for multiple roots.)
|
523 |
+
"""
|
524 |
+
maxsteps = 20
|
525 |
+
|
526 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
527 |
+
self.ctx = ctx
|
528 |
+
if not len(x0) == 1:
|
529 |
+
raise ValueError('expected 1 starting point, got %i' % len(x0))
|
530 |
+
self.x0 = x0[0]
|
531 |
+
self.f = f
|
532 |
+
if not 'df' in kwargs:
|
533 |
+
def df(x):
|
534 |
+
return self.ctx.diff(f, x)
|
535 |
+
else:
|
536 |
+
df = kwargs['df']
|
537 |
+
self.df = df
|
538 |
+
def phi(x):
|
539 |
+
return x - f(x) / df(x)
|
540 |
+
self.phi = phi
|
541 |
+
self.verbose = kwargs['verbose']
|
542 |
+
|
543 |
+
def __iter__(self):
|
544 |
+
x0 = self.x0
|
545 |
+
f = self.f
|
546 |
+
df = self.df
|
547 |
+
phi = self.phi
|
548 |
+
error = 0
|
549 |
+
counter = 0
|
550 |
+
while True:
|
551 |
+
prevx = x0
|
552 |
+
try:
|
553 |
+
x0 = phi(x0)
|
554 |
+
except ZeroDivisionError:
|
555 |
+
if self.verbose:
|
556 |
+
print('ZeroDivisionError: canceled with x =', x0)
|
557 |
+
break
|
558 |
+
preverror = error
|
559 |
+
error = abs(prevx - x0)
|
560 |
+
# TODO: decide not to use convergence acceleration
|
561 |
+
if error and abs(error - preverror) / error < 1:
|
562 |
+
if self.verbose:
|
563 |
+
print('converging slowly')
|
564 |
+
counter += 1
|
565 |
+
if counter >= 3:
|
566 |
+
# accelerate convergence
|
567 |
+
phi = steffensen(phi)
|
568 |
+
counter = 0
|
569 |
+
if self.verbose:
|
570 |
+
print('accelerating convergence')
|
571 |
+
yield x0, error
|
572 |
+
|
573 |
+
# TODO: add Brent
|
574 |
+
|
575 |
+
############################
|
576 |
+
# MULTIDIMENSIONAL SOLVERS #
|
577 |
+
############################
|
578 |
+
|
579 |
+
def jacobian(ctx, f, x):
|
580 |
+
"""
|
581 |
+
Calculate the Jacobian matrix of a function at the point x0.
|
582 |
+
|
583 |
+
This is the first derivative of a vectorial function:
|
584 |
+
|
585 |
+
f : R^m -> R^n with m >= n
|
586 |
+
"""
|
587 |
+
x = ctx.matrix(x)
|
588 |
+
h = ctx.sqrt(ctx.eps)
|
589 |
+
fx = ctx.matrix(f(*x))
|
590 |
+
m = len(fx)
|
591 |
+
n = len(x)
|
592 |
+
J = ctx.matrix(m, n)
|
593 |
+
for j in xrange(n):
|
594 |
+
xj = x.copy()
|
595 |
+
xj[j] += h
|
596 |
+
Jj = (ctx.matrix(f(*xj)) - fx) / h
|
597 |
+
for i in xrange(m):
|
598 |
+
J[i,j] = Jj[i]
|
599 |
+
return J
|
600 |
+
|
601 |
+
# TODO: test with user-specified jacobian matrix
|
602 |
+
class MDNewton:
|
603 |
+
"""
|
604 |
+
Find the root of a vector function numerically using Newton's method.
|
605 |
+
|
606 |
+
f is a vector function representing a nonlinear equation system.
|
607 |
+
|
608 |
+
x0 is the starting point close to the root.
|
609 |
+
|
610 |
+
J is a function returning the Jacobian matrix for a point.
|
611 |
+
|
612 |
+
Supports overdetermined systems.
|
613 |
+
|
614 |
+
Use the 'norm' keyword to specify which norm to use. Defaults to max-norm.
|
615 |
+
The function to calculate the Jacobian matrix can be given using the
|
616 |
+
keyword 'J'. Otherwise it will be calculated numerically.
|
617 |
+
|
618 |
+
Please note that this method converges only locally. Especially for high-
|
619 |
+
dimensional systems it is not trivial to find a good starting point being
|
620 |
+
close enough to the root.
|
621 |
+
|
622 |
+
It is recommended to use a faster, low-precision solver from SciPy [1] or
|
623 |
+
OpenOpt [2] to get an initial guess. Afterwards you can use this method for
|
624 |
+
root-polishing to any precision.
|
625 |
+
|
626 |
+
[1] http://scipy.org
|
627 |
+
|
628 |
+
[2] http://openopt.org/Welcome
|
629 |
+
"""
|
630 |
+
maxsteps = 10
|
631 |
+
|
632 |
+
def __init__(self, ctx, f, x0, **kwargs):
|
633 |
+
self.ctx = ctx
|
634 |
+
self.f = f
|
635 |
+
if isinstance(x0, (tuple, list)):
|
636 |
+
x0 = ctx.matrix(x0)
|
637 |
+
assert x0.cols == 1, 'need a vector'
|
638 |
+
self.x0 = x0
|
639 |
+
if 'J' in kwargs:
|
640 |
+
self.J = kwargs['J']
|
641 |
+
else:
|
642 |
+
def J(*x):
|
643 |
+
return ctx.jacobian(f, x)
|
644 |
+
self.J = J
|
645 |
+
self.norm = kwargs['norm']
|
646 |
+
self.verbose = kwargs['verbose']
|
647 |
+
|
648 |
+
def __iter__(self):
|
649 |
+
f = self.f
|
650 |
+
x0 = self.x0
|
651 |
+
norm = self.norm
|
652 |
+
J = self.J
|
653 |
+
fx = self.ctx.matrix(f(*x0))
|
654 |
+
fxnorm = norm(fx)
|
655 |
+
cancel = False
|
656 |
+
while not cancel:
|
657 |
+
# get direction of descent
|
658 |
+
fxn = -fx
|
659 |
+
Jx = J(*x0)
|
660 |
+
s = self.ctx.lu_solve(Jx, fxn)
|
661 |
+
if self.verbose:
|
662 |
+
print('Jx:')
|
663 |
+
print(Jx)
|
664 |
+
print('s:', s)
|
665 |
+
# damping step size TODO: better strategy (hard task)
|
666 |
+
l = self.ctx.one
|
667 |
+
x1 = x0 + s
|
668 |
+
while True:
|
669 |
+
if x1 == x0:
|
670 |
+
if self.verbose:
|
671 |
+
print("canceled, won't get more excact")
|
672 |
+
cancel = True
|
673 |
+
break
|
674 |
+
fx = self.ctx.matrix(f(*x1))
|
675 |
+
newnorm = norm(fx)
|
676 |
+
if newnorm < fxnorm:
|
677 |
+
# new x accepted
|
678 |
+
fxnorm = newnorm
|
679 |
+
x0 = x1
|
680 |
+
break
|
681 |
+
l /= 2
|
682 |
+
x1 = x0 + l*s
|
683 |
+
yield (x0, fxnorm)
|
684 |
+
|
685 |
+
#############
|
686 |
+
# UTILITIES #
|
687 |
+
#############
|
688 |
+
|
689 |
+
str2solver = {'newton':Newton, 'secant':Secant, 'mnewton':MNewton,
|
690 |
+
'halley':Halley, 'muller':Muller, 'bisect':Bisection,
|
691 |
+
'illinois':Illinois, 'pegasus':Pegasus, 'anderson':Anderson,
|
692 |
+
'ridder':Ridder, 'anewton':ANewton, 'mdnewton':MDNewton}
|
693 |
+
|
694 |
+
def findroot(ctx, f, x0, solver='secant', tol=None, verbose=False, verify=True, **kwargs):
|
695 |
+
r"""
|
696 |
+
Find an approximate solution to `f(x) = 0`, using *x0* as starting point or
|
697 |
+
interval for *x*.
|
698 |
+
|
699 |
+
Multidimensional overdetermined systems are supported.
|
700 |
+
You can specify them using a function or a list of functions.
|
701 |
+
|
702 |
+
Mathematically speaking, this function returns `x` such that
|
703 |
+
`|f(x)|^2 \leq \mathrm{tol}` is true within the current working precision.
|
704 |
+
If the computed value does not meet this criterion, an exception is raised.
|
705 |
+
This exception can be disabled with *verify=False*.
|
706 |
+
|
707 |
+
For interval arithmetic (``iv.findroot()``), please note that
|
708 |
+
the returned interval ``x`` is not guaranteed to contain `f(x)=0`!
|
709 |
+
It is only some `x` for which `|f(x)|^2 \leq \mathrm{tol}` certainly holds
|
710 |
+
regardless of numerical error. This may be improved in the future.
|
711 |
+
|
712 |
+
**Arguments**
|
713 |
+
|
714 |
+
*f*
|
715 |
+
one dimensional function
|
716 |
+
*x0*
|
717 |
+
starting point, several starting points or interval (depends on solver)
|
718 |
+
*tol*
|
719 |
+
the returned solution has an error smaller than this
|
720 |
+
*verbose*
|
721 |
+
print additional information for each iteration if true
|
722 |
+
*verify*
|
723 |
+
verify the solution and raise a ValueError if `|f(x)|^2 > \mathrm{tol}`
|
724 |
+
*solver*
|
725 |
+
a generator for *f* and *x0* returning approximative solution and error
|
726 |
+
*maxsteps*
|
727 |
+
after how many steps the solver will cancel
|
728 |
+
*df*
|
729 |
+
first derivative of *f* (used by some solvers)
|
730 |
+
*d2f*
|
731 |
+
second derivative of *f* (used by some solvers)
|
732 |
+
*multidimensional*
|
733 |
+
force multidimensional solving
|
734 |
+
*J*
|
735 |
+
Jacobian matrix of *f* (used by multidimensional solvers)
|
736 |
+
*norm*
|
737 |
+
used vector norm (used by multidimensional solvers)
|
738 |
+
|
739 |
+
solver has to be callable with ``(f, x0, **kwargs)`` and return an generator
|
740 |
+
yielding pairs of approximative solution and estimated error (which is
|
741 |
+
expected to be positive).
|
742 |
+
You can use the following string aliases:
|
743 |
+
'secant', 'mnewton', 'halley', 'muller', 'illinois', 'pegasus', 'anderson',
|
744 |
+
'ridder', 'anewton', 'bisect'
|
745 |
+
|
746 |
+
See mpmath.calculus.optimization for their documentation.
|
747 |
+
|
748 |
+
**Examples**
|
749 |
+
|
750 |
+
The function :func:`~mpmath.findroot` locates a root of a given function using the
|
751 |
+
secant method by default. A simple example use of the secant method is to
|
752 |
+
compute `\pi` as the root of `\sin x` closest to `x_0 = 3`::
|
753 |
+
|
754 |
+
>>> from mpmath import *
|
755 |
+
>>> mp.dps = 30; mp.pretty = True
|
756 |
+
>>> findroot(sin, 3)
|
757 |
+
3.14159265358979323846264338328
|
758 |
+
|
759 |
+
The secant method can be used to find complex roots of analytic functions,
|
760 |
+
although it must in that case generally be given a nonreal starting value
|
761 |
+
(or else it will never leave the real line)::
|
762 |
+
|
763 |
+
>>> mp.dps = 15
|
764 |
+
>>> findroot(lambda x: x**3 + 2*x + 1, j)
|
765 |
+
(0.226698825758202 + 1.46771150871022j)
|
766 |
+
|
767 |
+
A nice application is to compute nontrivial roots of the Riemann zeta
|
768 |
+
function with many digits (good initial values are needed for convergence)::
|
769 |
+
|
770 |
+
>>> mp.dps = 30
|
771 |
+
>>> findroot(zeta, 0.5+14j)
|
772 |
+
(0.5 + 14.1347251417346937904572519836j)
|
773 |
+
|
774 |
+
The secant method can also be used as an optimization algorithm, by passing
|
775 |
+
it a derivative of a function. The following example locates the positive
|
776 |
+
minimum of the gamma function::
|
777 |
+
|
778 |
+
>>> mp.dps = 20
|
779 |
+
>>> findroot(lambda x: diff(gamma, x), 1)
|
780 |
+
1.4616321449683623413
|
781 |
+
|
782 |
+
Finally, a useful application is to compute inverse functions, such as the
|
783 |
+
Lambert W function which is the inverse of `w e^w`, given the first
|
784 |
+
term of the solution's asymptotic expansion as the initial value. In basic
|
785 |
+
cases, this gives identical results to mpmath's built-in ``lambertw``
|
786 |
+
function::
|
787 |
+
|
788 |
+
>>> def lambert(x):
|
789 |
+
... return findroot(lambda w: w*exp(w) - x, log(1+x))
|
790 |
+
...
|
791 |
+
>>> mp.dps = 15
|
792 |
+
>>> lambert(1); lambertw(1)
|
793 |
+
0.567143290409784
|
794 |
+
0.567143290409784
|
795 |
+
>>> lambert(1000); lambert(1000)
|
796 |
+
5.2496028524016
|
797 |
+
5.2496028524016
|
798 |
+
|
799 |
+
Multidimensional functions are also supported::
|
800 |
+
|
801 |
+
>>> f = [lambda x1, x2: x1**2 + x2,
|
802 |
+
... lambda x1, x2: 5*x1**2 - 3*x1 + 2*x2 - 3]
|
803 |
+
>>> findroot(f, (0, 0))
|
804 |
+
[-0.618033988749895]
|
805 |
+
[-0.381966011250105]
|
806 |
+
>>> findroot(f, (10, 10))
|
807 |
+
[ 1.61803398874989]
|
808 |
+
[-2.61803398874989]
|
809 |
+
|
810 |
+
You can verify this by solving the system manually.
|
811 |
+
|
812 |
+
Please note that the following (more general) syntax also works::
|
813 |
+
|
814 |
+
>>> def f(x1, x2):
|
815 |
+
... return x1**2 + x2, 5*x1**2 - 3*x1 + 2*x2 - 3
|
816 |
+
...
|
817 |
+
>>> findroot(f, (0, 0))
|
818 |
+
[-0.618033988749895]
|
819 |
+
[-0.381966011250105]
|
820 |
+
|
821 |
+
|
822 |
+
**Multiple roots**
|
823 |
+
|
824 |
+
For multiple roots all methods of the Newtonian family (including secant)
|
825 |
+
converge slowly. Consider this example::
|
826 |
+
|
827 |
+
>>> f = lambda x: (x - 1)**99
|
828 |
+
>>> findroot(f, 0.9, verify=False)
|
829 |
+
0.918073542444929
|
830 |
+
|
831 |
+
Even for a very close starting point the secant method converges very
|
832 |
+
slowly. Use ``verbose=True`` to illustrate this.
|
833 |
+
|
834 |
+
It is possible to modify Newton's method to make it converge regardless of
|
835 |
+
the root's multiplicity::
|
836 |
+
|
837 |
+
>>> findroot(f, -10, solver='mnewton')
|
838 |
+
1.0
|
839 |
+
|
840 |
+
This variant uses the first and second derivative of the function, which is
|
841 |
+
not very efficient.
|
842 |
+
|
843 |
+
Alternatively you can use an experimental Newtonian solver that keeps track
|
844 |
+
of the speed of convergence and accelerates it using Steffensen's method if
|
845 |
+
necessary::
|
846 |
+
|
847 |
+
>>> findroot(f, -10, solver='anewton', verbose=True)
|
848 |
+
x: -9.88888888888888888889
|
849 |
+
error: 0.111111111111111111111
|
850 |
+
converging slowly
|
851 |
+
x: -9.77890011223344556678
|
852 |
+
error: 0.10998877665544332211
|
853 |
+
converging slowly
|
854 |
+
x: -9.67002233332199662166
|
855 |
+
error: 0.108877778911448945119
|
856 |
+
converging slowly
|
857 |
+
accelerating convergence
|
858 |
+
x: -9.5622443299551077669
|
859 |
+
error: 0.107778003366888854764
|
860 |
+
converging slowly
|
861 |
+
x: 0.99999999999999999214
|
862 |
+
error: 10.562244329955107759
|
863 |
+
x: 1.0
|
864 |
+
error: 7.8598304758094664213e-18
|
865 |
+
ZeroDivisionError: canceled with x = 1.0
|
866 |
+
1.0
|
867 |
+
|
868 |
+
**Complex roots**
|
869 |
+
|
870 |
+
For complex roots it's recommended to use Muller's method as it converges
|
871 |
+
even for real starting points very fast::
|
872 |
+
|
873 |
+
>>> findroot(lambda x: x**4 + x + 1, (0, 1, 2), solver='muller')
|
874 |
+
(0.727136084491197 + 0.934099289460529j)
|
875 |
+
|
876 |
+
|
877 |
+
**Intersection methods**
|
878 |
+
|
879 |
+
When you need to find a root in a known interval, it's highly recommended to
|
880 |
+
use an intersection-based solver like ``'anderson'`` or ``'ridder'``.
|
881 |
+
Usually they converge faster and more reliable. They have however problems
|
882 |
+
with multiple roots and usually need a sign change to find a root::
|
883 |
+
|
884 |
+
>>> findroot(lambda x: x**3, (-1, 1), solver='anderson')
|
885 |
+
0.0
|
886 |
+
|
887 |
+
Be careful with symmetric functions::
|
888 |
+
|
889 |
+
>>> findroot(lambda x: x**2, (-1, 1), solver='anderson') #doctest:+ELLIPSIS
|
890 |
+
Traceback (most recent call last):
|
891 |
+
...
|
892 |
+
ZeroDivisionError
|
893 |
+
|
894 |
+
It fails even for better starting points, because there is no sign change::
|
895 |
+
|
896 |
+
>>> findroot(lambda x: x**2, (-1, .5), solver='anderson')
|
897 |
+
Traceback (most recent call last):
|
898 |
+
...
|
899 |
+
ValueError: Could not find root within given tolerance. (1.0 > 2.16840434497100886801e-19)
|
900 |
+
Try another starting point or tweak arguments.
|
901 |
+
|
902 |
+
"""
|
903 |
+
prec = ctx.prec
|
904 |
+
try:
|
905 |
+
ctx.prec += 20
|
906 |
+
|
907 |
+
# initialize arguments
|
908 |
+
if tol is None:
|
909 |
+
tol = ctx.eps * 2**10
|
910 |
+
|
911 |
+
kwargs['verbose'] = kwargs.get('verbose', verbose)
|
912 |
+
|
913 |
+
if 'd1f' in kwargs:
|
914 |
+
kwargs['df'] = kwargs['d1f']
|
915 |
+
|
916 |
+
kwargs['tol'] = tol
|
917 |
+
if isinstance(x0, (list, tuple)):
|
918 |
+
x0 = [ctx.convert(x) for x in x0]
|
919 |
+
else:
|
920 |
+
x0 = [ctx.convert(x0)]
|
921 |
+
|
922 |
+
if isinstance(solver, str):
|
923 |
+
try:
|
924 |
+
solver = str2solver[solver]
|
925 |
+
except KeyError:
|
926 |
+
raise ValueError('could not recognize solver')
|
927 |
+
|
928 |
+
# accept list of functions
|
929 |
+
if isinstance(f, (list, tuple)):
|
930 |
+
f2 = copy(f)
|
931 |
+
def tmp(*args):
|
932 |
+
return [fn(*args) for fn in f2]
|
933 |
+
f = tmp
|
934 |
+
|
935 |
+
# detect multidimensional functions
|
936 |
+
try:
|
937 |
+
fx = f(*x0)
|
938 |
+
multidimensional = isinstance(fx, (list, tuple, ctx.matrix))
|
939 |
+
except TypeError:
|
940 |
+
fx = f(x0[0])
|
941 |
+
multidimensional = False
|
942 |
+
if 'multidimensional' in kwargs:
|
943 |
+
multidimensional = kwargs['multidimensional']
|
944 |
+
if multidimensional:
|
945 |
+
# only one multidimensional solver available at the moment
|
946 |
+
solver = MDNewton
|
947 |
+
if not 'norm' in kwargs:
|
948 |
+
norm = lambda x: ctx.norm(x, 'inf')
|
949 |
+
kwargs['norm'] = norm
|
950 |
+
else:
|
951 |
+
norm = kwargs['norm']
|
952 |
+
else:
|
953 |
+
norm = abs
|
954 |
+
|
955 |
+
# happily return starting point if it's a root
|
956 |
+
if norm(fx) == 0:
|
957 |
+
if multidimensional:
|
958 |
+
return ctx.matrix(x0)
|
959 |
+
else:
|
960 |
+
return x0[0]
|
961 |
+
|
962 |
+
# use solver
|
963 |
+
iterations = solver(ctx, f, x0, **kwargs)
|
964 |
+
if 'maxsteps' in kwargs:
|
965 |
+
maxsteps = kwargs['maxsteps']
|
966 |
+
else:
|
967 |
+
maxsteps = iterations.maxsteps
|
968 |
+
i = 0
|
969 |
+
for x, error in iterations:
|
970 |
+
if verbose:
|
971 |
+
print('x: ', x)
|
972 |
+
print('error:', error)
|
973 |
+
i += 1
|
974 |
+
if error < tol * max(1, norm(x)) or i >= maxsteps:
|
975 |
+
break
|
976 |
+
else:
|
977 |
+
if not i:
|
978 |
+
raise ValueError('Could not find root using the given solver.\n'
|
979 |
+
'Try another starting point or tweak arguments.')
|
980 |
+
if not isinstance(x, (list, tuple, ctx.matrix)):
|
981 |
+
xl = [x]
|
982 |
+
else:
|
983 |
+
xl = x
|
984 |
+
if verify and norm(f(*xl))**2 > tol: # TODO: better condition?
|
985 |
+
raise ValueError('Could not find root within given tolerance. '
|
986 |
+
'(%s > %s)\n'
|
987 |
+
'Try another starting point or tweak arguments.'
|
988 |
+
% (norm(f(*xl))**2, tol))
|
989 |
+
return x
|
990 |
+
finally:
|
991 |
+
ctx.prec = prec
|
992 |
+
|
993 |
+
|
994 |
+
def multiplicity(ctx, f, root, tol=None, maxsteps=10, **kwargs):
|
995 |
+
"""
|
996 |
+
Return the multiplicity of a given root of f.
|
997 |
+
|
998 |
+
Internally, numerical derivatives are used. This might be inefficient for
|
999 |
+
higher order derviatives. Due to this, ``multiplicity`` cancels after
|
1000 |
+
evaluating 10 derivatives by default. You can be specify the n-th derivative
|
1001 |
+
using the dnf keyword.
|
1002 |
+
|
1003 |
+
>>> from mpmath import *
|
1004 |
+
>>> multiplicity(lambda x: sin(x) - 1, pi/2)
|
1005 |
+
2
|
1006 |
+
|
1007 |
+
"""
|
1008 |
+
if tol is None:
|
1009 |
+
tol = ctx.eps ** 0.8
|
1010 |
+
kwargs['d0f'] = f
|
1011 |
+
for i in xrange(maxsteps):
|
1012 |
+
dfstr = 'd' + str(i) + 'f'
|
1013 |
+
if dfstr in kwargs:
|
1014 |
+
df = kwargs[dfstr]
|
1015 |
+
else:
|
1016 |
+
df = lambda x: ctx.diff(f, x, i)
|
1017 |
+
if not abs(df(root)) < tol:
|
1018 |
+
break
|
1019 |
+
return i
|
1020 |
+
|
1021 |
+
def steffensen(f):
|
1022 |
+
"""
|
1023 |
+
linear convergent function -> quadratic convergent function
|
1024 |
+
|
1025 |
+
Steffensen's method for quadratic convergence of a linear converging
|
1026 |
+
sequence.
|
1027 |
+
Don not use it for higher rates of convergence.
|
1028 |
+
It may even work for divergent sequences.
|
1029 |
+
|
1030 |
+
Definition:
|
1031 |
+
F(x) = (x*f(f(x)) - f(x)**2) / (f(f(x)) - 2*f(x) + x)
|
1032 |
+
|
1033 |
+
Example
|
1034 |
+
.......
|
1035 |
+
|
1036 |
+
You can use Steffensen's method to accelerate a fixpoint iteration of linear
|
1037 |
+
(or less) convergence.
|
1038 |
+
|
1039 |
+
x* is a fixpoint of the iteration x_{k+1} = phi(x_k) if x* = phi(x*). For
|
1040 |
+
phi(x) = x**2 there are two fixpoints: 0 and 1.
|
1041 |
+
|
1042 |
+
Let's try Steffensen's method:
|
1043 |
+
|
1044 |
+
>>> f = lambda x: x**2
|
1045 |
+
>>> from mpmath.calculus.optimization import steffensen
|
1046 |
+
>>> F = steffensen(f)
|
1047 |
+
>>> for x in [0.5, 0.9, 2.0]:
|
1048 |
+
... fx = Fx = x
|
1049 |
+
... for i in xrange(9):
|
1050 |
+
... try:
|
1051 |
+
... fx = f(fx)
|
1052 |
+
... except OverflowError:
|
1053 |
+
... pass
|
1054 |
+
... try:
|
1055 |
+
... Fx = F(Fx)
|
1056 |
+
... except ZeroDivisionError:
|
1057 |
+
... pass
|
1058 |
+
... print('%20g %20g' % (fx, Fx))
|
1059 |
+
0.25 -0.5
|
1060 |
+
0.0625 0.1
|
1061 |
+
0.00390625 -0.0011236
|
1062 |
+
1.52588e-05 1.41691e-09
|
1063 |
+
2.32831e-10 -2.84465e-27
|
1064 |
+
5.42101e-20 2.30189e-80
|
1065 |
+
2.93874e-39 -1.2197e-239
|
1066 |
+
8.63617e-78 0
|
1067 |
+
7.45834e-155 0
|
1068 |
+
0.81 1.02676
|
1069 |
+
0.6561 1.00134
|
1070 |
+
0.430467 1
|
1071 |
+
0.185302 1
|
1072 |
+
0.0343368 1
|
1073 |
+
0.00117902 1
|
1074 |
+
1.39008e-06 1
|
1075 |
+
1.93233e-12 1
|
1076 |
+
3.73392e-24 1
|
1077 |
+
4 1.6
|
1078 |
+
16 1.2962
|
1079 |
+
256 1.10194
|
1080 |
+
65536 1.01659
|
1081 |
+
4.29497e+09 1.00053
|
1082 |
+
1.84467e+19 1
|
1083 |
+
3.40282e+38 1
|
1084 |
+
1.15792e+77 1
|
1085 |
+
1.34078e+154 1
|
1086 |
+
|
1087 |
+
Unmodified, the iteration converges only towards 0. Modified it converges
|
1088 |
+
not only much faster, it converges even to the repelling fixpoint 1.
|
1089 |
+
"""
|
1090 |
+
def F(x):
|
1091 |
+
fx = f(x)
|
1092 |
+
ffx = f(fx)
|
1093 |
+
return (x*ffx - fx**2) / (ffx - 2*fx + x)
|
1094 |
+
return F
|
1095 |
+
|
1096 |
+
OptimizationMethods.jacobian = jacobian
|
1097 |
+
OptimizationMethods.findroot = findroot
|
1098 |
+
OptimizationMethods.multiplicity = multiplicity
|
1099 |
+
|
1100 |
+
if __name__ == '__main__':
|
1101 |
+
import doctest
|
1102 |
+
doctest.testmod()
|
MLPY/Lib/site-packages/mpmath/calculus/polynomials.py
ADDED
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ..libmp.backend import xrange
|
2 |
+
from .calculus import defun
|
3 |
+
|
4 |
+
#----------------------------------------------------------------------------#
|
5 |
+
# Polynomials #
|
6 |
+
#----------------------------------------------------------------------------#
|
7 |
+
|
8 |
+
# XXX: extra precision
|
9 |
+
@defun
|
10 |
+
def polyval(ctx, coeffs, x, derivative=False):
|
11 |
+
r"""
|
12 |
+
Given coefficients `[c_n, \ldots, c_2, c_1, c_0]` and a number `x`,
|
13 |
+
:func:`~mpmath.polyval` evaluates the polynomial
|
14 |
+
|
15 |
+
.. math ::
|
16 |
+
|
17 |
+
P(x) = c_n x^n + \ldots + c_2 x^2 + c_1 x + c_0.
|
18 |
+
|
19 |
+
If *derivative=True* is set, :func:`~mpmath.polyval` simultaneously
|
20 |
+
evaluates `P(x)` with the derivative, `P'(x)`, and returns the
|
21 |
+
tuple `(P(x), P'(x))`.
|
22 |
+
|
23 |
+
>>> from mpmath import *
|
24 |
+
>>> mp.pretty = True
|
25 |
+
>>> polyval([3, 0, 2], 0.5)
|
26 |
+
2.75
|
27 |
+
>>> polyval([3, 0, 2], 0.5, derivative=True)
|
28 |
+
(2.75, 3.0)
|
29 |
+
|
30 |
+
The coefficients and the evaluation point may be any combination
|
31 |
+
of real or complex numbers.
|
32 |
+
"""
|
33 |
+
if not coeffs:
|
34 |
+
return ctx.zero
|
35 |
+
p = ctx.convert(coeffs[0])
|
36 |
+
q = ctx.zero
|
37 |
+
for c in coeffs[1:]:
|
38 |
+
if derivative:
|
39 |
+
q = p + x*q
|
40 |
+
p = c + x*p
|
41 |
+
if derivative:
|
42 |
+
return p, q
|
43 |
+
else:
|
44 |
+
return p
|
45 |
+
|
46 |
+
@defun
|
47 |
+
def polyroots(ctx, coeffs, maxsteps=50, cleanup=True, extraprec=10,
|
48 |
+
error=False, roots_init=None):
|
49 |
+
"""
|
50 |
+
Computes all roots (real or complex) of a given polynomial.
|
51 |
+
|
52 |
+
The roots are returned as a sorted list, where real roots appear first
|
53 |
+
followed by complex conjugate roots as adjacent elements. The polynomial
|
54 |
+
should be given as a list of coefficients, in the format used by
|
55 |
+
:func:`~mpmath.polyval`. The leading coefficient must be nonzero.
|
56 |
+
|
57 |
+
With *error=True*, :func:`~mpmath.polyroots` returns a tuple *(roots, err)*
|
58 |
+
where *err* is an estimate of the maximum error among the computed roots.
|
59 |
+
|
60 |
+
**Examples**
|
61 |
+
|
62 |
+
Finding the three real roots of `x^3 - x^2 - 14x + 24`::
|
63 |
+
|
64 |
+
>>> from mpmath import *
|
65 |
+
>>> mp.dps = 15; mp.pretty = True
|
66 |
+
>>> nprint(polyroots([1,-1,-14,24]), 4)
|
67 |
+
[-4.0, 2.0, 3.0]
|
68 |
+
|
69 |
+
Finding the two complex conjugate roots of `4x^2 + 3x + 2`, with an
|
70 |
+
error estimate::
|
71 |
+
|
72 |
+
>>> roots, err = polyroots([4,3,2], error=True)
|
73 |
+
>>> for r in roots:
|
74 |
+
... print(r)
|
75 |
+
...
|
76 |
+
(-0.375 + 0.59947894041409j)
|
77 |
+
(-0.375 - 0.59947894041409j)
|
78 |
+
>>>
|
79 |
+
>>> err
|
80 |
+
2.22044604925031e-16
|
81 |
+
>>>
|
82 |
+
>>> polyval([4,3,2], roots[0])
|
83 |
+
(2.22044604925031e-16 + 0.0j)
|
84 |
+
>>> polyval([4,3,2], roots[1])
|
85 |
+
(2.22044604925031e-16 + 0.0j)
|
86 |
+
|
87 |
+
The following example computes all the 5th roots of unity; that is,
|
88 |
+
the roots of `x^5 - 1`::
|
89 |
+
|
90 |
+
>>> mp.dps = 20
|
91 |
+
>>> for r in polyroots([1, 0, 0, 0, 0, -1]):
|
92 |
+
... print(r)
|
93 |
+
...
|
94 |
+
1.0
|
95 |
+
(-0.8090169943749474241 + 0.58778525229247312917j)
|
96 |
+
(-0.8090169943749474241 - 0.58778525229247312917j)
|
97 |
+
(0.3090169943749474241 + 0.95105651629515357212j)
|
98 |
+
(0.3090169943749474241 - 0.95105651629515357212j)
|
99 |
+
|
100 |
+
**Precision and conditioning**
|
101 |
+
|
102 |
+
The roots are computed to the current working precision accuracy. If this
|
103 |
+
accuracy cannot be achieved in ``maxsteps`` steps, then a
|
104 |
+
``NoConvergence`` exception is raised. The algorithm internally is using
|
105 |
+
the current working precision extended by ``extraprec``. If
|
106 |
+
``NoConvergence`` was raised, that is caused either by not having enough
|
107 |
+
extra precision to achieve convergence (in which case increasing
|
108 |
+
``extraprec`` should fix the problem) or too low ``maxsteps`` (in which
|
109 |
+
case increasing ``maxsteps`` should fix the problem), or a combination of
|
110 |
+
both.
|
111 |
+
|
112 |
+
The user should always do a convergence study with regards to
|
113 |
+
``extraprec`` to ensure accurate results. It is possible to get
|
114 |
+
convergence to a wrong answer with too low ``extraprec``.
|
115 |
+
|
116 |
+
Provided there are no repeated roots, :func:`~mpmath.polyroots` can
|
117 |
+
typically compute all roots of an arbitrary polynomial to high precision::
|
118 |
+
|
119 |
+
>>> mp.dps = 60
|
120 |
+
>>> for r in polyroots([1, 0, -10, 0, 1]):
|
121 |
+
... print(r)
|
122 |
+
...
|
123 |
+
-3.14626436994197234232913506571557044551247712918732870123249
|
124 |
+
-0.317837245195782244725757617296174288373133378433432554879127
|
125 |
+
0.317837245195782244725757617296174288373133378433432554879127
|
126 |
+
3.14626436994197234232913506571557044551247712918732870123249
|
127 |
+
>>>
|
128 |
+
>>> sqrt(3) + sqrt(2)
|
129 |
+
3.14626436994197234232913506571557044551247712918732870123249
|
130 |
+
>>> sqrt(3) - sqrt(2)
|
131 |
+
0.317837245195782244725757617296174288373133378433432554879127
|
132 |
+
|
133 |
+
**Algorithm**
|
134 |
+
|
135 |
+
:func:`~mpmath.polyroots` implements the Durand-Kerner method [1], which
|
136 |
+
uses complex arithmetic to locate all roots simultaneously.
|
137 |
+
The Durand-Kerner method can be viewed as approximately performing
|
138 |
+
simultaneous Newton iteration for all the roots. In particular,
|
139 |
+
the convergence to simple roots is quadratic, just like Newton's
|
140 |
+
method.
|
141 |
+
|
142 |
+
Although all roots are internally calculated using complex arithmetic, any
|
143 |
+
root found to have an imaginary part smaller than the estimated numerical
|
144 |
+
error is truncated to a real number (small real parts are also chopped).
|
145 |
+
Real roots are placed first in the returned list, sorted by value. The
|
146 |
+
remaining complex roots are sorted by their real parts so that conjugate
|
147 |
+
roots end up next to each other.
|
148 |
+
|
149 |
+
**References**
|
150 |
+
|
151 |
+
1. http://en.wikipedia.org/wiki/Durand-Kerner_method
|
152 |
+
|
153 |
+
"""
|
154 |
+
if len(coeffs) <= 1:
|
155 |
+
if not coeffs or not coeffs[0]:
|
156 |
+
raise ValueError("Input to polyroots must not be the zero polynomial")
|
157 |
+
# Constant polynomial with no roots
|
158 |
+
return []
|
159 |
+
|
160 |
+
orig = ctx.prec
|
161 |
+
tol = +ctx.eps
|
162 |
+
with ctx.extraprec(extraprec):
|
163 |
+
deg = len(coeffs) - 1
|
164 |
+
# Must be monic
|
165 |
+
lead = ctx.convert(coeffs[0])
|
166 |
+
if lead == 1:
|
167 |
+
coeffs = [ctx.convert(c) for c in coeffs]
|
168 |
+
else:
|
169 |
+
coeffs = [c/lead for c in coeffs]
|
170 |
+
f = lambda x: ctx.polyval(coeffs, x)
|
171 |
+
if roots_init is None:
|
172 |
+
roots = [ctx.mpc((0.4+0.9j)**n) for n in xrange(deg)]
|
173 |
+
else:
|
174 |
+
roots = [None]*deg;
|
175 |
+
deg_init = min(deg, len(roots_init))
|
176 |
+
roots[:deg_init] = list(roots_init[:deg_init])
|
177 |
+
roots[deg_init:] = [ctx.mpc((0.4+0.9j)**n) for n
|
178 |
+
in xrange(deg_init,deg)]
|
179 |
+
err = [ctx.one for n in xrange(deg)]
|
180 |
+
# Durand-Kerner iteration until convergence
|
181 |
+
for step in xrange(maxsteps):
|
182 |
+
if abs(max(err)) < tol:
|
183 |
+
break
|
184 |
+
for i in xrange(deg):
|
185 |
+
p = roots[i]
|
186 |
+
x = f(p)
|
187 |
+
for j in range(deg):
|
188 |
+
if i != j:
|
189 |
+
try:
|
190 |
+
x /= (p-roots[j])
|
191 |
+
except ZeroDivisionError:
|
192 |
+
continue
|
193 |
+
roots[i] = p - x
|
194 |
+
err[i] = abs(x)
|
195 |
+
if abs(max(err)) >= tol:
|
196 |
+
raise ctx.NoConvergence("Didn't converge in maxsteps=%d steps." \
|
197 |
+
% maxsteps)
|
198 |
+
# Remove small real or imaginary parts
|
199 |
+
if cleanup:
|
200 |
+
for i in xrange(deg):
|
201 |
+
if abs(roots[i]) < tol:
|
202 |
+
roots[i] = ctx.zero
|
203 |
+
elif abs(ctx._im(roots[i])) < tol:
|
204 |
+
roots[i] = roots[i].real
|
205 |
+
elif abs(ctx._re(roots[i])) < tol:
|
206 |
+
roots[i] = roots[i].imag * 1j
|
207 |
+
roots.sort(key=lambda x: (abs(ctx._im(x)), ctx._re(x)))
|
208 |
+
if error:
|
209 |
+
err = max(err)
|
210 |
+
err = max(err, ctx.ldexp(1, -orig+1))
|
211 |
+
return [+r for r in roots], +err
|
212 |
+
else:
|
213 |
+
return [+r for r in roots]
|