Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/__config__.py +161 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/_distributor_init.py +18 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/__init__.py +31 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/hierarchy.py +0 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/__init__.py +0 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/hierarchy_test_data.py +145 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_disjoint_set.py +202 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_hierarchy.py +1225 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_vq.py +421 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/vq.py +835 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/__init__.py +236 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_basic.py +1919 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_blas_subroutines.h +164 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pxd +40 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pyi +16 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp.py +1621 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cholesky.py +356 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cossin.py +221 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_ldl.py +353 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu.py +374 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu_cython.pyi +6 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_polar.py +111 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qr.py +430 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qz.py +449 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_schur.py +300 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_svd.py +517 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_expm_frechet.py +413 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_interpolative_backend.py +1681 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_lapack_subroutines.h +0 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs.py +861 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_expm.pyi +6 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_inv_ssq.py +886 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_sqrtm.py +214 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_misc.py +191 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_procrustes.py +90 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_sketches.py +179 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_solvers.py +846 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_special_matrices.py +1257 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_testutils.py +65 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/basic.py +24 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/blas.py +484 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pxd +169 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pyx +1422 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pxd +0 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pyx +0 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp.py +25 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_cholesky.py +22 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_lu.py +21 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_qr.py +20 -0
- astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_schur.py +22 -0
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/__config__.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is generated by SciPy's build process
|
| 2 |
+
# It contains system_info results at the time of building this package.
|
| 3 |
+
from enum import Enum
|
| 4 |
+
|
| 5 |
+
__all__ = ["show"]
|
| 6 |
+
_built_with_meson = True
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class DisplayModes(Enum):
|
| 10 |
+
stdout = "stdout"
|
| 11 |
+
dicts = "dicts"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _cleanup(d):
|
| 15 |
+
"""
|
| 16 |
+
Removes empty values in a `dict` recursively
|
| 17 |
+
This ensures we remove values that Meson could not provide to CONFIG
|
| 18 |
+
"""
|
| 19 |
+
if isinstance(d, dict):
|
| 20 |
+
return { k: _cleanup(v) for k, v in d.items() if v != '' and _cleanup(v) != '' }
|
| 21 |
+
else:
|
| 22 |
+
return d
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
CONFIG = _cleanup(
|
| 26 |
+
{
|
| 27 |
+
"Compilers": {
|
| 28 |
+
"c": {
|
| 29 |
+
"name": "clang",
|
| 30 |
+
"linker": r"ld64",
|
| 31 |
+
"version": "15.0.0",
|
| 32 |
+
"commands": r"cc",
|
| 33 |
+
"args": r"",
|
| 34 |
+
"linker args": r"",
|
| 35 |
+
},
|
| 36 |
+
"cython": {
|
| 37 |
+
"name": r"cython",
|
| 38 |
+
"linker": r"cython",
|
| 39 |
+
"version": r"3.0.10",
|
| 40 |
+
"commands": r"cython",
|
| 41 |
+
"args": r"",
|
| 42 |
+
"linker args": r"",
|
| 43 |
+
},
|
| 44 |
+
"c++": {
|
| 45 |
+
"name": "clang",
|
| 46 |
+
"linker": r"ld64",
|
| 47 |
+
"version": "15.0.0",
|
| 48 |
+
"commands": r"c++",
|
| 49 |
+
"args": r"",
|
| 50 |
+
"linker args": r"",
|
| 51 |
+
},
|
| 52 |
+
"fortran": {
|
| 53 |
+
"name": "gcc",
|
| 54 |
+
"linker": r"ld64",
|
| 55 |
+
"version": "12.1.0",
|
| 56 |
+
"commands": r"gfortran",
|
| 57 |
+
"args": r"",
|
| 58 |
+
"linker args": r"",
|
| 59 |
+
},
|
| 60 |
+
"pythran": {
|
| 61 |
+
"version": r"0.15.0",
|
| 62 |
+
"include directory": r"../../../../../../private/var/folders/2f/8t5k6yr535sdw0s4glnpxrzm0000gn/T/pip-build-env-ddcl7dz8/overlay/lib/python3.9/site-packages/pythran"
|
| 63 |
+
},
|
| 64 |
+
},
|
| 65 |
+
"Machine Information": {
|
| 66 |
+
"host": {
|
| 67 |
+
"cpu": r"aarch64",
|
| 68 |
+
"family": r"aarch64",
|
| 69 |
+
"endian": r"little",
|
| 70 |
+
"system": r"darwin",
|
| 71 |
+
},
|
| 72 |
+
"build": {
|
| 73 |
+
"cpu": r"aarch64",
|
| 74 |
+
"family": r"aarch64",
|
| 75 |
+
"endian": r"little",
|
| 76 |
+
"system": r"darwin",
|
| 77 |
+
},
|
| 78 |
+
"cross-compiled": bool("False".lower().replace('false', '')),
|
| 79 |
+
},
|
| 80 |
+
"Build Dependencies": {
|
| 81 |
+
"blas": {
|
| 82 |
+
"name": "openblas",
|
| 83 |
+
"found": bool("True".lower().replace('false', '')),
|
| 84 |
+
"version": "0.3.27",
|
| 85 |
+
"detection method": "pkgconfig",
|
| 86 |
+
"include directory": r"/opt/arm64-builds/include",
|
| 87 |
+
"lib directory": r"/opt/arm64-builds/lib",
|
| 88 |
+
"openblas configuration": r"USE_64BITINT=0 DYNAMIC_ARCH=1 DYNAMIC_OLDER= NO_CBLAS= NO_LAPACK= NO_LAPACKE= NO_AFFINITY=1 USE_OPENMP= SANDYBRIDGE MAX_THREADS=64",
|
| 89 |
+
"pc file directory": r"/opt/arm64-builds/lib/pkgconfig",
|
| 90 |
+
},
|
| 91 |
+
"lapack": {
|
| 92 |
+
"name": "openblas",
|
| 93 |
+
"found": bool("True".lower().replace('false', '')),
|
| 94 |
+
"version": "0.3.27",
|
| 95 |
+
"detection method": "pkgconfig",
|
| 96 |
+
"include directory": r"/opt/arm64-builds/include",
|
| 97 |
+
"lib directory": r"/opt/arm64-builds/lib",
|
| 98 |
+
"openblas configuration": r"USE_64BITINT=0 DYNAMIC_ARCH=1 DYNAMIC_OLDER= NO_CBLAS= NO_LAPACK= NO_LAPACKE= NO_AFFINITY=1 USE_OPENMP= SANDYBRIDGE MAX_THREADS=64",
|
| 99 |
+
"pc file directory": r"/opt/arm64-builds/lib/pkgconfig",
|
| 100 |
+
},
|
| 101 |
+
"pybind11": {
|
| 102 |
+
"name": "pybind11",
|
| 103 |
+
"version": "2.12.0",
|
| 104 |
+
"detection method": "config-tool",
|
| 105 |
+
"include directory": r"unknown",
|
| 106 |
+
},
|
| 107 |
+
},
|
| 108 |
+
"Python Information": {
|
| 109 |
+
"path": r"/private/var/folders/2f/8t5k6yr535sdw0s4glnpxrzm0000gn/T/cibw-run-_36keccq/cp39-macosx_arm64/build/venv/bin/python",
|
| 110 |
+
"version": "3.9",
|
| 111 |
+
},
|
| 112 |
+
}
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def _check_pyyaml():
|
| 117 |
+
import yaml
|
| 118 |
+
|
| 119 |
+
return yaml
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def show(mode=DisplayModes.stdout.value):
|
| 123 |
+
"""
|
| 124 |
+
Show libraries and system information on which SciPy was built
|
| 125 |
+
and is being used
|
| 126 |
+
|
| 127 |
+
Parameters
|
| 128 |
+
----------
|
| 129 |
+
mode : {`'stdout'`, `'dicts'`}, optional.
|
| 130 |
+
Indicates how to display the config information.
|
| 131 |
+
`'stdout'` prints to console, `'dicts'` returns a dictionary
|
| 132 |
+
of the configuration.
|
| 133 |
+
|
| 134 |
+
Returns
|
| 135 |
+
-------
|
| 136 |
+
out : {`dict`, `None`}
|
| 137 |
+
If mode is `'dicts'`, a dict is returned, else None
|
| 138 |
+
|
| 139 |
+
Notes
|
| 140 |
+
-----
|
| 141 |
+
1. The `'stdout'` mode will give more readable
|
| 142 |
+
output if ``pyyaml`` is installed
|
| 143 |
+
|
| 144 |
+
"""
|
| 145 |
+
if mode == DisplayModes.stdout.value:
|
| 146 |
+
try: # Non-standard library, check import
|
| 147 |
+
yaml = _check_pyyaml()
|
| 148 |
+
|
| 149 |
+
print(yaml.dump(CONFIG))
|
| 150 |
+
except ModuleNotFoundError:
|
| 151 |
+
import warnings
|
| 152 |
+
import json
|
| 153 |
+
|
| 154 |
+
warnings.warn("Install `pyyaml` for better output", stacklevel=1)
|
| 155 |
+
print(json.dumps(CONFIG, indent=2))
|
| 156 |
+
elif mode == DisplayModes.dicts.value:
|
| 157 |
+
return CONFIG
|
| 158 |
+
else:
|
| 159 |
+
raise AttributeError(
|
| 160 |
+
f"Invalid `mode`, use one of: {', '.join([e.value for e in DisplayModes])}"
|
| 161 |
+
)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/_distributor_init.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" Distributor init file
|
| 2 |
+
|
| 3 |
+
Distributors: you can replace the contents of this file with your own custom
|
| 4 |
+
code to support particular distributions of SciPy.
|
| 5 |
+
|
| 6 |
+
For example, this is a good place to put any checks for hardware requirements
|
| 7 |
+
or BLAS/LAPACK library initialization.
|
| 8 |
+
|
| 9 |
+
The SciPy standard source distribution will not put code in this file beyond
|
| 10 |
+
the try-except import of `_distributor_init_local` (which is not part of a
|
| 11 |
+
standard source distribution), so you can safely replace this file with your
|
| 12 |
+
own version.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
from . import _distributor_init_local # noqa: F401
|
| 17 |
+
except ImportError:
|
| 18 |
+
pass
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
=========================================
|
| 3 |
+
Clustering package (:mod:`scipy.cluster`)
|
| 4 |
+
=========================================
|
| 5 |
+
|
| 6 |
+
.. currentmodule:: scipy.cluster
|
| 7 |
+
|
| 8 |
+
.. toctree::
|
| 9 |
+
:hidden:
|
| 10 |
+
|
| 11 |
+
cluster.vq
|
| 12 |
+
cluster.hierarchy
|
| 13 |
+
|
| 14 |
+
Clustering algorithms are useful in information theory, target detection,
|
| 15 |
+
communications, compression, and other areas. The `vq` module only
|
| 16 |
+
supports vector quantization and the k-means algorithms.
|
| 17 |
+
|
| 18 |
+
The `hierarchy` module provides functions for hierarchical and
|
| 19 |
+
agglomerative clustering. Its features include generating hierarchical
|
| 20 |
+
clusters from distance matrices,
|
| 21 |
+
calculating statistics on clusters, cutting linkages
|
| 22 |
+
to generate flat clusters, and visualizing clusters with dendrograms.
|
| 23 |
+
|
| 24 |
+
"""
|
| 25 |
+
__all__ = ['vq', 'hierarchy']
|
| 26 |
+
|
| 27 |
+
from . import vq, hierarchy
|
| 28 |
+
|
| 29 |
+
from scipy._lib._testutils import PytestTester
|
| 30 |
+
test = PytestTester(__name__)
|
| 31 |
+
del PytestTester
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/hierarchy.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/__init__.py
ADDED
|
File without changes
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/hierarchy_test_data.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from numpy import array
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
Q_X = array([[5.26563660e-01, 3.14160190e-01, 8.00656370e-02],
|
| 5 |
+
[7.50205180e-01, 4.60299830e-01, 8.98696460e-01],
|
| 6 |
+
[6.65461230e-01, 6.94011420e-01, 9.10465700e-01],
|
| 7 |
+
[9.64047590e-01, 1.43082200e-03, 7.39874220e-01],
|
| 8 |
+
[1.08159060e-01, 5.53028790e-01, 6.63804780e-02],
|
| 9 |
+
[9.31359130e-01, 8.25424910e-01, 9.52315440e-01],
|
| 10 |
+
[6.78086960e-01, 3.41903970e-01, 5.61481950e-01],
|
| 11 |
+
[9.82730940e-01, 7.04605210e-01, 8.70978630e-02],
|
| 12 |
+
[6.14691610e-01, 4.69989230e-02, 6.02406450e-01],
|
| 13 |
+
[5.80161260e-01, 9.17354970e-01, 5.88163850e-01],
|
| 14 |
+
[1.38246310e+00, 1.96358160e+00, 1.94437880e+00],
|
| 15 |
+
[2.10675860e+00, 1.67148730e+00, 1.34854480e+00],
|
| 16 |
+
[1.39880070e+00, 1.66142050e+00, 1.32224550e+00],
|
| 17 |
+
[1.71410460e+00, 1.49176380e+00, 1.45432170e+00],
|
| 18 |
+
[1.54102340e+00, 1.84374950e+00, 1.64658950e+00],
|
| 19 |
+
[2.08512480e+00, 1.84524350e+00, 2.17340850e+00],
|
| 20 |
+
[1.30748740e+00, 1.53801650e+00, 2.16007740e+00],
|
| 21 |
+
[1.41447700e+00, 1.99329070e+00, 1.99107420e+00],
|
| 22 |
+
[1.61943490e+00, 1.47703280e+00, 1.89788160e+00],
|
| 23 |
+
[1.59880600e+00, 1.54988980e+00, 1.57563350e+00],
|
| 24 |
+
[3.37247380e+00, 2.69635310e+00, 3.39981700e+00],
|
| 25 |
+
[3.13705120e+00, 3.36528090e+00, 3.06089070e+00],
|
| 26 |
+
[3.29413250e+00, 3.19619500e+00, 2.90700170e+00],
|
| 27 |
+
[2.65510510e+00, 3.06785900e+00, 2.97198540e+00],
|
| 28 |
+
[3.30941040e+00, 2.59283970e+00, 2.57714110e+00],
|
| 29 |
+
[2.59557220e+00, 3.33477370e+00, 3.08793190e+00],
|
| 30 |
+
[2.58206180e+00, 3.41615670e+00, 3.26441990e+00],
|
| 31 |
+
[2.71127000e+00, 2.77032450e+00, 2.63466500e+00],
|
| 32 |
+
[2.79617850e+00, 3.25473720e+00, 3.41801560e+00],
|
| 33 |
+
[2.64741750e+00, 2.54538040e+00, 3.25354110e+00]])
|
| 34 |
+
|
| 35 |
+
ytdist = array([662., 877., 255., 412., 996., 295., 468., 268., 400., 754.,
|
| 36 |
+
564., 138., 219., 869., 669.])
|
| 37 |
+
|
| 38 |
+
linkage_ytdist_single = array([[2., 5., 138., 2.],
|
| 39 |
+
[3., 4., 219., 2.],
|
| 40 |
+
[0., 7., 255., 3.],
|
| 41 |
+
[1., 8., 268., 4.],
|
| 42 |
+
[6., 9., 295., 6.]])
|
| 43 |
+
|
| 44 |
+
linkage_ytdist_complete = array([[2., 5., 138., 2.],
|
| 45 |
+
[3., 4., 219., 2.],
|
| 46 |
+
[1., 6., 400., 3.],
|
| 47 |
+
[0., 7., 412., 3.],
|
| 48 |
+
[8., 9., 996., 6.]])
|
| 49 |
+
|
| 50 |
+
linkage_ytdist_average = array([[2., 5., 138., 2.],
|
| 51 |
+
[3., 4., 219., 2.],
|
| 52 |
+
[0., 7., 333.5, 3.],
|
| 53 |
+
[1., 6., 347.5, 3.],
|
| 54 |
+
[8., 9., 680.77777778, 6.]])
|
| 55 |
+
|
| 56 |
+
linkage_ytdist_weighted = array([[2., 5., 138., 2.],
|
| 57 |
+
[3., 4., 219., 2.],
|
| 58 |
+
[0., 7., 333.5, 3.],
|
| 59 |
+
[1., 6., 347.5, 3.],
|
| 60 |
+
[8., 9., 670.125, 6.]])
|
| 61 |
+
|
| 62 |
+
# the optimal leaf ordering of linkage_ytdist_single
|
| 63 |
+
linkage_ytdist_single_olo = array([[5., 2., 138., 2.],
|
| 64 |
+
[4., 3., 219., 2.],
|
| 65 |
+
[7., 0., 255., 3.],
|
| 66 |
+
[1., 8., 268., 4.],
|
| 67 |
+
[6., 9., 295., 6.]])
|
| 68 |
+
|
| 69 |
+
X = array([[1.43054825, -7.5693489],
|
| 70 |
+
[6.95887839, 6.82293382],
|
| 71 |
+
[2.87137846, -9.68248579],
|
| 72 |
+
[7.87974764, -6.05485803],
|
| 73 |
+
[8.24018364, -6.09495602],
|
| 74 |
+
[7.39020262, 8.54004355]])
|
| 75 |
+
|
| 76 |
+
linkage_X_centroid = array([[3., 4., 0.36265956, 2.],
|
| 77 |
+
[1., 5., 1.77045373, 2.],
|
| 78 |
+
[0., 2., 2.55760419, 2.],
|
| 79 |
+
[6., 8., 6.43614494, 4.],
|
| 80 |
+
[7., 9., 15.17363237, 6.]])
|
| 81 |
+
|
| 82 |
+
linkage_X_median = array([[3., 4., 0.36265956, 2.],
|
| 83 |
+
[1., 5., 1.77045373, 2.],
|
| 84 |
+
[0., 2., 2.55760419, 2.],
|
| 85 |
+
[6., 8., 6.43614494, 4.],
|
| 86 |
+
[7., 9., 15.17363237, 6.]])
|
| 87 |
+
|
| 88 |
+
linkage_X_ward = array([[3., 4., 0.36265956, 2.],
|
| 89 |
+
[1., 5., 1.77045373, 2.],
|
| 90 |
+
[0., 2., 2.55760419, 2.],
|
| 91 |
+
[6., 8., 9.10208346, 4.],
|
| 92 |
+
[7., 9., 24.7784379, 6.]])
|
| 93 |
+
|
| 94 |
+
# the optimal leaf ordering of linkage_X_ward
|
| 95 |
+
linkage_X_ward_olo = array([[4., 3., 0.36265956, 2.],
|
| 96 |
+
[5., 1., 1.77045373, 2.],
|
| 97 |
+
[2., 0., 2.55760419, 2.],
|
| 98 |
+
[6., 8., 9.10208346, 4.],
|
| 99 |
+
[7., 9., 24.7784379, 6.]])
|
| 100 |
+
|
| 101 |
+
inconsistent_ytdist = {
|
| 102 |
+
1: array([[138., 0., 1., 0.],
|
| 103 |
+
[219., 0., 1., 0.],
|
| 104 |
+
[255., 0., 1., 0.],
|
| 105 |
+
[268., 0., 1., 0.],
|
| 106 |
+
[295., 0., 1., 0.]]),
|
| 107 |
+
2: array([[138., 0., 1., 0.],
|
| 108 |
+
[219., 0., 1., 0.],
|
| 109 |
+
[237., 25.45584412, 2., 0.70710678],
|
| 110 |
+
[261.5, 9.19238816, 2., 0.70710678],
|
| 111 |
+
[233.66666667, 83.9424406, 3., 0.7306594]]),
|
| 112 |
+
3: array([[138., 0., 1., 0.],
|
| 113 |
+
[219., 0., 1., 0.],
|
| 114 |
+
[237., 25.45584412, 2., 0.70710678],
|
| 115 |
+
[247.33333333, 25.38372182, 3., 0.81417007],
|
| 116 |
+
[239., 69.36377537, 4., 0.80733783]]),
|
| 117 |
+
4: array([[138., 0., 1., 0.],
|
| 118 |
+
[219., 0., 1., 0.],
|
| 119 |
+
[237., 25.45584412, 2., 0.70710678],
|
| 120 |
+
[247.33333333, 25.38372182, 3., 0.81417007],
|
| 121 |
+
[235., 60.73302232, 5., 0.98793042]])}
|
| 122 |
+
|
| 123 |
+
fcluster_inconsistent = {
|
| 124 |
+
0.8: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1,
|
| 125 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1]),
|
| 126 |
+
1.0: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1,
|
| 127 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1]),
|
| 128 |
+
2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 129 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1])}
|
| 130 |
+
|
| 131 |
+
fcluster_distance = {
|
| 132 |
+
0.6: array([4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 3,
|
| 133 |
+
1, 1, 1, 2, 1, 1, 1, 1, 1]),
|
| 134 |
+
1.0: array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
|
| 135 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1]),
|
| 136 |
+
2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 137 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1])}
|
| 138 |
+
|
| 139 |
+
fcluster_maxclust = {
|
| 140 |
+
8.0: array([5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 4,
|
| 141 |
+
1, 1, 1, 3, 1, 1, 1, 1, 2]),
|
| 142 |
+
4.0: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
|
| 143 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1]),
|
| 144 |
+
1.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 145 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1])}
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_disjoint_set.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from pytest import raises as assert_raises
|
| 3 |
+
import numpy as np
|
| 4 |
+
from scipy.cluster.hierarchy import DisjointSet
|
| 5 |
+
import string
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def generate_random_token():
|
| 9 |
+
k = len(string.ascii_letters)
|
| 10 |
+
tokens = list(np.arange(k, dtype=int))
|
| 11 |
+
tokens += list(np.arange(k, dtype=float))
|
| 12 |
+
tokens += list(string.ascii_letters)
|
| 13 |
+
tokens += [None for i in range(k)]
|
| 14 |
+
tokens = np.array(tokens, dtype=object)
|
| 15 |
+
rng = np.random.RandomState(seed=0)
|
| 16 |
+
|
| 17 |
+
while 1:
|
| 18 |
+
size = rng.randint(1, 3)
|
| 19 |
+
element = rng.choice(tokens, size)
|
| 20 |
+
if size == 1:
|
| 21 |
+
yield element[0]
|
| 22 |
+
else:
|
| 23 |
+
yield tuple(element)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def get_elements(n):
|
| 27 |
+
# dict is deterministic without difficulty of comparing numpy ints
|
| 28 |
+
elements = {}
|
| 29 |
+
for element in generate_random_token():
|
| 30 |
+
if element not in elements:
|
| 31 |
+
elements[element] = len(elements)
|
| 32 |
+
if len(elements) >= n:
|
| 33 |
+
break
|
| 34 |
+
return list(elements.keys())
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def test_init():
|
| 38 |
+
n = 10
|
| 39 |
+
elements = get_elements(n)
|
| 40 |
+
dis = DisjointSet(elements)
|
| 41 |
+
assert dis.n_subsets == n
|
| 42 |
+
assert list(dis) == elements
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def test_len():
|
| 46 |
+
n = 10
|
| 47 |
+
elements = get_elements(n)
|
| 48 |
+
dis = DisjointSet(elements)
|
| 49 |
+
assert len(dis) == n
|
| 50 |
+
|
| 51 |
+
dis.add("dummy")
|
| 52 |
+
assert len(dis) == n + 1
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 56 |
+
def test_contains(n):
|
| 57 |
+
elements = get_elements(n)
|
| 58 |
+
dis = DisjointSet(elements)
|
| 59 |
+
for x in elements:
|
| 60 |
+
assert x in dis
|
| 61 |
+
|
| 62 |
+
assert "dummy" not in dis
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 66 |
+
def test_add(n):
|
| 67 |
+
elements = get_elements(n)
|
| 68 |
+
dis1 = DisjointSet(elements)
|
| 69 |
+
|
| 70 |
+
dis2 = DisjointSet()
|
| 71 |
+
for i, x in enumerate(elements):
|
| 72 |
+
dis2.add(x)
|
| 73 |
+
assert len(dis2) == i + 1
|
| 74 |
+
|
| 75 |
+
# test idempotency by adding element again
|
| 76 |
+
dis2.add(x)
|
| 77 |
+
assert len(dis2) == i + 1
|
| 78 |
+
|
| 79 |
+
assert list(dis1) == list(dis2)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def test_element_not_present():
|
| 83 |
+
elements = get_elements(n=10)
|
| 84 |
+
dis = DisjointSet(elements)
|
| 85 |
+
|
| 86 |
+
with assert_raises(KeyError):
|
| 87 |
+
dis["dummy"]
|
| 88 |
+
|
| 89 |
+
with assert_raises(KeyError):
|
| 90 |
+
dis.merge(elements[0], "dummy")
|
| 91 |
+
|
| 92 |
+
with assert_raises(KeyError):
|
| 93 |
+
dis.connected(elements[0], "dummy")
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
@pytest.mark.parametrize("direction", ["forwards", "backwards"])
|
| 97 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 98 |
+
def test_linear_union_sequence(n, direction):
|
| 99 |
+
elements = get_elements(n)
|
| 100 |
+
dis = DisjointSet(elements)
|
| 101 |
+
assert elements == list(dis)
|
| 102 |
+
|
| 103 |
+
indices = list(range(n - 1))
|
| 104 |
+
if direction == "backwards":
|
| 105 |
+
indices = indices[::-1]
|
| 106 |
+
|
| 107 |
+
for it, i in enumerate(indices):
|
| 108 |
+
assert not dis.connected(elements[i], elements[i + 1])
|
| 109 |
+
assert dis.merge(elements[i], elements[i + 1])
|
| 110 |
+
assert dis.connected(elements[i], elements[i + 1])
|
| 111 |
+
assert dis.n_subsets == n - 1 - it
|
| 112 |
+
|
| 113 |
+
roots = [dis[i] for i in elements]
|
| 114 |
+
if direction == "forwards":
|
| 115 |
+
assert all(elements[0] == r for r in roots)
|
| 116 |
+
else:
|
| 117 |
+
assert all(elements[-2] == r for r in roots)
|
| 118 |
+
assert not dis.merge(elements[0], elements[-1])
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 122 |
+
def test_self_unions(n):
|
| 123 |
+
elements = get_elements(n)
|
| 124 |
+
dis = DisjointSet(elements)
|
| 125 |
+
|
| 126 |
+
for x in elements:
|
| 127 |
+
assert dis.connected(x, x)
|
| 128 |
+
assert not dis.merge(x, x)
|
| 129 |
+
assert dis.connected(x, x)
|
| 130 |
+
assert dis.n_subsets == len(elements)
|
| 131 |
+
|
| 132 |
+
assert elements == list(dis)
|
| 133 |
+
roots = [dis[x] for x in elements]
|
| 134 |
+
assert elements == roots
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
@pytest.mark.parametrize("order", ["ab", "ba"])
|
| 138 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 139 |
+
def test_equal_size_ordering(n, order):
|
| 140 |
+
elements = get_elements(n)
|
| 141 |
+
dis = DisjointSet(elements)
|
| 142 |
+
|
| 143 |
+
rng = np.random.RandomState(seed=0)
|
| 144 |
+
indices = np.arange(n)
|
| 145 |
+
rng.shuffle(indices)
|
| 146 |
+
|
| 147 |
+
for i in range(0, len(indices), 2):
|
| 148 |
+
a, b = elements[indices[i]], elements[indices[i + 1]]
|
| 149 |
+
if order == "ab":
|
| 150 |
+
assert dis.merge(a, b)
|
| 151 |
+
else:
|
| 152 |
+
assert dis.merge(b, a)
|
| 153 |
+
|
| 154 |
+
expected = elements[min(indices[i], indices[i + 1])]
|
| 155 |
+
assert dis[a] == expected
|
| 156 |
+
assert dis[b] == expected
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
@pytest.mark.parametrize("kmax", [5, 10])
|
| 160 |
+
def test_binary_tree(kmax):
|
| 161 |
+
n = 2**kmax
|
| 162 |
+
elements = get_elements(n)
|
| 163 |
+
dis = DisjointSet(elements)
|
| 164 |
+
rng = np.random.RandomState(seed=0)
|
| 165 |
+
|
| 166 |
+
for k in 2**np.arange(kmax):
|
| 167 |
+
for i in range(0, n, 2 * k):
|
| 168 |
+
r1, r2 = rng.randint(0, k, size=2)
|
| 169 |
+
a, b = elements[i + r1], elements[i + k + r2]
|
| 170 |
+
assert not dis.connected(a, b)
|
| 171 |
+
assert dis.merge(a, b)
|
| 172 |
+
assert dis.connected(a, b)
|
| 173 |
+
|
| 174 |
+
assert elements == list(dis)
|
| 175 |
+
roots = [dis[i] for i in elements]
|
| 176 |
+
expected_indices = np.arange(n) - np.arange(n) % (2 * k)
|
| 177 |
+
expected = [elements[i] for i in expected_indices]
|
| 178 |
+
assert roots == expected
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
@pytest.mark.parametrize("n", [10, 100])
|
| 182 |
+
def test_subsets(n):
|
| 183 |
+
elements = get_elements(n)
|
| 184 |
+
dis = DisjointSet(elements)
|
| 185 |
+
|
| 186 |
+
rng = np.random.RandomState(seed=0)
|
| 187 |
+
for i, j in rng.randint(0, n, (n, 2)):
|
| 188 |
+
x = elements[i]
|
| 189 |
+
y = elements[j]
|
| 190 |
+
|
| 191 |
+
expected = {element for element in dis if {dis[element]} == {dis[x]}}
|
| 192 |
+
assert dis.subset_size(x) == len(dis.subset(x))
|
| 193 |
+
assert expected == dis.subset(x)
|
| 194 |
+
|
| 195 |
+
expected = {dis[element]: set() for element in dis}
|
| 196 |
+
for element in dis:
|
| 197 |
+
expected[dis[element]].add(element)
|
| 198 |
+
expected = list(expected.values())
|
| 199 |
+
assert expected == dis.subsets()
|
| 200 |
+
|
| 201 |
+
dis.merge(x, y)
|
| 202 |
+
assert dis.subset(x) == dis.subset(y)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_hierarchy.py
ADDED
|
@@ -0,0 +1,1225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Author: Damian Eads
|
| 3 |
+
# Date: April 17, 2008
|
| 4 |
+
#
|
| 5 |
+
# Copyright (C) 2008 Damian Eads
|
| 6 |
+
#
|
| 7 |
+
# Redistribution and use in source and binary forms, with or without
|
| 8 |
+
# modification, are permitted provided that the following conditions
|
| 9 |
+
# are met:
|
| 10 |
+
#
|
| 11 |
+
# 1. Redistributions of source code must retain the above copyright
|
| 12 |
+
# notice, this list of conditions and the following disclaimer.
|
| 13 |
+
#
|
| 14 |
+
# 2. Redistributions in binary form must reproduce the above
|
| 15 |
+
# copyright notice, this list of conditions and the following
|
| 16 |
+
# disclaimer in the documentation and/or other materials provided
|
| 17 |
+
# with the distribution.
|
| 18 |
+
#
|
| 19 |
+
# 3. The name of the author may not be used to endorse or promote
|
| 20 |
+
# products derived from this software without specific prior
|
| 21 |
+
# written permission.
|
| 22 |
+
#
|
| 23 |
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
| 24 |
+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 25 |
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
| 26 |
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
| 27 |
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 28 |
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
| 29 |
+
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
| 30 |
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
| 31 |
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
| 32 |
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| 33 |
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 34 |
+
import numpy as np
|
| 35 |
+
from numpy.testing import assert_allclose, assert_equal, assert_, assert_warns
|
| 36 |
+
import pytest
|
| 37 |
+
from pytest import raises as assert_raises
|
| 38 |
+
|
| 39 |
+
import scipy.cluster.hierarchy
|
| 40 |
+
from scipy.cluster.hierarchy import (
|
| 41 |
+
ClusterWarning, linkage, from_mlab_linkage, to_mlab_linkage,
|
| 42 |
+
num_obs_linkage, inconsistent, cophenet, fclusterdata, fcluster,
|
| 43 |
+
is_isomorphic, single, leaders,
|
| 44 |
+
correspond, is_monotonic, maxdists, maxinconsts, maxRstat,
|
| 45 |
+
is_valid_linkage, is_valid_im, to_tree, leaves_list, dendrogram,
|
| 46 |
+
set_link_color_palette, cut_tree, optimal_leaf_ordering,
|
| 47 |
+
_order_cluster_tree, _hierarchy, _LINKAGE_METHODS)
|
| 48 |
+
from scipy.spatial.distance import pdist
|
| 49 |
+
from scipy.cluster._hierarchy import Heap
|
| 50 |
+
from scipy.conftest import array_api_compatible
|
| 51 |
+
from scipy._lib._array_api import xp_assert_close, xp_assert_equal
|
| 52 |
+
|
| 53 |
+
from . import hierarchy_test_data
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
# Matplotlib is not a scipy dependency but is optionally used in dendrogram, so
|
| 57 |
+
# check if it's available
|
| 58 |
+
try:
|
| 59 |
+
import matplotlib
|
| 60 |
+
# and set the backend to be Agg (no gui)
|
| 61 |
+
matplotlib.use('Agg')
|
| 62 |
+
# before importing pyplot
|
| 63 |
+
import matplotlib.pyplot as plt
|
| 64 |
+
have_matplotlib = True
|
| 65 |
+
except Exception:
|
| 66 |
+
have_matplotlib = False
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_if_array_api")]
|
| 70 |
+
skip_if_array_api = pytest.mark.skip_if_array_api
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class TestLinkage:
|
| 74 |
+
|
| 75 |
+
@skip_if_array_api(cpu_only=True)
|
| 76 |
+
def test_linkage_non_finite_elements_in_distance_matrix(self, xp):
|
| 77 |
+
# Tests linkage(Y) where Y contains a non-finite element (e.g. NaN or Inf).
|
| 78 |
+
# Exception expected.
|
| 79 |
+
y = xp.zeros((6,))
|
| 80 |
+
y[0] = xp.nan
|
| 81 |
+
assert_raises(ValueError, linkage, y)
|
| 82 |
+
|
| 83 |
+
@skip_if_array_api(cpu_only=True)
|
| 84 |
+
def test_linkage_empty_distance_matrix(self, xp):
|
| 85 |
+
# Tests linkage(Y) where Y is a 0x4 linkage matrix. Exception expected.
|
| 86 |
+
y = xp.zeros((0,))
|
| 87 |
+
assert_raises(ValueError, linkage, y)
|
| 88 |
+
|
| 89 |
+
@skip_if_array_api(cpu_only=True)
|
| 90 |
+
def test_linkage_tdist(self, xp):
|
| 91 |
+
for method in ['single', 'complete', 'average', 'weighted']:
|
| 92 |
+
self.check_linkage_tdist(method, xp)
|
| 93 |
+
|
| 94 |
+
def check_linkage_tdist(self, method, xp):
|
| 95 |
+
# Tests linkage(Y, method) on the tdist data set.
|
| 96 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), method)
|
| 97 |
+
expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_' + method)
|
| 98 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
|
| 99 |
+
|
| 100 |
+
@skip_if_array_api(cpu_only=True)
|
| 101 |
+
def test_linkage_X(self, xp):
|
| 102 |
+
for method in ['centroid', 'median', 'ward']:
|
| 103 |
+
self.check_linkage_q(method, xp)
|
| 104 |
+
|
| 105 |
+
def check_linkage_q(self, method, xp):
|
| 106 |
+
# Tests linkage(Y, method) on the Q data set.
|
| 107 |
+
Z = linkage(xp.asarray(hierarchy_test_data.X), method)
|
| 108 |
+
expectedZ = getattr(hierarchy_test_data, 'linkage_X_' + method)
|
| 109 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
|
| 110 |
+
|
| 111 |
+
y = scipy.spatial.distance.pdist(hierarchy_test_data.X,
|
| 112 |
+
metric="euclidean")
|
| 113 |
+
Z = linkage(xp.asarray(y), method)
|
| 114 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
|
| 115 |
+
|
| 116 |
+
@skip_if_array_api(cpu_only=True)
|
| 117 |
+
def test_compare_with_trivial(self, xp):
|
| 118 |
+
rng = np.random.RandomState(0)
|
| 119 |
+
n = 20
|
| 120 |
+
X = rng.rand(n, 2)
|
| 121 |
+
d = pdist(X)
|
| 122 |
+
|
| 123 |
+
for method, code in _LINKAGE_METHODS.items():
|
| 124 |
+
Z_trivial = _hierarchy.linkage(d, n, code)
|
| 125 |
+
Z = linkage(xp.asarray(d), method)
|
| 126 |
+
xp_assert_close(Z, xp.asarray(Z_trivial), rtol=1e-14, atol=1e-15)
|
| 127 |
+
|
| 128 |
+
@skip_if_array_api(cpu_only=True)
|
| 129 |
+
def test_optimal_leaf_ordering(self, xp):
|
| 130 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), optimal_ordering=True)
|
| 131 |
+
expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_single_olo')
|
| 132 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
@skip_if_array_api(cpu_only=True)
|
| 136 |
+
class TestLinkageTies:
|
| 137 |
+
|
| 138 |
+
_expectations = {
|
| 139 |
+
'single': np.array([[0, 1, 1.41421356, 2],
|
| 140 |
+
[2, 3, 1.41421356, 3]]),
|
| 141 |
+
'complete': np.array([[0, 1, 1.41421356, 2],
|
| 142 |
+
[2, 3, 2.82842712, 3]]),
|
| 143 |
+
'average': np.array([[0, 1, 1.41421356, 2],
|
| 144 |
+
[2, 3, 2.12132034, 3]]),
|
| 145 |
+
'weighted': np.array([[0, 1, 1.41421356, 2],
|
| 146 |
+
[2, 3, 2.12132034, 3]]),
|
| 147 |
+
'centroid': np.array([[0, 1, 1.41421356, 2],
|
| 148 |
+
[2, 3, 2.12132034, 3]]),
|
| 149 |
+
'median': np.array([[0, 1, 1.41421356, 2],
|
| 150 |
+
[2, 3, 2.12132034, 3]]),
|
| 151 |
+
'ward': np.array([[0, 1, 1.41421356, 2],
|
| 152 |
+
[2, 3, 2.44948974, 3]]),
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
def test_linkage_ties(self, xp):
|
| 156 |
+
for method in ['single', 'complete', 'average', 'weighted',
|
| 157 |
+
'centroid', 'median', 'ward']:
|
| 158 |
+
self.check_linkage_ties(method, xp)
|
| 159 |
+
|
| 160 |
+
def check_linkage_ties(self, method, xp):
|
| 161 |
+
X = xp.asarray([[-1, -1], [0, 0], [1, 1]])
|
| 162 |
+
Z = linkage(X, method=method)
|
| 163 |
+
expectedZ = self._expectations[method]
|
| 164 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
@skip_if_array_api(cpu_only=True)
|
| 168 |
+
class TestInconsistent:
|
| 169 |
+
|
| 170 |
+
def test_inconsistent_tdist(self, xp):
|
| 171 |
+
for depth in hierarchy_test_data.inconsistent_ytdist:
|
| 172 |
+
self.check_inconsistent_tdist(depth, xp)
|
| 173 |
+
|
| 174 |
+
def check_inconsistent_tdist(self, depth, xp):
|
| 175 |
+
Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
|
| 176 |
+
xp_assert_close(inconsistent(Z, depth),
|
| 177 |
+
xp.asarray(hierarchy_test_data.inconsistent_ytdist[depth]))
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
@skip_if_array_api(cpu_only=True)
|
| 181 |
+
class TestCopheneticDistance:
|
| 182 |
+
|
| 183 |
+
def test_linkage_cophenet_tdist_Z(self, xp):
|
| 184 |
+
# Tests cophenet(Z) on tdist data set.
|
| 185 |
+
expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295,
|
| 186 |
+
295, 138, 219, 295, 295])
|
| 187 |
+
Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
|
| 188 |
+
M = cophenet(Z)
|
| 189 |
+
xp_assert_close(M, xp.asarray(expectedM, dtype=xp.float64), atol=1e-10)
|
| 190 |
+
|
| 191 |
+
def test_linkage_cophenet_tdist_Z_Y(self, xp):
|
| 192 |
+
# Tests cophenet(Z, Y) on tdist data set.
|
| 193 |
+
Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
|
| 194 |
+
(c, M) = cophenet(Z, xp.asarray(hierarchy_test_data.ytdist))
|
| 195 |
+
expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295,
|
| 196 |
+
295, 138, 219, 295, 295], dtype=xp.float64)
|
| 197 |
+
expectedc = xp.asarray(0.639931296433393415057366837573, dtype=xp.float64)[()]
|
| 198 |
+
xp_assert_close(c, expectedc, atol=1e-10)
|
| 199 |
+
xp_assert_close(M, expectedM, atol=1e-10)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
class TestMLabLinkageConversion:
|
| 203 |
+
|
| 204 |
+
def test_mlab_linkage_conversion_empty(self, xp):
|
| 205 |
+
# Tests from/to_mlab_linkage on empty linkage array.
|
| 206 |
+
X = xp.asarray([], dtype=xp.float64)
|
| 207 |
+
xp_assert_equal(from_mlab_linkage(X), X)
|
| 208 |
+
xp_assert_equal(to_mlab_linkage(X), X)
|
| 209 |
+
|
| 210 |
+
@skip_if_array_api(cpu_only=True)
|
| 211 |
+
def test_mlab_linkage_conversion_single_row(self, xp):
|
| 212 |
+
# Tests from/to_mlab_linkage on linkage array with single row.
|
| 213 |
+
Z = xp.asarray([[0., 1., 3., 2.]])
|
| 214 |
+
Zm = xp.asarray([[1, 2, 3]])
|
| 215 |
+
xp_assert_close(from_mlab_linkage(Zm), xp.asarray(Z, dtype=xp.float64),
|
| 216 |
+
rtol=1e-15)
|
| 217 |
+
xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64),
|
| 218 |
+
rtol=1e-15)
|
| 219 |
+
|
| 220 |
+
@skip_if_array_api(cpu_only=True)
|
| 221 |
+
def test_mlab_linkage_conversion_multiple_rows(self, xp):
|
| 222 |
+
# Tests from/to_mlab_linkage on linkage array with multiple rows.
|
| 223 |
+
Zm = xp.asarray([[3, 6, 138], [4, 5, 219],
|
| 224 |
+
[1, 8, 255], [2, 9, 268], [7, 10, 295]])
|
| 225 |
+
Z = xp.asarray([[2., 5., 138., 2.],
|
| 226 |
+
[3., 4., 219., 2.],
|
| 227 |
+
[0., 7., 255., 3.],
|
| 228 |
+
[1., 8., 268., 4.],
|
| 229 |
+
[6., 9., 295., 6.]],
|
| 230 |
+
dtype=xp.float64)
|
| 231 |
+
xp_assert_close(from_mlab_linkage(Zm), Z, rtol=1e-15)
|
| 232 |
+
xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64),
|
| 233 |
+
rtol=1e-15)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
@skip_if_array_api(cpu_only=True)
|
| 237 |
+
class TestFcluster:
|
| 238 |
+
|
| 239 |
+
def test_fclusterdata(self, xp):
|
| 240 |
+
for t in hierarchy_test_data.fcluster_inconsistent:
|
| 241 |
+
self.check_fclusterdata(t, 'inconsistent', xp)
|
| 242 |
+
for t in hierarchy_test_data.fcluster_distance:
|
| 243 |
+
self.check_fclusterdata(t, 'distance', xp)
|
| 244 |
+
for t in hierarchy_test_data.fcluster_maxclust:
|
| 245 |
+
self.check_fclusterdata(t, 'maxclust', xp)
|
| 246 |
+
|
| 247 |
+
def check_fclusterdata(self, t, criterion, xp):
|
| 248 |
+
# Tests fclusterdata(X, criterion=criterion, t=t) on a random 3-cluster data set
|
| 249 |
+
expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t])
|
| 250 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 251 |
+
T = fclusterdata(X, criterion=criterion, t=t)
|
| 252 |
+
assert_(is_isomorphic(T, expectedT))
|
| 253 |
+
|
| 254 |
+
def test_fcluster(self, xp):
|
| 255 |
+
for t in hierarchy_test_data.fcluster_inconsistent:
|
| 256 |
+
self.check_fcluster(t, 'inconsistent', xp)
|
| 257 |
+
for t in hierarchy_test_data.fcluster_distance:
|
| 258 |
+
self.check_fcluster(t, 'distance', xp)
|
| 259 |
+
for t in hierarchy_test_data.fcluster_maxclust:
|
| 260 |
+
self.check_fcluster(t, 'maxclust', xp)
|
| 261 |
+
|
| 262 |
+
def check_fcluster(self, t, criterion, xp):
|
| 263 |
+
# Tests fcluster(Z, criterion=criterion, t=t) on a random 3-cluster data set.
|
| 264 |
+
expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t])
|
| 265 |
+
Z = single(xp.asarray(hierarchy_test_data.Q_X))
|
| 266 |
+
T = fcluster(Z, criterion=criterion, t=t)
|
| 267 |
+
assert_(is_isomorphic(T, expectedT))
|
| 268 |
+
|
| 269 |
+
def test_fcluster_monocrit(self, xp):
|
| 270 |
+
for t in hierarchy_test_data.fcluster_distance:
|
| 271 |
+
self.check_fcluster_monocrit(t, xp)
|
| 272 |
+
for t in hierarchy_test_data.fcluster_maxclust:
|
| 273 |
+
self.check_fcluster_maxclust_monocrit(t, xp)
|
| 274 |
+
|
| 275 |
+
def check_fcluster_monocrit(self, t, xp):
|
| 276 |
+
expectedT = xp.asarray(hierarchy_test_data.fcluster_distance[t])
|
| 277 |
+
Z = single(xp.asarray(hierarchy_test_data.Q_X))
|
| 278 |
+
T = fcluster(Z, t, criterion='monocrit', monocrit=maxdists(Z))
|
| 279 |
+
assert_(is_isomorphic(T, expectedT))
|
| 280 |
+
|
| 281 |
+
def check_fcluster_maxclust_monocrit(self, t, xp):
|
| 282 |
+
expectedT = xp.asarray(hierarchy_test_data.fcluster_maxclust[t])
|
| 283 |
+
Z = single(xp.asarray(hierarchy_test_data.Q_X))
|
| 284 |
+
T = fcluster(Z, t, criterion='maxclust_monocrit', monocrit=maxdists(Z))
|
| 285 |
+
assert_(is_isomorphic(T, expectedT))
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
@skip_if_array_api(cpu_only=True)
|
| 289 |
+
class TestLeaders:
|
| 290 |
+
|
| 291 |
+
def test_leaders_single(self, xp):
|
| 292 |
+
# Tests leaders using a flat clustering generated by single linkage.
|
| 293 |
+
X = hierarchy_test_data.Q_X
|
| 294 |
+
Y = pdist(X)
|
| 295 |
+
Y = xp.asarray(Y)
|
| 296 |
+
Z = linkage(Y)
|
| 297 |
+
T = fcluster(Z, criterion='maxclust', t=3)
|
| 298 |
+
Lright = (xp.asarray([53, 55, 56]), xp.asarray([2, 3, 1]))
|
| 299 |
+
T = xp.asarray(T, dtype=xp.int32)
|
| 300 |
+
L = leaders(Z, T)
|
| 301 |
+
assert_allclose(np.concatenate(L), np.concatenate(Lright), rtol=1e-15)
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
@skip_if_array_api(np_only=True,
|
| 305 |
+
reasons=['`is_isomorphic` only supports NumPy backend'])
|
| 306 |
+
class TestIsIsomorphic:
|
| 307 |
+
|
| 308 |
+
@skip_if_array_api(np_only=True,
|
| 309 |
+
reasons=['array-likes only supported for NumPy backend'])
|
| 310 |
+
def test_array_like(self, xp):
|
| 311 |
+
assert is_isomorphic([1, 1, 1], [2, 2, 2])
|
| 312 |
+
assert is_isomorphic([], [])
|
| 313 |
+
|
| 314 |
+
def test_is_isomorphic_1(self, xp):
|
| 315 |
+
# Tests is_isomorphic on test case #1 (one flat cluster, different labellings)
|
| 316 |
+
a = xp.asarray([1, 1, 1])
|
| 317 |
+
b = xp.asarray([2, 2, 2])
|
| 318 |
+
assert is_isomorphic(a, b)
|
| 319 |
+
assert is_isomorphic(b, a)
|
| 320 |
+
|
| 321 |
+
def test_is_isomorphic_2(self, xp):
|
| 322 |
+
# Tests is_isomorphic on test case #2 (two flat clusters, different labelings)
|
| 323 |
+
a = xp.asarray([1, 7, 1])
|
| 324 |
+
b = xp.asarray([2, 3, 2])
|
| 325 |
+
assert is_isomorphic(a, b)
|
| 326 |
+
assert is_isomorphic(b, a)
|
| 327 |
+
|
| 328 |
+
def test_is_isomorphic_3(self, xp):
|
| 329 |
+
# Tests is_isomorphic on test case #3 (no flat clusters)
|
| 330 |
+
a = xp.asarray([])
|
| 331 |
+
b = xp.asarray([])
|
| 332 |
+
assert is_isomorphic(a, b)
|
| 333 |
+
|
| 334 |
+
def test_is_isomorphic_4A(self, xp):
|
| 335 |
+
# Tests is_isomorphic on test case #4A
|
| 336 |
+
# (3 flat clusters, different labelings, isomorphic)
|
| 337 |
+
a = xp.asarray([1, 2, 3])
|
| 338 |
+
b = xp.asarray([1, 3, 2])
|
| 339 |
+
assert is_isomorphic(a, b)
|
| 340 |
+
assert is_isomorphic(b, a)
|
| 341 |
+
|
| 342 |
+
def test_is_isomorphic_4B(self, xp):
|
| 343 |
+
# Tests is_isomorphic on test case #4B
|
| 344 |
+
# (3 flat clusters, different labelings, nonisomorphic)
|
| 345 |
+
a = xp.asarray([1, 2, 3, 3])
|
| 346 |
+
b = xp.asarray([1, 3, 2, 3])
|
| 347 |
+
assert is_isomorphic(a, b) is False
|
| 348 |
+
assert is_isomorphic(b, a) is False
|
| 349 |
+
|
| 350 |
+
def test_is_isomorphic_4C(self, xp):
|
| 351 |
+
# Tests is_isomorphic on test case #4C
|
| 352 |
+
# (3 flat clusters, different labelings, isomorphic)
|
| 353 |
+
a = xp.asarray([7, 2, 3])
|
| 354 |
+
b = xp.asarray([6, 3, 2])
|
| 355 |
+
assert is_isomorphic(a, b)
|
| 356 |
+
assert is_isomorphic(b, a)
|
| 357 |
+
|
| 358 |
+
def test_is_isomorphic_5(self, xp):
|
| 359 |
+
# Tests is_isomorphic on test case #5 (1000 observations, 2/3/5 random
|
| 360 |
+
# clusters, random permutation of the labeling).
|
| 361 |
+
for nc in [2, 3, 5]:
|
| 362 |
+
self.help_is_isomorphic_randperm(1000, nc, xp=xp)
|
| 363 |
+
|
| 364 |
+
def test_is_isomorphic_6(self, xp):
|
| 365 |
+
# Tests is_isomorphic on test case #5A (1000 observations, 2/3/5 random
|
| 366 |
+
# clusters, random permutation of the labeling, slightly
|
| 367 |
+
# nonisomorphic.)
|
| 368 |
+
for nc in [2, 3, 5]:
|
| 369 |
+
self.help_is_isomorphic_randperm(1000, nc, True, 5, xp=xp)
|
| 370 |
+
|
| 371 |
+
def test_is_isomorphic_7(self, xp):
|
| 372 |
+
# Regression test for gh-6271
|
| 373 |
+
a = xp.asarray([1, 2, 3])
|
| 374 |
+
b = xp.asarray([1, 1, 1])
|
| 375 |
+
assert not is_isomorphic(a, b)
|
| 376 |
+
|
| 377 |
+
def help_is_isomorphic_randperm(self, nobs, nclusters, noniso=False, nerrors=0,
|
| 378 |
+
*, xp):
|
| 379 |
+
for k in range(3):
|
| 380 |
+
a = (np.random.rand(nobs) * nclusters).astype(int)
|
| 381 |
+
b = np.zeros(a.size, dtype=int)
|
| 382 |
+
P = np.random.permutation(nclusters)
|
| 383 |
+
for i in range(0, a.shape[0]):
|
| 384 |
+
b[i] = P[a[i]]
|
| 385 |
+
if noniso:
|
| 386 |
+
Q = np.random.permutation(nobs)
|
| 387 |
+
b[Q[0:nerrors]] += 1
|
| 388 |
+
b[Q[0:nerrors]] %= nclusters
|
| 389 |
+
a = xp.asarray(a)
|
| 390 |
+
b = xp.asarray(b)
|
| 391 |
+
assert is_isomorphic(a, b) == (not noniso)
|
| 392 |
+
assert is_isomorphic(b, a) == (not noniso)
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
@skip_if_array_api(cpu_only=True)
|
| 396 |
+
class TestIsValidLinkage:
|
| 397 |
+
|
| 398 |
+
def test_is_valid_linkage_various_size(self, xp):
|
| 399 |
+
for nrow, ncol, valid in [(2, 5, False), (2, 3, False),
|
| 400 |
+
(1, 4, True), (2, 4, True)]:
|
| 401 |
+
self.check_is_valid_linkage_various_size(nrow, ncol, valid, xp)
|
| 402 |
+
|
| 403 |
+
def check_is_valid_linkage_various_size(self, nrow, ncol, valid, xp):
|
| 404 |
+
# Tests is_valid_linkage(Z) with linkage matrices of various sizes
|
| 405 |
+
Z = xp.asarray([[0, 1, 3.0, 2, 5],
|
| 406 |
+
[3, 2, 4.0, 3, 3]], dtype=xp.float64)
|
| 407 |
+
Z = Z[:nrow, :ncol]
|
| 408 |
+
assert_(is_valid_linkage(Z) == valid)
|
| 409 |
+
if not valid:
|
| 410 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 411 |
+
|
| 412 |
+
def test_is_valid_linkage_int_type(self, xp):
|
| 413 |
+
# Tests is_valid_linkage(Z) with integer type.
|
| 414 |
+
Z = xp.asarray([[0, 1, 3.0, 2],
|
| 415 |
+
[3, 2, 4.0, 3]], dtype=xp.int64)
|
| 416 |
+
assert_(is_valid_linkage(Z) is False)
|
| 417 |
+
assert_raises(TypeError, is_valid_linkage, Z, throw=True)
|
| 418 |
+
|
| 419 |
+
def test_is_valid_linkage_empty(self, xp):
|
| 420 |
+
# Tests is_valid_linkage(Z) with empty linkage.
|
| 421 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 422 |
+
assert_(is_valid_linkage(Z) is False)
|
| 423 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 424 |
+
|
| 425 |
+
def test_is_valid_linkage_4_and_up(self, xp):
|
| 426 |
+
# Tests is_valid_linkage(Z) on linkage on observation sets between
|
| 427 |
+
# sizes 4 and 15 (step size 3).
|
| 428 |
+
for i in range(4, 15, 3):
|
| 429 |
+
y = np.random.rand(i*(i-1)//2)
|
| 430 |
+
y = xp.asarray(y)
|
| 431 |
+
Z = linkage(y)
|
| 432 |
+
assert_(is_valid_linkage(Z) is True)
|
| 433 |
+
|
| 434 |
+
def test_is_valid_linkage_4_and_up_neg_index_left(self, xp):
|
| 435 |
+
# Tests is_valid_linkage(Z) on linkage on observation sets between
|
| 436 |
+
# sizes 4 and 15 (step size 3) with negative indices (left).
|
| 437 |
+
for i in range(4, 15, 3):
|
| 438 |
+
y = np.random.rand(i*(i-1)//2)
|
| 439 |
+
y = xp.asarray(y)
|
| 440 |
+
Z = linkage(y)
|
| 441 |
+
Z[i//2,0] = -2
|
| 442 |
+
assert_(is_valid_linkage(Z) is False)
|
| 443 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 444 |
+
|
| 445 |
+
def test_is_valid_linkage_4_and_up_neg_index_right(self, xp):
|
| 446 |
+
# Tests is_valid_linkage(Z) on linkage on observation sets between
|
| 447 |
+
# sizes 4 and 15 (step size 3) with negative indices (right).
|
| 448 |
+
for i in range(4, 15, 3):
|
| 449 |
+
y = np.random.rand(i*(i-1)//2)
|
| 450 |
+
y = xp.asarray(y)
|
| 451 |
+
Z = linkage(y)
|
| 452 |
+
Z[i//2,1] = -2
|
| 453 |
+
assert_(is_valid_linkage(Z) is False)
|
| 454 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 455 |
+
|
| 456 |
+
def test_is_valid_linkage_4_and_up_neg_dist(self, xp):
|
| 457 |
+
# Tests is_valid_linkage(Z) on linkage on observation sets between
|
| 458 |
+
# sizes 4 and 15 (step size 3) with negative distances.
|
| 459 |
+
for i in range(4, 15, 3):
|
| 460 |
+
y = np.random.rand(i*(i-1)//2)
|
| 461 |
+
y = xp.asarray(y)
|
| 462 |
+
Z = linkage(y)
|
| 463 |
+
Z[i//2,2] = -0.5
|
| 464 |
+
assert_(is_valid_linkage(Z) is False)
|
| 465 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 466 |
+
|
| 467 |
+
def test_is_valid_linkage_4_and_up_neg_counts(self, xp):
|
| 468 |
+
# Tests is_valid_linkage(Z) on linkage on observation sets between
|
| 469 |
+
# sizes 4 and 15 (step size 3) with negative counts.
|
| 470 |
+
for i in range(4, 15, 3):
|
| 471 |
+
y = np.random.rand(i*(i-1)//2)
|
| 472 |
+
y = xp.asarray(y)
|
| 473 |
+
Z = linkage(y)
|
| 474 |
+
Z[i//2,3] = -2
|
| 475 |
+
assert_(is_valid_linkage(Z) is False)
|
| 476 |
+
assert_raises(ValueError, is_valid_linkage, Z, throw=True)
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
@skip_if_array_api(cpu_only=True)
|
| 480 |
+
class TestIsValidInconsistent:
|
| 481 |
+
|
| 482 |
+
def test_is_valid_im_int_type(self, xp):
|
| 483 |
+
# Tests is_valid_im(R) with integer type.
|
| 484 |
+
R = xp.asarray([[0, 1, 3.0, 2],
|
| 485 |
+
[3, 2, 4.0, 3]], dtype=xp.int64)
|
| 486 |
+
assert_(is_valid_im(R) is False)
|
| 487 |
+
assert_raises(TypeError, is_valid_im, R, throw=True)
|
| 488 |
+
|
| 489 |
+
def test_is_valid_im_various_size(self, xp):
|
| 490 |
+
for nrow, ncol, valid in [(2, 5, False), (2, 3, False),
|
| 491 |
+
(1, 4, True), (2, 4, True)]:
|
| 492 |
+
self.check_is_valid_im_various_size(nrow, ncol, valid, xp)
|
| 493 |
+
|
| 494 |
+
def check_is_valid_im_various_size(self, nrow, ncol, valid, xp):
|
| 495 |
+
# Tests is_valid_im(R) with linkage matrices of various sizes
|
| 496 |
+
R = xp.asarray([[0, 1, 3.0, 2, 5],
|
| 497 |
+
[3, 2, 4.0, 3, 3]], dtype=xp.float64)
|
| 498 |
+
R = R[:nrow, :ncol]
|
| 499 |
+
assert_(is_valid_im(R) == valid)
|
| 500 |
+
if not valid:
|
| 501 |
+
assert_raises(ValueError, is_valid_im, R, throw=True)
|
| 502 |
+
|
| 503 |
+
def test_is_valid_im_empty(self, xp):
|
| 504 |
+
# Tests is_valid_im(R) with empty inconsistency matrix.
|
| 505 |
+
R = xp.zeros((0, 4), dtype=xp.float64)
|
| 506 |
+
assert_(is_valid_im(R) is False)
|
| 507 |
+
assert_raises(ValueError, is_valid_im, R, throw=True)
|
| 508 |
+
|
| 509 |
+
def test_is_valid_im_4_and_up(self, xp):
|
| 510 |
+
# Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
|
| 511 |
+
# (step size 3).
|
| 512 |
+
for i in range(4, 15, 3):
|
| 513 |
+
y = np.random.rand(i*(i-1)//2)
|
| 514 |
+
y = xp.asarray(y)
|
| 515 |
+
Z = linkage(y)
|
| 516 |
+
R = inconsistent(Z)
|
| 517 |
+
assert_(is_valid_im(R) is True)
|
| 518 |
+
|
| 519 |
+
def test_is_valid_im_4_and_up_neg_index_left(self, xp):
|
| 520 |
+
# Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
|
| 521 |
+
# (step size 3) with negative link height means.
|
| 522 |
+
for i in range(4, 15, 3):
|
| 523 |
+
y = np.random.rand(i*(i-1)//2)
|
| 524 |
+
y = xp.asarray(y)
|
| 525 |
+
Z = linkage(y)
|
| 526 |
+
R = inconsistent(Z)
|
| 527 |
+
R[i//2,0] = -2.0
|
| 528 |
+
assert_(is_valid_im(R) is False)
|
| 529 |
+
assert_raises(ValueError, is_valid_im, R, throw=True)
|
| 530 |
+
|
| 531 |
+
def test_is_valid_im_4_and_up_neg_index_right(self, xp):
|
| 532 |
+
# Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
|
| 533 |
+
# (step size 3) with negative link height standard deviations.
|
| 534 |
+
for i in range(4, 15, 3):
|
| 535 |
+
y = np.random.rand(i*(i-1)//2)
|
| 536 |
+
y = xp.asarray(y)
|
| 537 |
+
Z = linkage(y)
|
| 538 |
+
R = inconsistent(Z)
|
| 539 |
+
R[i//2,1] = -2.0
|
| 540 |
+
assert_(is_valid_im(R) is False)
|
| 541 |
+
assert_raises(ValueError, is_valid_im, R, throw=True)
|
| 542 |
+
|
| 543 |
+
def test_is_valid_im_4_and_up_neg_dist(self, xp):
|
| 544 |
+
# Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
|
| 545 |
+
# (step size 3) with negative link counts.
|
| 546 |
+
for i in range(4, 15, 3):
|
| 547 |
+
y = np.random.rand(i*(i-1)//2)
|
| 548 |
+
y = xp.asarray(y)
|
| 549 |
+
Z = linkage(y)
|
| 550 |
+
R = inconsistent(Z)
|
| 551 |
+
R[i//2,2] = -0.5
|
| 552 |
+
assert_(is_valid_im(R) is False)
|
| 553 |
+
assert_raises(ValueError, is_valid_im, R, throw=True)
|
| 554 |
+
|
| 555 |
+
|
| 556 |
+
class TestNumObsLinkage:
|
| 557 |
+
|
| 558 |
+
@skip_if_array_api(cpu_only=True)
|
| 559 |
+
def test_num_obs_linkage_empty(self, xp):
|
| 560 |
+
# Tests num_obs_linkage(Z) with empty linkage.
|
| 561 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 562 |
+
assert_raises(ValueError, num_obs_linkage, Z)
|
| 563 |
+
|
| 564 |
+
def test_num_obs_linkage_1x4(self, xp):
|
| 565 |
+
# Tests num_obs_linkage(Z) on linkage over 2 observations.
|
| 566 |
+
Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64)
|
| 567 |
+
assert_equal(num_obs_linkage(Z), 2)
|
| 568 |
+
|
| 569 |
+
def test_num_obs_linkage_2x4(self, xp):
|
| 570 |
+
# Tests num_obs_linkage(Z) on linkage over 3 observations.
|
| 571 |
+
Z = xp.asarray([[0, 1, 3.0, 2],
|
| 572 |
+
[3, 2, 4.0, 3]], dtype=xp.float64)
|
| 573 |
+
assert_equal(num_obs_linkage(Z), 3)
|
| 574 |
+
|
| 575 |
+
@skip_if_array_api(cpu_only=True)
|
| 576 |
+
def test_num_obs_linkage_4_and_up(self, xp):
|
| 577 |
+
# Tests num_obs_linkage(Z) on linkage on observation sets between sizes
|
| 578 |
+
# 4 and 15 (step size 3).
|
| 579 |
+
for i in range(4, 15, 3):
|
| 580 |
+
y = np.random.rand(i*(i-1)//2)
|
| 581 |
+
y = xp.asarray(y)
|
| 582 |
+
Z = linkage(y)
|
| 583 |
+
assert_equal(num_obs_linkage(Z), i)
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
@skip_if_array_api(cpu_only=True)
|
| 587 |
+
class TestLeavesList:
|
| 588 |
+
|
| 589 |
+
def test_leaves_list_1x4(self, xp):
|
| 590 |
+
# Tests leaves_list(Z) on a 1x4 linkage.
|
| 591 |
+
Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64)
|
| 592 |
+
to_tree(Z)
|
| 593 |
+
assert_allclose(leaves_list(Z), [0, 1], rtol=1e-15)
|
| 594 |
+
|
| 595 |
+
def test_leaves_list_2x4(self, xp):
|
| 596 |
+
# Tests leaves_list(Z) on a 2x4 linkage.
|
| 597 |
+
Z = xp.asarray([[0, 1, 3.0, 2],
|
| 598 |
+
[3, 2, 4.0, 3]], dtype=xp.float64)
|
| 599 |
+
to_tree(Z)
|
| 600 |
+
assert_allclose(leaves_list(Z), [0, 1, 2], rtol=1e-15)
|
| 601 |
+
|
| 602 |
+
def test_leaves_list_Q(self, xp):
|
| 603 |
+
for method in ['single', 'complete', 'average', 'weighted', 'centroid',
|
| 604 |
+
'median', 'ward']:
|
| 605 |
+
self.check_leaves_list_Q(method, xp)
|
| 606 |
+
|
| 607 |
+
def check_leaves_list_Q(self, method, xp):
|
| 608 |
+
# Tests leaves_list(Z) on the Q data set
|
| 609 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 610 |
+
Z = linkage(X, method)
|
| 611 |
+
node = to_tree(Z)
|
| 612 |
+
assert_allclose(node.pre_order(), leaves_list(Z), rtol=1e-15)
|
| 613 |
+
|
| 614 |
+
def test_Q_subtree_pre_order(self, xp):
|
| 615 |
+
# Tests that pre_order() works when called on sub-trees.
|
| 616 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 617 |
+
Z = linkage(X, 'single')
|
| 618 |
+
node = to_tree(Z)
|
| 619 |
+
assert_allclose(node.pre_order(), (node.get_left().pre_order()
|
| 620 |
+
+ node.get_right().pre_order()),
|
| 621 |
+
rtol=1e-15)
|
| 622 |
+
|
| 623 |
+
|
| 624 |
+
@skip_if_array_api(cpu_only=True)
|
| 625 |
+
class TestCorrespond:
|
| 626 |
+
|
| 627 |
+
def test_correspond_empty(self, xp):
|
| 628 |
+
# Tests correspond(Z, y) with empty linkage and condensed distance matrix.
|
| 629 |
+
y = xp.zeros((0,), dtype=xp.float64)
|
| 630 |
+
Z = xp.zeros((0,4), dtype=xp.float64)
|
| 631 |
+
assert_raises(ValueError, correspond, Z, y)
|
| 632 |
+
|
| 633 |
+
def test_correspond_2_and_up(self, xp):
|
| 634 |
+
# Tests correspond(Z, y) on linkage and CDMs over observation sets of
|
| 635 |
+
# different sizes.
|
| 636 |
+
for i in range(2, 4):
|
| 637 |
+
y = np.random.rand(i*(i-1)//2)
|
| 638 |
+
y = xp.asarray(y)
|
| 639 |
+
Z = linkage(y)
|
| 640 |
+
assert_(correspond(Z, y))
|
| 641 |
+
for i in range(4, 15, 3):
|
| 642 |
+
y = np.random.rand(i*(i-1)//2)
|
| 643 |
+
y = xp.asarray(y)
|
| 644 |
+
Z = linkage(y)
|
| 645 |
+
assert_(correspond(Z, y))
|
| 646 |
+
|
| 647 |
+
def test_correspond_4_and_up(self, xp):
|
| 648 |
+
# Tests correspond(Z, y) on linkage and CDMs over observation sets of
|
| 649 |
+
# different sizes. Correspondence should be false.
|
| 650 |
+
for (i, j) in (list(zip(list(range(2, 4)), list(range(3, 5)))) +
|
| 651 |
+
list(zip(list(range(3, 5)), list(range(2, 4))))):
|
| 652 |
+
y = np.random.rand(i*(i-1)//2)
|
| 653 |
+
y2 = np.random.rand(j*(j-1)//2)
|
| 654 |
+
y = xp.asarray(y)
|
| 655 |
+
y2 = xp.asarray(y2)
|
| 656 |
+
Z = linkage(y)
|
| 657 |
+
Z2 = linkage(y2)
|
| 658 |
+
assert not correspond(Z, y2)
|
| 659 |
+
assert not correspond(Z2, y)
|
| 660 |
+
|
| 661 |
+
def test_correspond_4_and_up_2(self, xp):
|
| 662 |
+
# Tests correspond(Z, y) on linkage and CDMs over observation sets of
|
| 663 |
+
# different sizes. Correspondence should be false.
|
| 664 |
+
for (i, j) in (list(zip(list(range(2, 7)), list(range(16, 21)))) +
|
| 665 |
+
list(zip(list(range(2, 7)), list(range(16, 21))))):
|
| 666 |
+
y = np.random.rand(i*(i-1)//2)
|
| 667 |
+
y2 = np.random.rand(j*(j-1)//2)
|
| 668 |
+
y = xp.asarray(y)
|
| 669 |
+
y2 = xp.asarray(y2)
|
| 670 |
+
Z = linkage(y)
|
| 671 |
+
Z2 = linkage(y2)
|
| 672 |
+
assert not correspond(Z, y2)
|
| 673 |
+
assert not correspond(Z2, y)
|
| 674 |
+
|
| 675 |
+
def test_num_obs_linkage_multi_matrix(self, xp):
|
| 676 |
+
# Tests num_obs_linkage with observation matrices of multiple sizes.
|
| 677 |
+
for n in range(2, 10):
|
| 678 |
+
X = np.random.rand(n, 4)
|
| 679 |
+
Y = pdist(X)
|
| 680 |
+
Y = xp.asarray(Y)
|
| 681 |
+
Z = linkage(Y)
|
| 682 |
+
assert_equal(num_obs_linkage(Z), n)
|
| 683 |
+
|
| 684 |
+
|
| 685 |
+
@skip_if_array_api(cpu_only=True)
|
| 686 |
+
class TestIsMonotonic:
|
| 687 |
+
|
| 688 |
+
def test_is_monotonic_empty(self, xp):
|
| 689 |
+
# Tests is_monotonic(Z) on an empty linkage.
|
| 690 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 691 |
+
assert_raises(ValueError, is_monotonic, Z)
|
| 692 |
+
|
| 693 |
+
def test_is_monotonic_1x4(self, xp):
|
| 694 |
+
# Tests is_monotonic(Z) on 1x4 linkage. Expecting True.
|
| 695 |
+
Z = xp.asarray([[0, 1, 0.3, 2]], dtype=xp.float64)
|
| 696 |
+
assert is_monotonic(Z)
|
| 697 |
+
|
| 698 |
+
def test_is_monotonic_2x4_T(self, xp):
|
| 699 |
+
# Tests is_monotonic(Z) on 2x4 linkage. Expecting True.
|
| 700 |
+
Z = xp.asarray([[0, 1, 0.3, 2],
|
| 701 |
+
[2, 3, 0.4, 3]], dtype=xp.float64)
|
| 702 |
+
assert is_monotonic(Z)
|
| 703 |
+
|
| 704 |
+
def test_is_monotonic_2x4_F(self, xp):
|
| 705 |
+
# Tests is_monotonic(Z) on 2x4 linkage. Expecting False.
|
| 706 |
+
Z = xp.asarray([[0, 1, 0.4, 2],
|
| 707 |
+
[2, 3, 0.3, 3]], dtype=xp.float64)
|
| 708 |
+
assert not is_monotonic(Z)
|
| 709 |
+
|
| 710 |
+
def test_is_monotonic_3x4_T(self, xp):
|
| 711 |
+
# Tests is_monotonic(Z) on 3x4 linkage. Expecting True.
|
| 712 |
+
Z = xp.asarray([[0, 1, 0.3, 2],
|
| 713 |
+
[2, 3, 0.4, 2],
|
| 714 |
+
[4, 5, 0.6, 4]], dtype=xp.float64)
|
| 715 |
+
assert is_monotonic(Z)
|
| 716 |
+
|
| 717 |
+
def test_is_monotonic_3x4_F1(self, xp):
|
| 718 |
+
# Tests is_monotonic(Z) on 3x4 linkage (case 1). Expecting False.
|
| 719 |
+
Z = xp.asarray([[0, 1, 0.3, 2],
|
| 720 |
+
[2, 3, 0.2, 2],
|
| 721 |
+
[4, 5, 0.6, 4]], dtype=xp.float64)
|
| 722 |
+
assert not is_monotonic(Z)
|
| 723 |
+
|
| 724 |
+
def test_is_monotonic_3x4_F2(self, xp):
|
| 725 |
+
# Tests is_monotonic(Z) on 3x4 linkage (case 2). Expecting False.
|
| 726 |
+
Z = xp.asarray([[0, 1, 0.8, 2],
|
| 727 |
+
[2, 3, 0.4, 2],
|
| 728 |
+
[4, 5, 0.6, 4]], dtype=xp.float64)
|
| 729 |
+
assert not is_monotonic(Z)
|
| 730 |
+
|
| 731 |
+
def test_is_monotonic_3x4_F3(self, xp):
|
| 732 |
+
# Tests is_monotonic(Z) on 3x4 linkage (case 3). Expecting False
|
| 733 |
+
Z = xp.asarray([[0, 1, 0.3, 2],
|
| 734 |
+
[2, 3, 0.4, 2],
|
| 735 |
+
[4, 5, 0.2, 4]], dtype=xp.float64)
|
| 736 |
+
assert not is_monotonic(Z)
|
| 737 |
+
|
| 738 |
+
def test_is_monotonic_tdist_linkage1(self, xp):
|
| 739 |
+
# Tests is_monotonic(Z) on clustering generated by single linkage on
|
| 740 |
+
# tdist data set. Expecting True.
|
| 741 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 742 |
+
assert is_monotonic(Z)
|
| 743 |
+
|
| 744 |
+
def test_is_monotonic_tdist_linkage2(self, xp):
|
| 745 |
+
# Tests is_monotonic(Z) on clustering generated by single linkage on
|
| 746 |
+
# tdist data set. Perturbing. Expecting False.
|
| 747 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 748 |
+
Z[2,2] = 0.0
|
| 749 |
+
assert not is_monotonic(Z)
|
| 750 |
+
|
| 751 |
+
def test_is_monotonic_Q_linkage(self, xp):
|
| 752 |
+
# Tests is_monotonic(Z) on clustering generated by single linkage on
|
| 753 |
+
# Q data set. Expecting True.
|
| 754 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 755 |
+
Z = linkage(X, 'single')
|
| 756 |
+
assert is_monotonic(Z)
|
| 757 |
+
|
| 758 |
+
|
| 759 |
+
@skip_if_array_api(cpu_only=True)
|
| 760 |
+
class TestMaxDists:
|
| 761 |
+
|
| 762 |
+
def test_maxdists_empty_linkage(self, xp):
|
| 763 |
+
# Tests maxdists(Z) on empty linkage. Expecting exception.
|
| 764 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 765 |
+
assert_raises(ValueError, maxdists, Z)
|
| 766 |
+
|
| 767 |
+
def test_maxdists_one_cluster_linkage(self, xp):
|
| 768 |
+
# Tests maxdists(Z) on linkage with one cluster.
|
| 769 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 770 |
+
MD = maxdists(Z)
|
| 771 |
+
expectedMD = calculate_maximum_distances(Z, xp)
|
| 772 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 773 |
+
|
| 774 |
+
def test_maxdists_Q_linkage(self, xp):
|
| 775 |
+
for method in ['single', 'complete', 'ward', 'centroid', 'median']:
|
| 776 |
+
self.check_maxdists_Q_linkage(method, xp)
|
| 777 |
+
|
| 778 |
+
def check_maxdists_Q_linkage(self, method, xp):
|
| 779 |
+
# Tests maxdists(Z) on the Q data set
|
| 780 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 781 |
+
Z = linkage(X, method)
|
| 782 |
+
MD = maxdists(Z)
|
| 783 |
+
expectedMD = calculate_maximum_distances(Z, xp)
|
| 784 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 785 |
+
|
| 786 |
+
|
| 787 |
+
class TestMaxInconsts:
|
| 788 |
+
|
| 789 |
+
@skip_if_array_api(cpu_only=True)
|
| 790 |
+
def test_maxinconsts_empty_linkage(self, xp):
|
| 791 |
+
# Tests maxinconsts(Z, R) on empty linkage. Expecting exception.
|
| 792 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 793 |
+
R = xp.zeros((0, 4), dtype=xp.float64)
|
| 794 |
+
assert_raises(ValueError, maxinconsts, Z, R)
|
| 795 |
+
|
| 796 |
+
def test_maxinconsts_difrow_linkage(self, xp):
|
| 797 |
+
# Tests maxinconsts(Z, R) on linkage and inconsistency matrices with
|
| 798 |
+
# different numbers of clusters. Expecting exception.
|
| 799 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 800 |
+
R = np.random.rand(2, 4)
|
| 801 |
+
R = xp.asarray(R)
|
| 802 |
+
assert_raises(ValueError, maxinconsts, Z, R)
|
| 803 |
+
|
| 804 |
+
@skip_if_array_api(cpu_only=True)
|
| 805 |
+
def test_maxinconsts_one_cluster_linkage(self, xp):
|
| 806 |
+
# Tests maxinconsts(Z, R) on linkage with one cluster.
|
| 807 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 808 |
+
R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
|
| 809 |
+
MD = maxinconsts(Z, R)
|
| 810 |
+
expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp)
|
| 811 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 812 |
+
|
| 813 |
+
@skip_if_array_api(cpu_only=True)
|
| 814 |
+
def test_maxinconsts_Q_linkage(self, xp):
|
| 815 |
+
for method in ['single', 'complete', 'ward', 'centroid', 'median']:
|
| 816 |
+
self.check_maxinconsts_Q_linkage(method, xp)
|
| 817 |
+
|
| 818 |
+
def check_maxinconsts_Q_linkage(self, method, xp):
|
| 819 |
+
# Tests maxinconsts(Z, R) on the Q data set
|
| 820 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 821 |
+
Z = linkage(X, method)
|
| 822 |
+
R = inconsistent(Z)
|
| 823 |
+
MD = maxinconsts(Z, R)
|
| 824 |
+
expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp)
|
| 825 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 826 |
+
|
| 827 |
+
|
| 828 |
+
class TestMaxRStat:
|
| 829 |
+
|
| 830 |
+
def test_maxRstat_invalid_index(self, xp):
|
| 831 |
+
for i in [3.3, -1, 4]:
|
| 832 |
+
self.check_maxRstat_invalid_index(i, xp)
|
| 833 |
+
|
| 834 |
+
def check_maxRstat_invalid_index(self, i, xp):
|
| 835 |
+
# Tests maxRstat(Z, R, i). Expecting exception.
|
| 836 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 837 |
+
R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
|
| 838 |
+
if isinstance(i, int):
|
| 839 |
+
assert_raises(ValueError, maxRstat, Z, R, i)
|
| 840 |
+
else:
|
| 841 |
+
assert_raises(TypeError, maxRstat, Z, R, i)
|
| 842 |
+
|
| 843 |
+
@skip_if_array_api(cpu_only=True)
|
| 844 |
+
def test_maxRstat_empty_linkage(self, xp):
|
| 845 |
+
for i in range(4):
|
| 846 |
+
self.check_maxRstat_empty_linkage(i, xp)
|
| 847 |
+
|
| 848 |
+
def check_maxRstat_empty_linkage(self, i, xp):
|
| 849 |
+
# Tests maxRstat(Z, R, i) on empty linkage. Expecting exception.
|
| 850 |
+
Z = xp.zeros((0, 4), dtype=xp.float64)
|
| 851 |
+
R = xp.zeros((0, 4), dtype=xp.float64)
|
| 852 |
+
assert_raises(ValueError, maxRstat, Z, R, i)
|
| 853 |
+
|
| 854 |
+
def test_maxRstat_difrow_linkage(self, xp):
|
| 855 |
+
for i in range(4):
|
| 856 |
+
self.check_maxRstat_difrow_linkage(i, xp)
|
| 857 |
+
|
| 858 |
+
def check_maxRstat_difrow_linkage(self, i, xp):
|
| 859 |
+
# Tests maxRstat(Z, R, i) on linkage and inconsistency matrices with
|
| 860 |
+
# different numbers of clusters. Expecting exception.
|
| 861 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 862 |
+
R = np.random.rand(2, 4)
|
| 863 |
+
R = xp.asarray(R)
|
| 864 |
+
assert_raises(ValueError, maxRstat, Z, R, i)
|
| 865 |
+
|
| 866 |
+
@skip_if_array_api(cpu_only=True)
|
| 867 |
+
def test_maxRstat_one_cluster_linkage(self, xp):
|
| 868 |
+
for i in range(4):
|
| 869 |
+
self.check_maxRstat_one_cluster_linkage(i, xp)
|
| 870 |
+
|
| 871 |
+
def check_maxRstat_one_cluster_linkage(self, i, xp):
|
| 872 |
+
# Tests maxRstat(Z, R, i) on linkage with one cluster.
|
| 873 |
+
Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
|
| 874 |
+
R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
|
| 875 |
+
MD = maxRstat(Z, R, 1)
|
| 876 |
+
expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp)
|
| 877 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 878 |
+
|
| 879 |
+
@skip_if_array_api(cpu_only=True)
|
| 880 |
+
def test_maxRstat_Q_linkage(self, xp):
|
| 881 |
+
for method in ['single', 'complete', 'ward', 'centroid', 'median']:
|
| 882 |
+
for i in range(4):
|
| 883 |
+
self.check_maxRstat_Q_linkage(method, i, xp)
|
| 884 |
+
|
| 885 |
+
def check_maxRstat_Q_linkage(self, method, i, xp):
|
| 886 |
+
# Tests maxRstat(Z, R, i) on the Q data set
|
| 887 |
+
X = xp.asarray(hierarchy_test_data.Q_X)
|
| 888 |
+
Z = linkage(X, method)
|
| 889 |
+
R = inconsistent(Z)
|
| 890 |
+
MD = maxRstat(Z, R, 1)
|
| 891 |
+
expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp)
|
| 892 |
+
xp_assert_close(MD, expectedMD, atol=1e-15)
|
| 893 |
+
|
| 894 |
+
|
| 895 |
+
@skip_if_array_api(cpu_only=True)
|
| 896 |
+
class TestDendrogram:
|
| 897 |
+
|
| 898 |
+
def test_dendrogram_single_linkage_tdist(self, xp):
|
| 899 |
+
# Tests dendrogram calculation on single linkage of the tdist data set.
|
| 900 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 901 |
+
R = dendrogram(Z, no_plot=True)
|
| 902 |
+
leaves = R["leaves"]
|
| 903 |
+
assert_equal(leaves, [2, 5, 1, 0, 3, 4])
|
| 904 |
+
|
| 905 |
+
def test_valid_orientation(self, xp):
|
| 906 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 907 |
+
assert_raises(ValueError, dendrogram, Z, orientation="foo")
|
| 908 |
+
|
| 909 |
+
def test_labels_as_array_or_list(self, xp):
|
| 910 |
+
# test for gh-12418
|
| 911 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 912 |
+
labels = xp.asarray([1, 3, 2, 6, 4, 5])
|
| 913 |
+
result1 = dendrogram(Z, labels=labels, no_plot=True)
|
| 914 |
+
result2 = dendrogram(Z, labels=list(labels), no_plot=True)
|
| 915 |
+
assert result1 == result2
|
| 916 |
+
|
| 917 |
+
@pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
|
| 918 |
+
def test_valid_label_size(self, xp):
|
| 919 |
+
link = xp.asarray([
|
| 920 |
+
[0, 1, 1.0, 4],
|
| 921 |
+
[2, 3, 1.0, 5],
|
| 922 |
+
[4, 5, 2.0, 6],
|
| 923 |
+
])
|
| 924 |
+
plt.figure()
|
| 925 |
+
with pytest.raises(ValueError) as exc_info:
|
| 926 |
+
dendrogram(link, labels=list(range(100)))
|
| 927 |
+
assert "Dimensions of Z and labels must be consistent."\
|
| 928 |
+
in str(exc_info.value)
|
| 929 |
+
|
| 930 |
+
with pytest.raises(
|
| 931 |
+
ValueError,
|
| 932 |
+
match="Dimensions of Z and labels must be consistent."):
|
| 933 |
+
dendrogram(link, labels=[])
|
| 934 |
+
|
| 935 |
+
plt.close()
|
| 936 |
+
|
| 937 |
+
@pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
|
| 938 |
+
def test_dendrogram_plot(self, xp):
|
| 939 |
+
for orientation in ['top', 'bottom', 'left', 'right']:
|
| 940 |
+
self.check_dendrogram_plot(orientation, xp)
|
| 941 |
+
|
| 942 |
+
def check_dendrogram_plot(self, orientation, xp):
|
| 943 |
+
# Tests dendrogram plotting.
|
| 944 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 945 |
+
expected = {'color_list': ['C1', 'C0', 'C0', 'C0', 'C0'],
|
| 946 |
+
'dcoord': [[0.0, 138.0, 138.0, 0.0],
|
| 947 |
+
[0.0, 219.0, 219.0, 0.0],
|
| 948 |
+
[0.0, 255.0, 255.0, 219.0],
|
| 949 |
+
[0.0, 268.0, 268.0, 255.0],
|
| 950 |
+
[138.0, 295.0, 295.0, 268.0]],
|
| 951 |
+
'icoord': [[5.0, 5.0, 15.0, 15.0],
|
| 952 |
+
[45.0, 45.0, 55.0, 55.0],
|
| 953 |
+
[35.0, 35.0, 50.0, 50.0],
|
| 954 |
+
[25.0, 25.0, 42.5, 42.5],
|
| 955 |
+
[10.0, 10.0, 33.75, 33.75]],
|
| 956 |
+
'ivl': ['2', '5', '1', '0', '3', '4'],
|
| 957 |
+
'leaves': [2, 5, 1, 0, 3, 4],
|
| 958 |
+
'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0', 'C0'],
|
| 959 |
+
}
|
| 960 |
+
|
| 961 |
+
fig = plt.figure()
|
| 962 |
+
ax = fig.add_subplot(221)
|
| 963 |
+
|
| 964 |
+
# test that dendrogram accepts ax keyword
|
| 965 |
+
R1 = dendrogram(Z, ax=ax, orientation=orientation)
|
| 966 |
+
R1['dcoord'] = np.asarray(R1['dcoord'])
|
| 967 |
+
assert_equal(R1, expected)
|
| 968 |
+
|
| 969 |
+
# test that dendrogram accepts and handle the leaf_font_size and
|
| 970 |
+
# leaf_rotation keywords
|
| 971 |
+
dendrogram(Z, ax=ax, orientation=orientation,
|
| 972 |
+
leaf_font_size=20, leaf_rotation=90)
|
| 973 |
+
testlabel = (
|
| 974 |
+
ax.get_xticklabels()[0]
|
| 975 |
+
if orientation in ['top', 'bottom']
|
| 976 |
+
else ax.get_yticklabels()[0]
|
| 977 |
+
)
|
| 978 |
+
assert_equal(testlabel.get_rotation(), 90)
|
| 979 |
+
assert_equal(testlabel.get_size(), 20)
|
| 980 |
+
dendrogram(Z, ax=ax, orientation=orientation,
|
| 981 |
+
leaf_rotation=90)
|
| 982 |
+
testlabel = (
|
| 983 |
+
ax.get_xticklabels()[0]
|
| 984 |
+
if orientation in ['top', 'bottom']
|
| 985 |
+
else ax.get_yticklabels()[0]
|
| 986 |
+
)
|
| 987 |
+
assert_equal(testlabel.get_rotation(), 90)
|
| 988 |
+
dendrogram(Z, ax=ax, orientation=orientation,
|
| 989 |
+
leaf_font_size=20)
|
| 990 |
+
testlabel = (
|
| 991 |
+
ax.get_xticklabels()[0]
|
| 992 |
+
if orientation in ['top', 'bottom']
|
| 993 |
+
else ax.get_yticklabels()[0]
|
| 994 |
+
)
|
| 995 |
+
assert_equal(testlabel.get_size(), 20)
|
| 996 |
+
plt.close()
|
| 997 |
+
|
| 998 |
+
# test plotting to gca (will import pylab)
|
| 999 |
+
R2 = dendrogram(Z, orientation=orientation)
|
| 1000 |
+
plt.close()
|
| 1001 |
+
R2['dcoord'] = np.asarray(R2['dcoord'])
|
| 1002 |
+
assert_equal(R2, expected)
|
| 1003 |
+
|
| 1004 |
+
@pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
|
| 1005 |
+
def test_dendrogram_truncate_mode(self, xp):
|
| 1006 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 1007 |
+
|
| 1008 |
+
R = dendrogram(Z, 2, 'lastp', show_contracted=True)
|
| 1009 |
+
plt.close()
|
| 1010 |
+
R['dcoord'] = np.asarray(R['dcoord'])
|
| 1011 |
+
assert_equal(R, {'color_list': ['C0'],
|
| 1012 |
+
'dcoord': [[0.0, 295.0, 295.0, 0.0]],
|
| 1013 |
+
'icoord': [[5.0, 5.0, 15.0, 15.0]],
|
| 1014 |
+
'ivl': ['(2)', '(4)'],
|
| 1015 |
+
'leaves': [6, 9],
|
| 1016 |
+
'leaves_color_list': ['C0', 'C0'],
|
| 1017 |
+
})
|
| 1018 |
+
|
| 1019 |
+
R = dendrogram(Z, 2, 'mtica', show_contracted=True)
|
| 1020 |
+
plt.close()
|
| 1021 |
+
R['dcoord'] = np.asarray(R['dcoord'])
|
| 1022 |
+
assert_equal(R, {'color_list': ['C1', 'C0', 'C0', 'C0'],
|
| 1023 |
+
'dcoord': [[0.0, 138.0, 138.0, 0.0],
|
| 1024 |
+
[0.0, 255.0, 255.0, 0.0],
|
| 1025 |
+
[0.0, 268.0, 268.0, 255.0],
|
| 1026 |
+
[138.0, 295.0, 295.0, 268.0]],
|
| 1027 |
+
'icoord': [[5.0, 5.0, 15.0, 15.0],
|
| 1028 |
+
[35.0, 35.0, 45.0, 45.0],
|
| 1029 |
+
[25.0, 25.0, 40.0, 40.0],
|
| 1030 |
+
[10.0, 10.0, 32.5, 32.5]],
|
| 1031 |
+
'ivl': ['2', '5', '1', '0', '(2)'],
|
| 1032 |
+
'leaves': [2, 5, 1, 0, 7],
|
| 1033 |
+
'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0'],
|
| 1034 |
+
})
|
| 1035 |
+
|
| 1036 |
+
def test_dendrogram_colors(self, xp):
|
| 1037 |
+
# Tests dendrogram plots with alternate colors
|
| 1038 |
+
Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
|
| 1039 |
+
|
| 1040 |
+
set_link_color_palette(['c', 'm', 'y', 'k'])
|
| 1041 |
+
R = dendrogram(Z, no_plot=True,
|
| 1042 |
+
above_threshold_color='g', color_threshold=250)
|
| 1043 |
+
set_link_color_palette(['g', 'r', 'c', 'm', 'y', 'k'])
|
| 1044 |
+
|
| 1045 |
+
color_list = R['color_list']
|
| 1046 |
+
assert_equal(color_list, ['c', 'm', 'g', 'g', 'g'])
|
| 1047 |
+
|
| 1048 |
+
# reset color palette (global list)
|
| 1049 |
+
set_link_color_palette(None)
|
| 1050 |
+
|
| 1051 |
+
def test_dendrogram_leaf_colors_zero_dist(self, xp):
|
| 1052 |
+
# tests that the colors of leafs are correct for tree
|
| 1053 |
+
# with two identical points
|
| 1054 |
+
x = xp.asarray([[1, 0, 0],
|
| 1055 |
+
[0, 0, 1],
|
| 1056 |
+
[0, 2, 0],
|
| 1057 |
+
[0, 0, 1],
|
| 1058 |
+
[0, 1, 0],
|
| 1059 |
+
[0, 1, 0]])
|
| 1060 |
+
z = linkage(x, "single")
|
| 1061 |
+
d = dendrogram(z, no_plot=True)
|
| 1062 |
+
exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2']
|
| 1063 |
+
colors = d["leaves_color_list"]
|
| 1064 |
+
assert_equal(colors, exp_colors)
|
| 1065 |
+
|
| 1066 |
+
def test_dendrogram_leaf_colors(self, xp):
|
| 1067 |
+
# tests that the colors are correct for a tree
|
| 1068 |
+
# with two near points ((0, 0, 1.1) and (0, 0, 1))
|
| 1069 |
+
x = xp.asarray([[1, 0, 0],
|
| 1070 |
+
[0, 0, 1.1],
|
| 1071 |
+
[0, 2, 0],
|
| 1072 |
+
[0, 0, 1],
|
| 1073 |
+
[0, 1, 0],
|
| 1074 |
+
[0, 1, 0]])
|
| 1075 |
+
z = linkage(x, "single")
|
| 1076 |
+
d = dendrogram(z, no_plot=True)
|
| 1077 |
+
exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2']
|
| 1078 |
+
colors = d["leaves_color_list"]
|
| 1079 |
+
assert_equal(colors, exp_colors)
|
| 1080 |
+
|
| 1081 |
+
|
| 1082 |
+
def calculate_maximum_distances(Z, xp):
|
| 1083 |
+
# Used for testing correctness of maxdists.
|
| 1084 |
+
n = Z.shape[0] + 1
|
| 1085 |
+
B = xp.zeros((n-1,), dtype=Z.dtype)
|
| 1086 |
+
q = xp.zeros((3,))
|
| 1087 |
+
for i in range(0, n - 1):
|
| 1088 |
+
q[:] = 0.0
|
| 1089 |
+
left = Z[i, 0]
|
| 1090 |
+
right = Z[i, 1]
|
| 1091 |
+
if left >= n:
|
| 1092 |
+
q[0] = B[xp.asarray(left, dtype=xp.int64) - n]
|
| 1093 |
+
if right >= n:
|
| 1094 |
+
q[1] = B[xp.asarray(right, dtype=xp.int64) - n]
|
| 1095 |
+
q[2] = Z[i, 2]
|
| 1096 |
+
B[i] = xp.max(q)
|
| 1097 |
+
return B
|
| 1098 |
+
|
| 1099 |
+
|
| 1100 |
+
def calculate_maximum_inconsistencies(Z, R, k=3, xp=np):
|
| 1101 |
+
# Used for testing correctness of maxinconsts.
|
| 1102 |
+
n = Z.shape[0] + 1
|
| 1103 |
+
dtype = xp.result_type(Z, R)
|
| 1104 |
+
B = xp.zeros((n-1,), dtype=dtype)
|
| 1105 |
+
q = xp.zeros((3,))
|
| 1106 |
+
for i in range(0, n - 1):
|
| 1107 |
+
q[:] = 0.0
|
| 1108 |
+
left = Z[i, 0]
|
| 1109 |
+
right = Z[i, 1]
|
| 1110 |
+
if left >= n:
|
| 1111 |
+
q[0] = B[xp.asarray(left, dtype=xp.int64) - n]
|
| 1112 |
+
if right >= n:
|
| 1113 |
+
q[1] = B[xp.asarray(right, dtype=xp.int64) - n]
|
| 1114 |
+
q[2] = R[i, k]
|
| 1115 |
+
B[i] = xp.max(q)
|
| 1116 |
+
return B
|
| 1117 |
+
|
| 1118 |
+
|
| 1119 |
+
@skip_if_array_api(cpu_only=True)
|
| 1120 |
+
def test_unsupported_uncondensed_distance_matrix_linkage_warning(xp):
|
| 1121 |
+
assert_warns(ClusterWarning, linkage, xp.asarray([[0, 1], [1, 0]]))
|
| 1122 |
+
|
| 1123 |
+
|
| 1124 |
+
def test_euclidean_linkage_value_error(xp):
|
| 1125 |
+
for method in scipy.cluster.hierarchy._EUCLIDEAN_METHODS:
|
| 1126 |
+
assert_raises(ValueError, linkage, xp.asarray([[1, 1], [1, 1]]),
|
| 1127 |
+
method=method, metric='cityblock')
|
| 1128 |
+
|
| 1129 |
+
|
| 1130 |
+
@skip_if_array_api(cpu_only=True)
|
| 1131 |
+
def test_2x2_linkage(xp):
|
| 1132 |
+
Z1 = linkage(xp.asarray([1]), method='single', metric='euclidean')
|
| 1133 |
+
Z2 = linkage(xp.asarray([[0, 1], [0, 0]]), method='single', metric='euclidean')
|
| 1134 |
+
xp_assert_close(Z1, Z2, rtol=1e-15)
|
| 1135 |
+
|
| 1136 |
+
|
| 1137 |
+
@skip_if_array_api(cpu_only=True)
|
| 1138 |
+
def test_node_compare(xp):
|
| 1139 |
+
np.random.seed(23)
|
| 1140 |
+
nobs = 50
|
| 1141 |
+
X = np.random.randn(nobs, 4)
|
| 1142 |
+
X = xp.asarray(X)
|
| 1143 |
+
Z = scipy.cluster.hierarchy.ward(X)
|
| 1144 |
+
tree = to_tree(Z)
|
| 1145 |
+
assert_(tree > tree.get_left())
|
| 1146 |
+
assert_(tree.get_right() > tree.get_left())
|
| 1147 |
+
assert_(tree.get_right() == tree.get_right())
|
| 1148 |
+
assert_(tree.get_right() != tree.get_left())
|
| 1149 |
+
|
| 1150 |
+
|
| 1151 |
+
@skip_if_array_api(np_only=True, reasons=['`cut_tree` uses non-standard indexing'])
|
| 1152 |
+
def test_cut_tree(xp):
|
| 1153 |
+
np.random.seed(23)
|
| 1154 |
+
nobs = 50
|
| 1155 |
+
X = np.random.randn(nobs, 4)
|
| 1156 |
+
X = xp.asarray(X)
|
| 1157 |
+
Z = scipy.cluster.hierarchy.ward(X)
|
| 1158 |
+
cutree = cut_tree(Z)
|
| 1159 |
+
|
| 1160 |
+
# cutree.dtype varies between int32 and int64 over platforms
|
| 1161 |
+
xp_assert_close(cutree[:, 0], xp.arange(nobs), rtol=1e-15, check_dtype=False)
|
| 1162 |
+
xp_assert_close(cutree[:, -1], xp.zeros(nobs), rtol=1e-15, check_dtype=False)
|
| 1163 |
+
assert_equal(np.asarray(cutree).max(0), np.arange(nobs - 1, -1, -1))
|
| 1164 |
+
|
| 1165 |
+
xp_assert_close(cutree[:, [-5]], cut_tree(Z, n_clusters=5), rtol=1e-15)
|
| 1166 |
+
xp_assert_close(cutree[:, [-5, -10]], cut_tree(Z, n_clusters=[5, 10]), rtol=1e-15)
|
| 1167 |
+
xp_assert_close(cutree[:, [-10, -5]], cut_tree(Z, n_clusters=[10, 5]), rtol=1e-15)
|
| 1168 |
+
|
| 1169 |
+
nodes = _order_cluster_tree(Z)
|
| 1170 |
+
heights = xp.asarray([node.dist for node in nodes])
|
| 1171 |
+
|
| 1172 |
+
xp_assert_close(cutree[:, np.searchsorted(heights, [5])],
|
| 1173 |
+
cut_tree(Z, height=5), rtol=1e-15)
|
| 1174 |
+
xp_assert_close(cutree[:, np.searchsorted(heights, [5, 10])],
|
| 1175 |
+
cut_tree(Z, height=[5, 10]), rtol=1e-15)
|
| 1176 |
+
xp_assert_close(cutree[:, np.searchsorted(heights, [10, 5])],
|
| 1177 |
+
cut_tree(Z, height=[10, 5]), rtol=1e-15)
|
| 1178 |
+
|
| 1179 |
+
|
| 1180 |
+
@skip_if_array_api(cpu_only=True)
|
| 1181 |
+
def test_optimal_leaf_ordering(xp):
|
| 1182 |
+
# test with the distance vector y
|
| 1183 |
+
Z = optimal_leaf_ordering(linkage(xp.asarray(hierarchy_test_data.ytdist)),
|
| 1184 |
+
xp.asarray(hierarchy_test_data.ytdist))
|
| 1185 |
+
expectedZ = hierarchy_test_data.linkage_ytdist_single_olo
|
| 1186 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
|
| 1187 |
+
|
| 1188 |
+
# test with the observation matrix X
|
| 1189 |
+
Z = optimal_leaf_ordering(linkage(xp.asarray(hierarchy_test_data.X), 'ward'),
|
| 1190 |
+
xp.asarray(hierarchy_test_data.X))
|
| 1191 |
+
expectedZ = hierarchy_test_data.linkage_X_ward_olo
|
| 1192 |
+
xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
|
| 1193 |
+
|
| 1194 |
+
|
| 1195 |
+
@skip_if_array_api(np_only=True, reasons=['`Heap` only supports NumPy backend'])
|
| 1196 |
+
def test_Heap(xp):
|
| 1197 |
+
values = xp.asarray([2, -1, 0, -1.5, 3])
|
| 1198 |
+
heap = Heap(values)
|
| 1199 |
+
|
| 1200 |
+
pair = heap.get_min()
|
| 1201 |
+
assert_equal(pair['key'], 3)
|
| 1202 |
+
assert_equal(pair['value'], -1.5)
|
| 1203 |
+
|
| 1204 |
+
heap.remove_min()
|
| 1205 |
+
pair = heap.get_min()
|
| 1206 |
+
assert_equal(pair['key'], 1)
|
| 1207 |
+
assert_equal(pair['value'], -1)
|
| 1208 |
+
|
| 1209 |
+
heap.change_value(1, 2.5)
|
| 1210 |
+
pair = heap.get_min()
|
| 1211 |
+
assert_equal(pair['key'], 2)
|
| 1212 |
+
assert_equal(pair['value'], 0)
|
| 1213 |
+
|
| 1214 |
+
heap.remove_min()
|
| 1215 |
+
heap.remove_min()
|
| 1216 |
+
|
| 1217 |
+
heap.change_value(1, 10)
|
| 1218 |
+
pair = heap.get_min()
|
| 1219 |
+
assert_equal(pair['key'], 4)
|
| 1220 |
+
assert_equal(pair['value'], 3)
|
| 1221 |
+
|
| 1222 |
+
heap.remove_min()
|
| 1223 |
+
pair = heap.get_min()
|
| 1224 |
+
assert_equal(pair['key'], 1)
|
| 1225 |
+
assert_equal(pair['value'], 10)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_vq.py
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
import sys
|
| 3 |
+
from copy import deepcopy
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
from numpy.testing import (
|
| 7 |
+
assert_array_equal, assert_equal, assert_, suppress_warnings
|
| 8 |
+
)
|
| 9 |
+
import pytest
|
| 10 |
+
from pytest import raises as assert_raises
|
| 11 |
+
|
| 12 |
+
from scipy.cluster.vq import (kmeans, kmeans2, py_vq, vq, whiten,
|
| 13 |
+
ClusterError, _krandinit)
|
| 14 |
+
from scipy.cluster import _vq
|
| 15 |
+
from scipy.conftest import array_api_compatible
|
| 16 |
+
from scipy.sparse._sputils import matrix
|
| 17 |
+
|
| 18 |
+
from scipy._lib._array_api import (
|
| 19 |
+
SCIPY_ARRAY_API, copy, cov, xp_assert_close, xp_assert_equal
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_if_array_api")]
|
| 23 |
+
skip_if_array_api = pytest.mark.skip_if_array_api
|
| 24 |
+
|
| 25 |
+
TESTDATA_2D = np.array([
|
| 26 |
+
-2.2, 1.17, -1.63, 1.69, -2.04, 4.38, -3.09, 0.95, -1.7, 4.79, -1.68, 0.68,
|
| 27 |
+
-2.26, 3.34, -2.29, 2.55, -1.72, -0.72, -1.99, 2.34, -2.75, 3.43, -2.45,
|
| 28 |
+
2.41, -4.26, 3.65, -1.57, 1.87, -1.96, 4.03, -3.01, 3.86, -2.53, 1.28,
|
| 29 |
+
-4.0, 3.95, -1.62, 1.25, -3.42, 3.17, -1.17, 0.12, -3.03, -0.27, -2.07,
|
| 30 |
+
-0.55, -1.17, 1.34, -2.82, 3.08, -2.44, 0.24, -1.71, 2.48, -5.23, 4.29,
|
| 31 |
+
-2.08, 3.69, -1.89, 3.62, -2.09, 0.26, -0.92, 1.07, -2.25, 0.88, -2.25,
|
| 32 |
+
2.02, -4.31, 3.86, -2.03, 3.42, -2.76, 0.3, -2.48, -0.29, -3.42, 3.21,
|
| 33 |
+
-2.3, 1.73, -2.84, 0.69, -1.81, 2.48, -5.24, 4.52, -2.8, 1.31, -1.67,
|
| 34 |
+
-2.34, -1.18, 2.17, -2.17, 2.82, -1.85, 2.25, -2.45, 1.86, -6.79, 3.94,
|
| 35 |
+
-2.33, 1.89, -1.55, 2.08, -1.36, 0.93, -2.51, 2.74, -2.39, 3.92, -3.33,
|
| 36 |
+
2.99, -2.06, -0.9, -2.83, 3.35, -2.59, 3.05, -2.36, 1.85, -1.69, 1.8,
|
| 37 |
+
-1.39, 0.66, -2.06, 0.38, -1.47, 0.44, -4.68, 3.77, -5.58, 3.44, -2.29,
|
| 38 |
+
2.24, -1.04, -0.38, -1.85, 4.23, -2.88, 0.73, -2.59, 1.39, -1.34, 1.75,
|
| 39 |
+
-1.95, 1.3, -2.45, 3.09, -1.99, 3.41, -5.55, 5.21, -1.73, 2.52, -2.17,
|
| 40 |
+
0.85, -2.06, 0.49, -2.54, 2.07, -2.03, 1.3, -3.23, 3.09, -1.55, 1.44,
|
| 41 |
+
-0.81, 1.1, -2.99, 2.92, -1.59, 2.18, -2.45, -0.73, -3.12, -1.3, -2.83,
|
| 42 |
+
0.2, -2.77, 3.24, -1.98, 1.6, -4.59, 3.39, -4.85, 3.75, -2.25, 1.71, -3.28,
|
| 43 |
+
3.38, -1.74, 0.88, -2.41, 1.92, -2.24, 1.19, -2.48, 1.06, -1.68, -0.62,
|
| 44 |
+
-1.3, 0.39, -1.78, 2.35, -3.54, 2.44, -1.32, 0.66, -2.38, 2.76, -2.35,
|
| 45 |
+
3.95, -1.86, 4.32, -2.01, -1.23, -1.79, 2.76, -2.13, -0.13, -5.25, 3.84,
|
| 46 |
+
-2.24, 1.59, -4.85, 2.96, -2.41, 0.01, -0.43, 0.13, -3.92, 2.91, -1.75,
|
| 47 |
+
-0.53, -1.69, 1.69, -1.09, 0.15, -2.11, 2.17, -1.53, 1.22, -2.1, -0.86,
|
| 48 |
+
-2.56, 2.28, -3.02, 3.33, -1.12, 3.86, -2.18, -1.19, -3.03, 0.79, -0.83,
|
| 49 |
+
0.97, -3.19, 1.45, -1.34, 1.28, -2.52, 4.22, -4.53, 3.22, -1.97, 1.75,
|
| 50 |
+
-2.36, 3.19, -0.83, 1.53, -1.59, 1.86, -2.17, 2.3, -1.63, 2.71, -2.03,
|
| 51 |
+
3.75, -2.57, -0.6, -1.47, 1.33, -1.95, 0.7, -1.65, 1.27, -1.42, 1.09, -3.0,
|
| 52 |
+
3.87, -2.51, 3.06, -2.6, 0.74, -1.08, -0.03, -2.44, 1.31, -2.65, 2.99,
|
| 53 |
+
-1.84, 1.65, -4.76, 3.75, -2.07, 3.98, -2.4, 2.67, -2.21, 1.49, -1.21,
|
| 54 |
+
1.22, -5.29, 2.38, -2.85, 2.28, -5.6, 3.78, -2.7, 0.8, -1.81, 3.5, -3.75,
|
| 55 |
+
4.17, -1.29, 2.99, -5.92, 3.43, -1.83, 1.23, -1.24, -1.04, -2.56, 2.37,
|
| 56 |
+
-3.26, 0.39, -4.63, 2.51, -4.52, 3.04, -1.7, 0.36, -1.41, 0.04, -2.1, 1.0,
|
| 57 |
+
-1.87, 3.78, -4.32, 3.59, -2.24, 1.38, -1.99, -0.22, -1.87, 1.95, -0.84,
|
| 58 |
+
2.17, -5.38, 3.56, -1.27, 2.9, -1.79, 3.31, -5.47, 3.85, -1.44, 3.69,
|
| 59 |
+
-2.02, 0.37, -1.29, 0.33, -2.34, 2.56, -1.74, -1.27, -1.97, 1.22, -2.51,
|
| 60 |
+
-0.16, -1.64, -0.96, -2.99, 1.4, -1.53, 3.31, -2.24, 0.45, -2.46, 1.71,
|
| 61 |
+
-2.88, 1.56, -1.63, 1.46, -1.41, 0.68, -1.96, 2.76, -1.61,
|
| 62 |
+
2.11]).reshape((200, 2))
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
# Global data
|
| 66 |
+
X = np.array([[3.0, 3], [4, 3], [4, 2],
|
| 67 |
+
[9, 2], [5, 1], [6, 2], [9, 4],
|
| 68 |
+
[5, 2], [5, 4], [7, 4], [6, 5]])
|
| 69 |
+
|
| 70 |
+
CODET1 = np.array([[3.0000, 3.0000],
|
| 71 |
+
[6.2000, 4.0000],
|
| 72 |
+
[5.8000, 1.8000]])
|
| 73 |
+
|
| 74 |
+
CODET2 = np.array([[11.0/3, 8.0/3],
|
| 75 |
+
[6.7500, 4.2500],
|
| 76 |
+
[6.2500, 1.7500]])
|
| 77 |
+
|
| 78 |
+
LABEL1 = np.array([0, 1, 2, 2, 2, 2, 1, 2, 1, 1, 1])
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
class TestWhiten:
|
| 82 |
+
|
| 83 |
+
def test_whiten(self, xp):
|
| 84 |
+
desired = xp.asarray([[5.08738849, 2.97091878],
|
| 85 |
+
[3.19909255, 0.69660580],
|
| 86 |
+
[4.51041982, 0.02640918],
|
| 87 |
+
[4.38567074, 0.95120889],
|
| 88 |
+
[2.32191480, 1.63195503]])
|
| 89 |
+
|
| 90 |
+
obs = xp.asarray([[0.98744510, 0.82766775],
|
| 91 |
+
[0.62093317, 0.19406729],
|
| 92 |
+
[0.87545741, 0.00735733],
|
| 93 |
+
[0.85124403, 0.26499712],
|
| 94 |
+
[0.45067590, 0.45464607]])
|
| 95 |
+
xp_assert_close(whiten(obs), desired, rtol=1e-5)
|
| 96 |
+
|
| 97 |
+
def test_whiten_zero_std(self, xp):
|
| 98 |
+
desired = xp.asarray([[0., 1.0, 2.86666544],
|
| 99 |
+
[0., 1.0, 1.32460034],
|
| 100 |
+
[0., 1.0, 3.74382172]])
|
| 101 |
+
|
| 102 |
+
obs = xp.asarray([[0., 1., 0.74109533],
|
| 103 |
+
[0., 1., 0.34243798],
|
| 104 |
+
[0., 1., 0.96785929]])
|
| 105 |
+
with warnings.catch_warnings(record=True) as w:
|
| 106 |
+
warnings.simplefilter('always')
|
| 107 |
+
|
| 108 |
+
xp_assert_close(whiten(obs), desired, rtol=1e-5)
|
| 109 |
+
|
| 110 |
+
assert_equal(len(w), 1)
|
| 111 |
+
assert_(issubclass(w[-1].category, RuntimeWarning))
|
| 112 |
+
|
| 113 |
+
def test_whiten_not_finite(self, xp):
|
| 114 |
+
for bad_value in xp.nan, xp.inf, -xp.inf:
|
| 115 |
+
obs = xp.asarray([[0.98744510, bad_value],
|
| 116 |
+
[0.62093317, 0.19406729],
|
| 117 |
+
[0.87545741, 0.00735733],
|
| 118 |
+
[0.85124403, 0.26499712],
|
| 119 |
+
[0.45067590, 0.45464607]])
|
| 120 |
+
assert_raises(ValueError, whiten, obs)
|
| 121 |
+
|
| 122 |
+
@pytest.mark.skipif(SCIPY_ARRAY_API,
|
| 123 |
+
reason='`np.matrix` unsupported in array API mode')
|
| 124 |
+
def test_whiten_not_finite_matrix(self, xp):
|
| 125 |
+
for bad_value in np.nan, np.inf, -np.inf:
|
| 126 |
+
obs = matrix([[0.98744510, bad_value],
|
| 127 |
+
[0.62093317, 0.19406729],
|
| 128 |
+
[0.87545741, 0.00735733],
|
| 129 |
+
[0.85124403, 0.26499712],
|
| 130 |
+
[0.45067590, 0.45464607]])
|
| 131 |
+
assert_raises(ValueError, whiten, obs)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class TestVq:
|
| 135 |
+
|
| 136 |
+
@skip_if_array_api(cpu_only=True)
|
| 137 |
+
def test_py_vq(self, xp):
|
| 138 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 139 |
+
# label1.dtype varies between int32 and int64 over platforms
|
| 140 |
+
label1 = py_vq(xp.asarray(X), xp.asarray(initc))[0]
|
| 141 |
+
xp_assert_equal(label1, xp.asarray(LABEL1, dtype=xp.int64),
|
| 142 |
+
check_dtype=False)
|
| 143 |
+
|
| 144 |
+
@pytest.mark.skipif(SCIPY_ARRAY_API,
|
| 145 |
+
reason='`np.matrix` unsupported in array API mode')
|
| 146 |
+
def test_py_vq_matrix(self, xp):
|
| 147 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 148 |
+
# label1.dtype varies between int32 and int64 over platforms
|
| 149 |
+
label1 = py_vq(matrix(X), matrix(initc))[0]
|
| 150 |
+
assert_array_equal(label1, LABEL1)
|
| 151 |
+
|
| 152 |
+
@skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
|
| 153 |
+
def test_vq(self, xp):
|
| 154 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 155 |
+
label1, _ = _vq.vq(xp.asarray(X), xp.asarray(initc))
|
| 156 |
+
assert_array_equal(label1, LABEL1)
|
| 157 |
+
_, _ = vq(xp.asarray(X), xp.asarray(initc))
|
| 158 |
+
|
| 159 |
+
@pytest.mark.skipif(SCIPY_ARRAY_API,
|
| 160 |
+
reason='`np.matrix` unsupported in array API mode')
|
| 161 |
+
def test_vq_matrix(self, xp):
|
| 162 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 163 |
+
label1, _ = _vq.vq(matrix(X), matrix(initc))
|
| 164 |
+
assert_array_equal(label1, LABEL1)
|
| 165 |
+
_, _ = vq(matrix(X), matrix(initc))
|
| 166 |
+
|
| 167 |
+
@skip_if_array_api(cpu_only=True)
|
| 168 |
+
def test_vq_1d(self, xp):
|
| 169 |
+
# Test special rank 1 vq algo, python implementation.
|
| 170 |
+
data = X[:, 0]
|
| 171 |
+
initc = data[:3]
|
| 172 |
+
a, b = _vq.vq(data, initc)
|
| 173 |
+
data = xp.asarray(data)
|
| 174 |
+
initc = xp.asarray(initc)
|
| 175 |
+
ta, tb = py_vq(data[:, np.newaxis], initc[:, np.newaxis])
|
| 176 |
+
# ta.dtype varies between int32 and int64 over platforms
|
| 177 |
+
xp_assert_equal(ta, xp.asarray(a, dtype=xp.int64), check_dtype=False)
|
| 178 |
+
xp_assert_equal(tb, xp.asarray(b))
|
| 179 |
+
|
| 180 |
+
@skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
|
| 181 |
+
def test__vq_sametype(self, xp):
|
| 182 |
+
a = xp.asarray([1.0, 2.0], dtype=xp.float64)
|
| 183 |
+
b = a.astype(xp.float32)
|
| 184 |
+
assert_raises(TypeError, _vq.vq, a, b)
|
| 185 |
+
|
| 186 |
+
@skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
|
| 187 |
+
def test__vq_invalid_type(self, xp):
|
| 188 |
+
a = xp.asarray([1, 2], dtype=int)
|
| 189 |
+
assert_raises(TypeError, _vq.vq, a, a)
|
| 190 |
+
|
| 191 |
+
@skip_if_array_api(cpu_only=True)
|
| 192 |
+
def test_vq_large_nfeat(self, xp):
|
| 193 |
+
X = np.random.rand(20, 20)
|
| 194 |
+
code_book = np.random.rand(3, 20)
|
| 195 |
+
|
| 196 |
+
codes0, dis0 = _vq.vq(X, code_book)
|
| 197 |
+
codes1, dis1 = py_vq(
|
| 198 |
+
xp.asarray(X), xp.asarray(code_book)
|
| 199 |
+
)
|
| 200 |
+
xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5)
|
| 201 |
+
# codes1.dtype varies between int32 and int64 over platforms
|
| 202 |
+
xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
|
| 203 |
+
|
| 204 |
+
X = X.astype(np.float32)
|
| 205 |
+
code_book = code_book.astype(np.float32)
|
| 206 |
+
|
| 207 |
+
codes0, dis0 = _vq.vq(X, code_book)
|
| 208 |
+
codes1, dis1 = py_vq(
|
| 209 |
+
xp.asarray(X), xp.asarray(code_book)
|
| 210 |
+
)
|
| 211 |
+
xp_assert_close(dis1, xp.asarray(dis0, dtype=xp.float64), rtol=1e-5)
|
| 212 |
+
# codes1.dtype varies between int32 and int64 over platforms
|
| 213 |
+
xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
|
| 214 |
+
|
| 215 |
+
@skip_if_array_api(cpu_only=True)
|
| 216 |
+
def test_vq_large_features(self, xp):
|
| 217 |
+
X = np.random.rand(10, 5) * 1000000
|
| 218 |
+
code_book = np.random.rand(2, 5) * 1000000
|
| 219 |
+
|
| 220 |
+
codes0, dis0 = _vq.vq(X, code_book)
|
| 221 |
+
codes1, dis1 = py_vq(
|
| 222 |
+
xp.asarray(X), xp.asarray(code_book)
|
| 223 |
+
)
|
| 224 |
+
xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5)
|
| 225 |
+
# codes1.dtype varies between int32 and int64 over platforms
|
| 226 |
+
xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
# Whole class skipped on GPU for now;
|
| 230 |
+
# once pdist/cdist are hooked up for CuPy, more tests will work
|
| 231 |
+
@skip_if_array_api(cpu_only=True)
|
| 232 |
+
class TestKMean:
|
| 233 |
+
|
| 234 |
+
def test_large_features(self, xp):
|
| 235 |
+
# Generate a data set with large values, and run kmeans on it to
|
| 236 |
+
# (regression for 1077).
|
| 237 |
+
d = 300
|
| 238 |
+
n = 100
|
| 239 |
+
|
| 240 |
+
m1 = np.random.randn(d)
|
| 241 |
+
m2 = np.random.randn(d)
|
| 242 |
+
x = 10000 * np.random.randn(n, d) - 20000 * m1
|
| 243 |
+
y = 10000 * np.random.randn(n, d) + 20000 * m2
|
| 244 |
+
|
| 245 |
+
data = np.empty((x.shape[0] + y.shape[0], d), np.float64)
|
| 246 |
+
data[:x.shape[0]] = x
|
| 247 |
+
data[x.shape[0]:] = y
|
| 248 |
+
|
| 249 |
+
kmeans(xp.asarray(data), 2)
|
| 250 |
+
|
| 251 |
+
def test_kmeans_simple(self, xp):
|
| 252 |
+
np.random.seed(54321)
|
| 253 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 254 |
+
code1 = kmeans(xp.asarray(X), xp.asarray(initc), iter=1)[0]
|
| 255 |
+
xp_assert_close(code1, xp.asarray(CODET2))
|
| 256 |
+
|
| 257 |
+
@pytest.mark.skipif(SCIPY_ARRAY_API,
|
| 258 |
+
reason='`np.matrix` unsupported in array API mode')
|
| 259 |
+
def test_kmeans_simple_matrix(self, xp):
|
| 260 |
+
np.random.seed(54321)
|
| 261 |
+
initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
|
| 262 |
+
code1 = kmeans(matrix(X), matrix(initc), iter=1)[0]
|
| 263 |
+
xp_assert_close(code1, CODET2)
|
| 264 |
+
|
| 265 |
+
def test_kmeans_lost_cluster(self, xp):
|
| 266 |
+
# This will cause kmeans to have a cluster with no points.
|
| 267 |
+
data = xp.asarray(TESTDATA_2D)
|
| 268 |
+
initk = xp.asarray([[-1.8127404, -0.67128041],
|
| 269 |
+
[2.04621601, 0.07401111],
|
| 270 |
+
[-2.31149087, -0.05160469]])
|
| 271 |
+
|
| 272 |
+
kmeans(data, initk)
|
| 273 |
+
with suppress_warnings() as sup:
|
| 274 |
+
sup.filter(UserWarning,
|
| 275 |
+
"One of the clusters is empty. Re-run kmeans with a "
|
| 276 |
+
"different initialization")
|
| 277 |
+
kmeans2(data, initk, missing='warn')
|
| 278 |
+
|
| 279 |
+
assert_raises(ClusterError, kmeans2, data, initk, missing='raise')
|
| 280 |
+
|
| 281 |
+
def test_kmeans2_simple(self, xp):
|
| 282 |
+
np.random.seed(12345678)
|
| 283 |
+
initc = xp.asarray(np.concatenate([[X[0]], [X[1]], [X[2]]]))
|
| 284 |
+
arrays = [xp.asarray] if SCIPY_ARRAY_API else [np.asarray, matrix]
|
| 285 |
+
for tp in arrays:
|
| 286 |
+
code1 = kmeans2(tp(X), tp(initc), iter=1)[0]
|
| 287 |
+
code2 = kmeans2(tp(X), tp(initc), iter=2)[0]
|
| 288 |
+
|
| 289 |
+
xp_assert_close(code1, xp.asarray(CODET1))
|
| 290 |
+
xp_assert_close(code2, xp.asarray(CODET2))
|
| 291 |
+
|
| 292 |
+
@pytest.mark.skipif(SCIPY_ARRAY_API,
|
| 293 |
+
reason='`np.matrix` unsupported in array API mode')
|
| 294 |
+
def test_kmeans2_simple_matrix(self, xp):
|
| 295 |
+
np.random.seed(12345678)
|
| 296 |
+
initc = xp.asarray(np.concatenate([[X[0]], [X[1]], [X[2]]]))
|
| 297 |
+
code1 = kmeans2(matrix(X), matrix(initc), iter=1)[0]
|
| 298 |
+
code2 = kmeans2(matrix(X), matrix(initc), iter=2)[0]
|
| 299 |
+
|
| 300 |
+
xp_assert_close(code1, CODET1)
|
| 301 |
+
xp_assert_close(code2, CODET2)
|
| 302 |
+
|
| 303 |
+
def test_kmeans2_rank1(self, xp):
|
| 304 |
+
data = xp.asarray(TESTDATA_2D)
|
| 305 |
+
data1 = data[:, 0]
|
| 306 |
+
|
| 307 |
+
initc = data1[:3]
|
| 308 |
+
code = copy(initc, xp=xp)
|
| 309 |
+
kmeans2(data1, code, iter=1)[0]
|
| 310 |
+
kmeans2(data1, code, iter=2)[0]
|
| 311 |
+
|
| 312 |
+
def test_kmeans2_rank1_2(self, xp):
|
| 313 |
+
data = xp.asarray(TESTDATA_2D)
|
| 314 |
+
data1 = data[:, 0]
|
| 315 |
+
kmeans2(data1, 2, iter=1)
|
| 316 |
+
|
| 317 |
+
def test_kmeans2_high_dim(self, xp):
|
| 318 |
+
# test kmeans2 when the number of dimensions exceeds the number
|
| 319 |
+
# of input points
|
| 320 |
+
data = xp.asarray(TESTDATA_2D)
|
| 321 |
+
data = xp.reshape(data, (20, 20))[:10, :]
|
| 322 |
+
kmeans2(data, 2)
|
| 323 |
+
|
| 324 |
+
def test_kmeans2_init(self, xp):
|
| 325 |
+
np.random.seed(12345)
|
| 326 |
+
data = xp.asarray(TESTDATA_2D)
|
| 327 |
+
k = 3
|
| 328 |
+
|
| 329 |
+
kmeans2(data, k, minit='points')
|
| 330 |
+
kmeans2(data[:, 1], k, minit='points') # special case (1-D)
|
| 331 |
+
|
| 332 |
+
kmeans2(data, k, minit='++')
|
| 333 |
+
kmeans2(data[:, 1], k, minit='++') # special case (1-D)
|
| 334 |
+
|
| 335 |
+
# minit='random' can give warnings, filter those
|
| 336 |
+
with suppress_warnings() as sup:
|
| 337 |
+
sup.filter(message="One of the clusters is empty. Re-run.")
|
| 338 |
+
kmeans2(data, k, minit='random')
|
| 339 |
+
kmeans2(data[:, 1], k, minit='random') # special case (1-D)
|
| 340 |
+
|
| 341 |
+
@pytest.mark.skipif(sys.platform == 'win32',
|
| 342 |
+
reason='Fails with MemoryError in Wine.')
|
| 343 |
+
def test_krandinit(self, xp):
|
| 344 |
+
data = xp.asarray(TESTDATA_2D)
|
| 345 |
+
datas = [xp.reshape(data, (200, 2)),
|
| 346 |
+
xp.reshape(data, (20, 20))[:10, :]]
|
| 347 |
+
k = int(1e6)
|
| 348 |
+
for data in datas:
|
| 349 |
+
rng = np.random.default_rng(1234)
|
| 350 |
+
init = _krandinit(data, k, rng, xp)
|
| 351 |
+
orig_cov = cov(data.T)
|
| 352 |
+
init_cov = cov(init.T)
|
| 353 |
+
xp_assert_close(orig_cov, init_cov, atol=1e-2)
|
| 354 |
+
|
| 355 |
+
def test_kmeans2_empty(self, xp):
|
| 356 |
+
# Regression test for gh-1032.
|
| 357 |
+
assert_raises(ValueError, kmeans2, xp.asarray([]), 2)
|
| 358 |
+
|
| 359 |
+
def test_kmeans_0k(self, xp):
|
| 360 |
+
# Regression test for gh-1073: fail when k arg is 0.
|
| 361 |
+
assert_raises(ValueError, kmeans, xp.asarray(X), 0)
|
| 362 |
+
assert_raises(ValueError, kmeans2, xp.asarray(X), 0)
|
| 363 |
+
assert_raises(ValueError, kmeans2, xp.asarray(X), xp.asarray([]))
|
| 364 |
+
|
| 365 |
+
def test_kmeans_large_thres(self, xp):
|
| 366 |
+
# Regression test for gh-1774
|
| 367 |
+
x = xp.asarray([1, 2, 3, 4, 10], dtype=xp.float64)
|
| 368 |
+
res = kmeans(x, 1, thresh=1e16)
|
| 369 |
+
xp_assert_close(res[0], xp.asarray([4.], dtype=xp.float64))
|
| 370 |
+
xp_assert_close(res[1], xp.asarray(2.3999999999999999, dtype=xp.float64)[()])
|
| 371 |
+
|
| 372 |
+
def test_kmeans2_kpp_low_dim(self, xp):
|
| 373 |
+
# Regression test for gh-11462
|
| 374 |
+
prev_res = xp.asarray([[-1.95266667, 0.898],
|
| 375 |
+
[-3.153375, 3.3945]], dtype=xp.float64)
|
| 376 |
+
np.random.seed(42)
|
| 377 |
+
res, _ = kmeans2(xp.asarray(TESTDATA_2D), 2, minit='++')
|
| 378 |
+
xp_assert_close(res, prev_res)
|
| 379 |
+
|
| 380 |
+
def test_kmeans2_kpp_high_dim(self, xp):
|
| 381 |
+
# Regression test for gh-11462
|
| 382 |
+
n_dim = 100
|
| 383 |
+
size = 10
|
| 384 |
+
centers = np.vstack([5 * np.ones(n_dim),
|
| 385 |
+
-5 * np.ones(n_dim)])
|
| 386 |
+
np.random.seed(42)
|
| 387 |
+
data = np.vstack([
|
| 388 |
+
np.random.multivariate_normal(centers[0], np.eye(n_dim), size=size),
|
| 389 |
+
np.random.multivariate_normal(centers[1], np.eye(n_dim), size=size)
|
| 390 |
+
])
|
| 391 |
+
|
| 392 |
+
data = xp.asarray(data)
|
| 393 |
+
res, _ = kmeans2(data, 2, minit='++')
|
| 394 |
+
xp_assert_equal(xp.sign(res), xp.sign(xp.asarray(centers)))
|
| 395 |
+
|
| 396 |
+
def test_kmeans_diff_convergence(self, xp):
|
| 397 |
+
# Regression test for gh-8727
|
| 398 |
+
obs = xp.asarray([-3, -1, 0, 1, 1, 8], dtype=xp.float64)
|
| 399 |
+
res = kmeans(obs, xp.asarray([-3., 0.99]))
|
| 400 |
+
xp_assert_close(res[0], xp.asarray([-0.4, 8.], dtype=xp.float64))
|
| 401 |
+
xp_assert_close(res[1], xp.asarray(1.0666666666666667, dtype=xp.float64)[()])
|
| 402 |
+
|
| 403 |
+
def test_kmeans_and_kmeans2_random_seed(self, xp):
|
| 404 |
+
|
| 405 |
+
seed_list = [
|
| 406 |
+
1234, np.random.RandomState(1234), np.random.default_rng(1234)
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
for seed in seed_list:
|
| 410 |
+
seed1 = deepcopy(seed)
|
| 411 |
+
seed2 = deepcopy(seed)
|
| 412 |
+
data = xp.asarray(TESTDATA_2D)
|
| 413 |
+
# test for kmeans
|
| 414 |
+
res1, _ = kmeans(data, 2, seed=seed1)
|
| 415 |
+
res2, _ = kmeans(data, 2, seed=seed2)
|
| 416 |
+
xp_assert_close(res1, res2, xp=xp) # should be same results
|
| 417 |
+
# test for kmeans2
|
| 418 |
+
for minit in ["random", "points", "++"]:
|
| 419 |
+
res1, _ = kmeans2(data, 2, minit=minit, seed=seed1)
|
| 420 |
+
res2, _ = kmeans2(data, 2, minit=minit, seed=seed2)
|
| 421 |
+
xp_assert_close(res1, res2, xp=xp) # should be same results
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/vq.py
ADDED
|
@@ -0,0 +1,835 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
K-means clustering and vector quantization (:mod:`scipy.cluster.vq`)
|
| 3 |
+
====================================================================
|
| 4 |
+
|
| 5 |
+
Provides routines for k-means clustering, generating code books
|
| 6 |
+
from k-means models and quantizing vectors by comparing them with
|
| 7 |
+
centroids in a code book.
|
| 8 |
+
|
| 9 |
+
.. autosummary::
|
| 10 |
+
:toctree: generated/
|
| 11 |
+
|
| 12 |
+
whiten -- Normalize a group of observations so each feature has unit variance
|
| 13 |
+
vq -- Calculate code book membership of a set of observation vectors
|
| 14 |
+
kmeans -- Perform k-means on a set of observation vectors forming k clusters
|
| 15 |
+
kmeans2 -- A different implementation of k-means with more methods
|
| 16 |
+
-- for initializing centroids
|
| 17 |
+
|
| 18 |
+
Background information
|
| 19 |
+
----------------------
|
| 20 |
+
The k-means algorithm takes as input the number of clusters to
|
| 21 |
+
generate, k, and a set of observation vectors to cluster. It
|
| 22 |
+
returns a set of centroids, one for each of the k clusters. An
|
| 23 |
+
observation vector is classified with the cluster number or
|
| 24 |
+
centroid index of the centroid closest to it.
|
| 25 |
+
|
| 26 |
+
A vector v belongs to cluster i if it is closer to centroid i than
|
| 27 |
+
any other centroid. If v belongs to i, we say centroid i is the
|
| 28 |
+
dominating centroid of v. The k-means algorithm tries to
|
| 29 |
+
minimize distortion, which is defined as the sum of the squared distances
|
| 30 |
+
between each observation vector and its dominating centroid.
|
| 31 |
+
The minimization is achieved by iteratively reclassifying
|
| 32 |
+
the observations into clusters and recalculating the centroids until
|
| 33 |
+
a configuration is reached in which the centroids are stable. One can
|
| 34 |
+
also define a maximum number of iterations.
|
| 35 |
+
|
| 36 |
+
Since vector quantization is a natural application for k-means,
|
| 37 |
+
information theory terminology is often used. The centroid index
|
| 38 |
+
or cluster index is also referred to as a "code" and the table
|
| 39 |
+
mapping codes to centroids and, vice versa, is often referred to as a
|
| 40 |
+
"code book". The result of k-means, a set of centroids, can be
|
| 41 |
+
used to quantize vectors. Quantization aims to find an encoding of
|
| 42 |
+
vectors that reduces the expected distortion.
|
| 43 |
+
|
| 44 |
+
All routines expect obs to be an M by N array, where the rows are
|
| 45 |
+
the observation vectors. The codebook is a k by N array, where the
|
| 46 |
+
ith row is the centroid of code word i. The observation vectors
|
| 47 |
+
and centroids have the same feature dimension.
|
| 48 |
+
|
| 49 |
+
As an example, suppose we wish to compress a 24-bit color image
|
| 50 |
+
(each pixel is represented by one byte for red, one for blue, and
|
| 51 |
+
one for green) before sending it over the web. By using a smaller
|
| 52 |
+
8-bit encoding, we can reduce the amount of data by two
|
| 53 |
+
thirds. Ideally, the colors for each of the 256 possible 8-bit
|
| 54 |
+
encoding values should be chosen to minimize distortion of the
|
| 55 |
+
color. Running k-means with k=256 generates a code book of 256
|
| 56 |
+
codes, which fills up all possible 8-bit sequences. Instead of
|
| 57 |
+
sending a 3-byte value for each pixel, the 8-bit centroid index
|
| 58 |
+
(or code word) of the dominating centroid is transmitted. The code
|
| 59 |
+
book is also sent over the wire so each 8-bit code can be
|
| 60 |
+
translated back to a 24-bit pixel value representation. If the
|
| 61 |
+
image of interest was of an ocean, we would expect many 24-bit
|
| 62 |
+
blues to be represented by 8-bit codes. If it was an image of a
|
| 63 |
+
human face, more flesh-tone colors would be represented in the
|
| 64 |
+
code book.
|
| 65 |
+
|
| 66 |
+
"""
|
| 67 |
+
import warnings
|
| 68 |
+
import numpy as np
|
| 69 |
+
from collections import deque
|
| 70 |
+
from scipy._lib._array_api import (
|
| 71 |
+
_asarray, array_namespace, size, atleast_nd, copy, cov
|
| 72 |
+
)
|
| 73 |
+
from scipy._lib._util import check_random_state, rng_integers
|
| 74 |
+
from scipy.spatial.distance import cdist
|
| 75 |
+
|
| 76 |
+
from . import _vq
|
| 77 |
+
|
| 78 |
+
__docformat__ = 'restructuredtext'
|
| 79 |
+
|
| 80 |
+
__all__ = ['whiten', 'vq', 'kmeans', 'kmeans2']
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class ClusterError(Exception):
|
| 84 |
+
pass
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def whiten(obs, check_finite=True):
|
| 88 |
+
"""
|
| 89 |
+
Normalize a group of observations on a per feature basis.
|
| 90 |
+
|
| 91 |
+
Before running k-means, it is beneficial to rescale each feature
|
| 92 |
+
dimension of the observation set by its standard deviation (i.e. "whiten"
|
| 93 |
+
it - as in "white noise" where each frequency has equal power).
|
| 94 |
+
Each feature is divided by its standard deviation across all observations
|
| 95 |
+
to give it unit variance.
|
| 96 |
+
|
| 97 |
+
Parameters
|
| 98 |
+
----------
|
| 99 |
+
obs : ndarray
|
| 100 |
+
Each row of the array is an observation. The
|
| 101 |
+
columns are the features seen during each observation.
|
| 102 |
+
|
| 103 |
+
>>> # f0 f1 f2
|
| 104 |
+
>>> obs = [[ 1., 1., 1.], #o0
|
| 105 |
+
... [ 2., 2., 2.], #o1
|
| 106 |
+
... [ 3., 3., 3.], #o2
|
| 107 |
+
... [ 4., 4., 4.]] #o3
|
| 108 |
+
|
| 109 |
+
check_finite : bool, optional
|
| 110 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 111 |
+
Disabling may give a performance gain, but may result in problems
|
| 112 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 113 |
+
Default: True
|
| 114 |
+
|
| 115 |
+
Returns
|
| 116 |
+
-------
|
| 117 |
+
result : ndarray
|
| 118 |
+
Contains the values in `obs` scaled by the standard deviation
|
| 119 |
+
of each column.
|
| 120 |
+
|
| 121 |
+
Examples
|
| 122 |
+
--------
|
| 123 |
+
>>> import numpy as np
|
| 124 |
+
>>> from scipy.cluster.vq import whiten
|
| 125 |
+
>>> features = np.array([[1.9, 2.3, 1.7],
|
| 126 |
+
... [1.5, 2.5, 2.2],
|
| 127 |
+
... [0.8, 0.6, 1.7,]])
|
| 128 |
+
>>> whiten(features)
|
| 129 |
+
array([[ 4.17944278, 2.69811351, 7.21248917],
|
| 130 |
+
[ 3.29956009, 2.93273208, 9.33380951],
|
| 131 |
+
[ 1.75976538, 0.7038557 , 7.21248917]])
|
| 132 |
+
|
| 133 |
+
"""
|
| 134 |
+
xp = array_namespace(obs)
|
| 135 |
+
obs = _asarray(obs, check_finite=check_finite, xp=xp)
|
| 136 |
+
std_dev = xp.std(obs, axis=0)
|
| 137 |
+
zero_std_mask = std_dev == 0
|
| 138 |
+
if xp.any(zero_std_mask):
|
| 139 |
+
std_dev[zero_std_mask] = 1.0
|
| 140 |
+
warnings.warn("Some columns have standard deviation zero. "
|
| 141 |
+
"The values of these columns will not change.",
|
| 142 |
+
RuntimeWarning, stacklevel=2)
|
| 143 |
+
return obs / std_dev
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
def vq(obs, code_book, check_finite=True):
|
| 147 |
+
"""
|
| 148 |
+
Assign codes from a code book to observations.
|
| 149 |
+
|
| 150 |
+
Assigns a code from a code book to each observation. Each
|
| 151 |
+
observation vector in the 'M' by 'N' `obs` array is compared with the
|
| 152 |
+
centroids in the code book and assigned the code of the closest
|
| 153 |
+
centroid.
|
| 154 |
+
|
| 155 |
+
The features in `obs` should have unit variance, which can be
|
| 156 |
+
achieved by passing them through the whiten function. The code
|
| 157 |
+
book can be created with the k-means algorithm or a different
|
| 158 |
+
encoding algorithm.
|
| 159 |
+
|
| 160 |
+
Parameters
|
| 161 |
+
----------
|
| 162 |
+
obs : ndarray
|
| 163 |
+
Each row of the 'M' x 'N' array is an observation. The columns are
|
| 164 |
+
the "features" seen during each observation. The features must be
|
| 165 |
+
whitened first using the whiten function or something equivalent.
|
| 166 |
+
code_book : ndarray
|
| 167 |
+
The code book is usually generated using the k-means algorithm.
|
| 168 |
+
Each row of the array holds a different code, and the columns are
|
| 169 |
+
the features of the code.
|
| 170 |
+
|
| 171 |
+
>>> # f0 f1 f2 f3
|
| 172 |
+
>>> code_book = [
|
| 173 |
+
... [ 1., 2., 3., 4.], #c0
|
| 174 |
+
... [ 1., 2., 3., 4.], #c1
|
| 175 |
+
... [ 1., 2., 3., 4.]] #c2
|
| 176 |
+
|
| 177 |
+
check_finite : bool, optional
|
| 178 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 179 |
+
Disabling may give a performance gain, but may result in problems
|
| 180 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 181 |
+
Default: True
|
| 182 |
+
|
| 183 |
+
Returns
|
| 184 |
+
-------
|
| 185 |
+
code : ndarray
|
| 186 |
+
A length M array holding the code book index for each observation.
|
| 187 |
+
dist : ndarray
|
| 188 |
+
The distortion (distance) between the observation and its nearest
|
| 189 |
+
code.
|
| 190 |
+
|
| 191 |
+
Examples
|
| 192 |
+
--------
|
| 193 |
+
>>> import numpy as np
|
| 194 |
+
>>> from scipy.cluster.vq import vq
|
| 195 |
+
>>> code_book = np.array([[1., 1., 1.],
|
| 196 |
+
... [2., 2., 2.]])
|
| 197 |
+
>>> features = np.array([[1.9, 2.3, 1.7],
|
| 198 |
+
... [1.5, 2.5, 2.2],
|
| 199 |
+
... [0.8, 0.6, 1.7]])
|
| 200 |
+
>>> vq(features, code_book)
|
| 201 |
+
(array([1, 1, 0], dtype=int32), array([0.43588989, 0.73484692, 0.83066239]))
|
| 202 |
+
|
| 203 |
+
"""
|
| 204 |
+
xp = array_namespace(obs, code_book)
|
| 205 |
+
obs = _asarray(obs, xp=xp, check_finite=check_finite)
|
| 206 |
+
code_book = _asarray(code_book, xp=xp, check_finite=check_finite)
|
| 207 |
+
ct = xp.result_type(obs, code_book)
|
| 208 |
+
|
| 209 |
+
c_obs = xp.astype(obs, ct, copy=False)
|
| 210 |
+
c_code_book = xp.astype(code_book, ct, copy=False)
|
| 211 |
+
|
| 212 |
+
if xp.isdtype(ct, kind='real floating'):
|
| 213 |
+
c_obs = np.asarray(c_obs)
|
| 214 |
+
c_code_book = np.asarray(c_code_book)
|
| 215 |
+
result = _vq.vq(c_obs, c_code_book)
|
| 216 |
+
return xp.asarray(result[0]), xp.asarray(result[1])
|
| 217 |
+
return py_vq(obs, code_book, check_finite=False)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def py_vq(obs, code_book, check_finite=True):
|
| 221 |
+
""" Python version of vq algorithm.
|
| 222 |
+
|
| 223 |
+
The algorithm computes the Euclidean distance between each
|
| 224 |
+
observation and every frame in the code_book.
|
| 225 |
+
|
| 226 |
+
Parameters
|
| 227 |
+
----------
|
| 228 |
+
obs : ndarray
|
| 229 |
+
Expects a rank 2 array. Each row is one observation.
|
| 230 |
+
code_book : ndarray
|
| 231 |
+
Code book to use. Same format than obs. Should have same number of
|
| 232 |
+
features (e.g., columns) than obs.
|
| 233 |
+
check_finite : bool, optional
|
| 234 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 235 |
+
Disabling may give a performance gain, but may result in problems
|
| 236 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 237 |
+
Default: True
|
| 238 |
+
|
| 239 |
+
Returns
|
| 240 |
+
-------
|
| 241 |
+
code : ndarray
|
| 242 |
+
code[i] gives the label of the ith obversation; its code is
|
| 243 |
+
code_book[code[i]].
|
| 244 |
+
mind_dist : ndarray
|
| 245 |
+
min_dist[i] gives the distance between the ith observation and its
|
| 246 |
+
corresponding code.
|
| 247 |
+
|
| 248 |
+
Notes
|
| 249 |
+
-----
|
| 250 |
+
This function is slower than the C version but works for
|
| 251 |
+
all input types. If the inputs have the wrong types for the
|
| 252 |
+
C versions of the function, this one is called as a last resort.
|
| 253 |
+
|
| 254 |
+
It is about 20 times slower than the C version.
|
| 255 |
+
|
| 256 |
+
"""
|
| 257 |
+
xp = array_namespace(obs, code_book)
|
| 258 |
+
obs = _asarray(obs, xp=xp, check_finite=check_finite)
|
| 259 |
+
code_book = _asarray(code_book, xp=xp, check_finite=check_finite)
|
| 260 |
+
|
| 261 |
+
if obs.ndim != code_book.ndim:
|
| 262 |
+
raise ValueError("Observation and code_book should have the same rank")
|
| 263 |
+
|
| 264 |
+
if obs.ndim == 1:
|
| 265 |
+
obs = obs[:, xp.newaxis]
|
| 266 |
+
code_book = code_book[:, xp.newaxis]
|
| 267 |
+
|
| 268 |
+
# Once `cdist` has array API support, this `xp.asarray` call can be removed
|
| 269 |
+
dist = xp.asarray(cdist(obs, code_book))
|
| 270 |
+
code = xp.argmin(dist, axis=1)
|
| 271 |
+
min_dist = xp.min(dist, axis=1)
|
| 272 |
+
return code, min_dist
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def _kmeans(obs, guess, thresh=1e-5, xp=None):
|
| 276 |
+
""" "raw" version of k-means.
|
| 277 |
+
|
| 278 |
+
Returns
|
| 279 |
+
-------
|
| 280 |
+
code_book
|
| 281 |
+
The lowest distortion codebook found.
|
| 282 |
+
avg_dist
|
| 283 |
+
The average distance a observation is from a code in the book.
|
| 284 |
+
Lower means the code_book matches the data better.
|
| 285 |
+
|
| 286 |
+
See Also
|
| 287 |
+
--------
|
| 288 |
+
kmeans : wrapper around k-means
|
| 289 |
+
|
| 290 |
+
Examples
|
| 291 |
+
--------
|
| 292 |
+
Note: not whitened in this example.
|
| 293 |
+
|
| 294 |
+
>>> import numpy as np
|
| 295 |
+
>>> from scipy.cluster.vq import _kmeans
|
| 296 |
+
>>> features = np.array([[ 1.9,2.3],
|
| 297 |
+
... [ 1.5,2.5],
|
| 298 |
+
... [ 0.8,0.6],
|
| 299 |
+
... [ 0.4,1.8],
|
| 300 |
+
... [ 1.0,1.0]])
|
| 301 |
+
>>> book = np.array((features[0],features[2]))
|
| 302 |
+
>>> _kmeans(features,book)
|
| 303 |
+
(array([[ 1.7 , 2.4 ],
|
| 304 |
+
[ 0.73333333, 1.13333333]]), 0.40563916697728591)
|
| 305 |
+
|
| 306 |
+
"""
|
| 307 |
+
xp = np if xp is None else xp
|
| 308 |
+
code_book = guess
|
| 309 |
+
diff = xp.inf
|
| 310 |
+
prev_avg_dists = deque([diff], maxlen=2)
|
| 311 |
+
while diff > thresh:
|
| 312 |
+
# compute membership and distances between obs and code_book
|
| 313 |
+
obs_code, distort = vq(obs, code_book, check_finite=False)
|
| 314 |
+
prev_avg_dists.append(xp.mean(distort, axis=-1))
|
| 315 |
+
# recalc code_book as centroids of associated obs
|
| 316 |
+
obs = np.asarray(obs)
|
| 317 |
+
obs_code = np.asarray(obs_code)
|
| 318 |
+
code_book, has_members = _vq.update_cluster_means(obs, obs_code,
|
| 319 |
+
code_book.shape[0])
|
| 320 |
+
obs = xp.asarray(obs)
|
| 321 |
+
obs_code = xp.asarray(obs_code)
|
| 322 |
+
code_book = xp.asarray(code_book)
|
| 323 |
+
has_members = xp.asarray(has_members)
|
| 324 |
+
code_book = code_book[has_members]
|
| 325 |
+
diff = xp.abs(prev_avg_dists[0] - prev_avg_dists[1])
|
| 326 |
+
|
| 327 |
+
return code_book, prev_avg_dists[1]
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
def kmeans(obs, k_or_guess, iter=20, thresh=1e-5, check_finite=True,
|
| 331 |
+
*, seed=None):
|
| 332 |
+
"""
|
| 333 |
+
Performs k-means on a set of observation vectors forming k clusters.
|
| 334 |
+
|
| 335 |
+
The k-means algorithm adjusts the classification of the observations
|
| 336 |
+
into clusters and updates the cluster centroids until the position of
|
| 337 |
+
the centroids is stable over successive iterations. In this
|
| 338 |
+
implementation of the algorithm, the stability of the centroids is
|
| 339 |
+
determined by comparing the absolute value of the change in the average
|
| 340 |
+
Euclidean distance between the observations and their corresponding
|
| 341 |
+
centroids against a threshold. This yields
|
| 342 |
+
a code book mapping centroids to codes and vice versa.
|
| 343 |
+
|
| 344 |
+
Parameters
|
| 345 |
+
----------
|
| 346 |
+
obs : ndarray
|
| 347 |
+
Each row of the M by N array is an observation vector. The
|
| 348 |
+
columns are the features seen during each observation.
|
| 349 |
+
The features must be whitened first with the `whiten` function.
|
| 350 |
+
|
| 351 |
+
k_or_guess : int or ndarray
|
| 352 |
+
The number of centroids to generate. A code is assigned to
|
| 353 |
+
each centroid, which is also the row index of the centroid
|
| 354 |
+
in the code_book matrix generated.
|
| 355 |
+
|
| 356 |
+
The initial k centroids are chosen by randomly selecting
|
| 357 |
+
observations from the observation matrix. Alternatively,
|
| 358 |
+
passing a k by N array specifies the initial k centroids.
|
| 359 |
+
|
| 360 |
+
iter : int, optional
|
| 361 |
+
The number of times to run k-means, returning the codebook
|
| 362 |
+
with the lowest distortion. This argument is ignored if
|
| 363 |
+
initial centroids are specified with an array for the
|
| 364 |
+
``k_or_guess`` parameter. This parameter does not represent the
|
| 365 |
+
number of iterations of the k-means algorithm.
|
| 366 |
+
|
| 367 |
+
thresh : float, optional
|
| 368 |
+
Terminates the k-means algorithm if the change in
|
| 369 |
+
distortion since the last k-means iteration is less than
|
| 370 |
+
or equal to threshold.
|
| 371 |
+
|
| 372 |
+
check_finite : bool, optional
|
| 373 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 374 |
+
Disabling may give a performance gain, but may result in problems
|
| 375 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 376 |
+
Default: True
|
| 377 |
+
|
| 378 |
+
seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
|
| 379 |
+
Seed for initializing the pseudo-random number generator.
|
| 380 |
+
If `seed` is None (or `numpy.random`), the `numpy.random.RandomState`
|
| 381 |
+
singleton is used.
|
| 382 |
+
If `seed` is an int, a new ``RandomState`` instance is used,
|
| 383 |
+
seeded with `seed`.
|
| 384 |
+
If `seed` is already a ``Generator`` or ``RandomState`` instance then
|
| 385 |
+
that instance is used.
|
| 386 |
+
The default is None.
|
| 387 |
+
|
| 388 |
+
Returns
|
| 389 |
+
-------
|
| 390 |
+
codebook : ndarray
|
| 391 |
+
A k by N array of k centroids. The ith centroid
|
| 392 |
+
codebook[i] is represented with the code i. The centroids
|
| 393 |
+
and codes generated represent the lowest distortion seen,
|
| 394 |
+
not necessarily the globally minimal distortion.
|
| 395 |
+
Note that the number of centroids is not necessarily the same as the
|
| 396 |
+
``k_or_guess`` parameter, because centroids assigned to no observations
|
| 397 |
+
are removed during iterations.
|
| 398 |
+
|
| 399 |
+
distortion : float
|
| 400 |
+
The mean (non-squared) Euclidean distance between the observations
|
| 401 |
+
passed and the centroids generated. Note the difference to the standard
|
| 402 |
+
definition of distortion in the context of the k-means algorithm, which
|
| 403 |
+
is the sum of the squared distances.
|
| 404 |
+
|
| 405 |
+
See Also
|
| 406 |
+
--------
|
| 407 |
+
kmeans2 : a different implementation of k-means clustering
|
| 408 |
+
with more methods for generating initial centroids but without
|
| 409 |
+
using a distortion change threshold as a stopping criterion.
|
| 410 |
+
|
| 411 |
+
whiten : must be called prior to passing an observation matrix
|
| 412 |
+
to kmeans.
|
| 413 |
+
|
| 414 |
+
Notes
|
| 415 |
+
-----
|
| 416 |
+
For more functionalities or optimal performance, you can use
|
| 417 |
+
`sklearn.cluster.KMeans <https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html>`_.
|
| 418 |
+
`This <https://hdbscan.readthedocs.io/en/latest/performance_and_scalability.html#comparison-of-high-performance-implementations>`_
|
| 419 |
+
is a benchmark result of several implementations.
|
| 420 |
+
|
| 421 |
+
Examples
|
| 422 |
+
--------
|
| 423 |
+
>>> import numpy as np
|
| 424 |
+
>>> from scipy.cluster.vq import vq, kmeans, whiten
|
| 425 |
+
>>> import matplotlib.pyplot as plt
|
| 426 |
+
>>> features = np.array([[ 1.9,2.3],
|
| 427 |
+
... [ 1.5,2.5],
|
| 428 |
+
... [ 0.8,0.6],
|
| 429 |
+
... [ 0.4,1.8],
|
| 430 |
+
... [ 0.1,0.1],
|
| 431 |
+
... [ 0.2,1.8],
|
| 432 |
+
... [ 2.0,0.5],
|
| 433 |
+
... [ 0.3,1.5],
|
| 434 |
+
... [ 1.0,1.0]])
|
| 435 |
+
>>> whitened = whiten(features)
|
| 436 |
+
>>> book = np.array((whitened[0],whitened[2]))
|
| 437 |
+
>>> kmeans(whitened,book)
|
| 438 |
+
(array([[ 2.3110306 , 2.86287398], # random
|
| 439 |
+
[ 0.93218041, 1.24398691]]), 0.85684700941625547)
|
| 440 |
+
|
| 441 |
+
>>> codes = 3
|
| 442 |
+
>>> kmeans(whitened,codes)
|
| 443 |
+
(array([[ 2.3110306 , 2.86287398], # random
|
| 444 |
+
[ 1.32544402, 0.65607529],
|
| 445 |
+
[ 0.40782893, 2.02786907]]), 0.5196582527686241)
|
| 446 |
+
|
| 447 |
+
>>> # Create 50 datapoints in two clusters a and b
|
| 448 |
+
>>> pts = 50
|
| 449 |
+
>>> rng = np.random.default_rng()
|
| 450 |
+
>>> a = rng.multivariate_normal([0, 0], [[4, 1], [1, 4]], size=pts)
|
| 451 |
+
>>> b = rng.multivariate_normal([30, 10],
|
| 452 |
+
... [[10, 2], [2, 1]],
|
| 453 |
+
... size=pts)
|
| 454 |
+
>>> features = np.concatenate((a, b))
|
| 455 |
+
>>> # Whiten data
|
| 456 |
+
>>> whitened = whiten(features)
|
| 457 |
+
>>> # Find 2 clusters in the data
|
| 458 |
+
>>> codebook, distortion = kmeans(whitened, 2)
|
| 459 |
+
>>> # Plot whitened data and cluster centers in red
|
| 460 |
+
>>> plt.scatter(whitened[:, 0], whitened[:, 1])
|
| 461 |
+
>>> plt.scatter(codebook[:, 0], codebook[:, 1], c='r')
|
| 462 |
+
>>> plt.show()
|
| 463 |
+
|
| 464 |
+
"""
|
| 465 |
+
if isinstance(k_or_guess, int):
|
| 466 |
+
xp = array_namespace(obs)
|
| 467 |
+
else:
|
| 468 |
+
xp = array_namespace(obs, k_or_guess)
|
| 469 |
+
obs = _asarray(obs, xp=xp, check_finite=check_finite)
|
| 470 |
+
guess = _asarray(k_or_guess, xp=xp, check_finite=check_finite)
|
| 471 |
+
if iter < 1:
|
| 472 |
+
raise ValueError("iter must be at least 1, got %s" % iter)
|
| 473 |
+
|
| 474 |
+
# Determine whether a count (scalar) or an initial guess (array) was passed.
|
| 475 |
+
if size(guess) != 1:
|
| 476 |
+
if size(guess) < 1:
|
| 477 |
+
raise ValueError("Asked for 0 clusters. Initial book was %s" %
|
| 478 |
+
guess)
|
| 479 |
+
return _kmeans(obs, guess, thresh=thresh, xp=xp)
|
| 480 |
+
|
| 481 |
+
# k_or_guess is a scalar, now verify that it's an integer
|
| 482 |
+
k = int(guess)
|
| 483 |
+
if k != guess:
|
| 484 |
+
raise ValueError("If k_or_guess is a scalar, it must be an integer.")
|
| 485 |
+
if k < 1:
|
| 486 |
+
raise ValueError("Asked for %d clusters." % k)
|
| 487 |
+
|
| 488 |
+
rng = check_random_state(seed)
|
| 489 |
+
|
| 490 |
+
# initialize best distance value to a large value
|
| 491 |
+
best_dist = xp.inf
|
| 492 |
+
for i in range(iter):
|
| 493 |
+
# the initial code book is randomly selected from observations
|
| 494 |
+
guess = _kpoints(obs, k, rng, xp)
|
| 495 |
+
book, dist = _kmeans(obs, guess, thresh=thresh, xp=xp)
|
| 496 |
+
if dist < best_dist:
|
| 497 |
+
best_book = book
|
| 498 |
+
best_dist = dist
|
| 499 |
+
return best_book, best_dist
|
| 500 |
+
|
| 501 |
+
|
| 502 |
+
def _kpoints(data, k, rng, xp):
|
| 503 |
+
"""Pick k points at random in data (one row = one observation).
|
| 504 |
+
|
| 505 |
+
Parameters
|
| 506 |
+
----------
|
| 507 |
+
data : ndarray
|
| 508 |
+
Expect a rank 1 or 2 array. Rank 1 are assumed to describe one
|
| 509 |
+
dimensional data, rank 2 multidimensional data, in which case one
|
| 510 |
+
row is one observation.
|
| 511 |
+
k : int
|
| 512 |
+
Number of samples to generate.
|
| 513 |
+
rng : `numpy.random.Generator` or `numpy.random.RandomState`
|
| 514 |
+
Random number generator.
|
| 515 |
+
|
| 516 |
+
Returns
|
| 517 |
+
-------
|
| 518 |
+
x : ndarray
|
| 519 |
+
A 'k' by 'N' containing the initial centroids
|
| 520 |
+
|
| 521 |
+
"""
|
| 522 |
+
idx = rng.choice(data.shape[0], size=int(k), replace=False)
|
| 523 |
+
# convert to array with default integer dtype (avoids numpy#25607)
|
| 524 |
+
idx = xp.asarray(idx, dtype=xp.asarray([1]).dtype)
|
| 525 |
+
return xp.take(data, idx, axis=0)
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
def _krandinit(data, k, rng, xp):
|
| 529 |
+
"""Returns k samples of a random variable whose parameters depend on data.
|
| 530 |
+
|
| 531 |
+
More precisely, it returns k observations sampled from a Gaussian random
|
| 532 |
+
variable whose mean and covariances are the ones estimated from the data.
|
| 533 |
+
|
| 534 |
+
Parameters
|
| 535 |
+
----------
|
| 536 |
+
data : ndarray
|
| 537 |
+
Expect a rank 1 or 2 array. Rank 1 is assumed to describe 1-D
|
| 538 |
+
data, rank 2 multidimensional data, in which case one
|
| 539 |
+
row is one observation.
|
| 540 |
+
k : int
|
| 541 |
+
Number of samples to generate.
|
| 542 |
+
rng : `numpy.random.Generator` or `numpy.random.RandomState`
|
| 543 |
+
Random number generator.
|
| 544 |
+
|
| 545 |
+
Returns
|
| 546 |
+
-------
|
| 547 |
+
x : ndarray
|
| 548 |
+
A 'k' by 'N' containing the initial centroids
|
| 549 |
+
|
| 550 |
+
"""
|
| 551 |
+
mu = xp.mean(data, axis=0)
|
| 552 |
+
k = np.asarray(k)
|
| 553 |
+
|
| 554 |
+
if data.ndim == 1:
|
| 555 |
+
_cov = cov(data)
|
| 556 |
+
x = rng.standard_normal(size=k)
|
| 557 |
+
x = xp.asarray(x)
|
| 558 |
+
x *= xp.sqrt(_cov)
|
| 559 |
+
elif data.shape[1] > data.shape[0]:
|
| 560 |
+
# initialize when the covariance matrix is rank deficient
|
| 561 |
+
_, s, vh = xp.linalg.svd(data - mu, full_matrices=False)
|
| 562 |
+
x = rng.standard_normal(size=(k, size(s)))
|
| 563 |
+
x = xp.asarray(x)
|
| 564 |
+
sVh = s[:, None] * vh / xp.sqrt(data.shape[0] - xp.asarray(1.))
|
| 565 |
+
x = x @ sVh
|
| 566 |
+
else:
|
| 567 |
+
_cov = atleast_nd(cov(data.T), ndim=2)
|
| 568 |
+
|
| 569 |
+
# k rows, d cols (one row = one obs)
|
| 570 |
+
# Generate k sample of a random variable ~ Gaussian(mu, cov)
|
| 571 |
+
x = rng.standard_normal(size=(k, size(mu)))
|
| 572 |
+
x = xp.asarray(x)
|
| 573 |
+
x = x @ xp.linalg.cholesky(_cov).T
|
| 574 |
+
|
| 575 |
+
x += mu
|
| 576 |
+
return x
|
| 577 |
+
|
| 578 |
+
|
| 579 |
+
def _kpp(data, k, rng, xp):
|
| 580 |
+
""" Picks k points in the data based on the kmeans++ method.
|
| 581 |
+
|
| 582 |
+
Parameters
|
| 583 |
+
----------
|
| 584 |
+
data : ndarray
|
| 585 |
+
Expect a rank 1 or 2 array. Rank 1 is assumed to describe 1-D
|
| 586 |
+
data, rank 2 multidimensional data, in which case one
|
| 587 |
+
row is one observation.
|
| 588 |
+
k : int
|
| 589 |
+
Number of samples to generate.
|
| 590 |
+
rng : `numpy.random.Generator` or `numpy.random.RandomState`
|
| 591 |
+
Random number generator.
|
| 592 |
+
|
| 593 |
+
Returns
|
| 594 |
+
-------
|
| 595 |
+
init : ndarray
|
| 596 |
+
A 'k' by 'N' containing the initial centroids.
|
| 597 |
+
|
| 598 |
+
References
|
| 599 |
+
----------
|
| 600 |
+
.. [1] D. Arthur and S. Vassilvitskii, "k-means++: the advantages of
|
| 601 |
+
careful seeding", Proceedings of the Eighteenth Annual ACM-SIAM Symposium
|
| 602 |
+
on Discrete Algorithms, 2007.
|
| 603 |
+
"""
|
| 604 |
+
|
| 605 |
+
ndim = len(data.shape)
|
| 606 |
+
if ndim == 1:
|
| 607 |
+
data = data[:, None]
|
| 608 |
+
|
| 609 |
+
dims = data.shape[1]
|
| 610 |
+
|
| 611 |
+
init = xp.empty((int(k), dims))
|
| 612 |
+
|
| 613 |
+
for i in range(k):
|
| 614 |
+
if i == 0:
|
| 615 |
+
init[i, :] = data[rng_integers(rng, data.shape[0]), :]
|
| 616 |
+
|
| 617 |
+
else:
|
| 618 |
+
D2 = cdist(init[:i,:], data, metric='sqeuclidean').min(axis=0)
|
| 619 |
+
probs = D2/D2.sum()
|
| 620 |
+
cumprobs = probs.cumsum()
|
| 621 |
+
r = rng.uniform()
|
| 622 |
+
cumprobs = np.asarray(cumprobs)
|
| 623 |
+
init[i, :] = data[np.searchsorted(cumprobs, r), :]
|
| 624 |
+
|
| 625 |
+
if ndim == 1:
|
| 626 |
+
init = init[:, 0]
|
| 627 |
+
return init
|
| 628 |
+
|
| 629 |
+
|
| 630 |
+
_valid_init_meth = {'random': _krandinit, 'points': _kpoints, '++': _kpp}
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
def _missing_warn():
|
| 634 |
+
"""Print a warning when called."""
|
| 635 |
+
warnings.warn("One of the clusters is empty. "
|
| 636 |
+
"Re-run kmeans with a different initialization.",
|
| 637 |
+
stacklevel=3)
|
| 638 |
+
|
| 639 |
+
|
| 640 |
+
def _missing_raise():
|
| 641 |
+
"""Raise a ClusterError when called."""
|
| 642 |
+
raise ClusterError("One of the clusters is empty. "
|
| 643 |
+
"Re-run kmeans with a different initialization.")
|
| 644 |
+
|
| 645 |
+
|
| 646 |
+
_valid_miss_meth = {'warn': _missing_warn, 'raise': _missing_raise}
|
| 647 |
+
|
| 648 |
+
|
| 649 |
+
def kmeans2(data, k, iter=10, thresh=1e-5, minit='random',
|
| 650 |
+
missing='warn', check_finite=True, *, seed=None):
|
| 651 |
+
"""
|
| 652 |
+
Classify a set of observations into k clusters using the k-means algorithm.
|
| 653 |
+
|
| 654 |
+
The algorithm attempts to minimize the Euclidean distance between
|
| 655 |
+
observations and centroids. Several initialization methods are
|
| 656 |
+
included.
|
| 657 |
+
|
| 658 |
+
Parameters
|
| 659 |
+
----------
|
| 660 |
+
data : ndarray
|
| 661 |
+
A 'M' by 'N' array of 'M' observations in 'N' dimensions or a length
|
| 662 |
+
'M' array of 'M' 1-D observations.
|
| 663 |
+
k : int or ndarray
|
| 664 |
+
The number of clusters to form as well as the number of
|
| 665 |
+
centroids to generate. If `minit` initialization string is
|
| 666 |
+
'matrix', or if a ndarray is given instead, it is
|
| 667 |
+
interpreted as initial cluster to use instead.
|
| 668 |
+
iter : int, optional
|
| 669 |
+
Number of iterations of the k-means algorithm to run. Note
|
| 670 |
+
that this differs in meaning from the iters parameter to
|
| 671 |
+
the kmeans function.
|
| 672 |
+
thresh : float, optional
|
| 673 |
+
(not used yet)
|
| 674 |
+
minit : str, optional
|
| 675 |
+
Method for initialization. Available methods are 'random',
|
| 676 |
+
'points', '++' and 'matrix':
|
| 677 |
+
|
| 678 |
+
'random': generate k centroids from a Gaussian with mean and
|
| 679 |
+
variance estimated from the data.
|
| 680 |
+
|
| 681 |
+
'points': choose k observations (rows) at random from data for
|
| 682 |
+
the initial centroids.
|
| 683 |
+
|
| 684 |
+
'++': choose k observations accordingly to the kmeans++ method
|
| 685 |
+
(careful seeding)
|
| 686 |
+
|
| 687 |
+
'matrix': interpret the k parameter as a k by M (or length k
|
| 688 |
+
array for 1-D data) array of initial centroids.
|
| 689 |
+
missing : str, optional
|
| 690 |
+
Method to deal with empty clusters. Available methods are
|
| 691 |
+
'warn' and 'raise':
|
| 692 |
+
|
| 693 |
+
'warn': give a warning and continue.
|
| 694 |
+
|
| 695 |
+
'raise': raise an ClusterError and terminate the algorithm.
|
| 696 |
+
check_finite : bool, optional
|
| 697 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 698 |
+
Disabling may give a performance gain, but may result in problems
|
| 699 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 700 |
+
Default: True
|
| 701 |
+
seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
|
| 702 |
+
Seed for initializing the pseudo-random number generator.
|
| 703 |
+
If `seed` is None (or `numpy.random`), the `numpy.random.RandomState`
|
| 704 |
+
singleton is used.
|
| 705 |
+
If `seed` is an int, a new ``RandomState`` instance is used,
|
| 706 |
+
seeded with `seed`.
|
| 707 |
+
If `seed` is already a ``Generator`` or ``RandomState`` instance then
|
| 708 |
+
that instance is used.
|
| 709 |
+
The default is None.
|
| 710 |
+
|
| 711 |
+
Returns
|
| 712 |
+
-------
|
| 713 |
+
centroid : ndarray
|
| 714 |
+
A 'k' by 'N' array of centroids found at the last iteration of
|
| 715 |
+
k-means.
|
| 716 |
+
label : ndarray
|
| 717 |
+
label[i] is the code or index of the centroid the
|
| 718 |
+
ith observation is closest to.
|
| 719 |
+
|
| 720 |
+
See Also
|
| 721 |
+
--------
|
| 722 |
+
kmeans
|
| 723 |
+
|
| 724 |
+
References
|
| 725 |
+
----------
|
| 726 |
+
.. [1] D. Arthur and S. Vassilvitskii, "k-means++: the advantages of
|
| 727 |
+
careful seeding", Proceedings of the Eighteenth Annual ACM-SIAM Symposium
|
| 728 |
+
on Discrete Algorithms, 2007.
|
| 729 |
+
|
| 730 |
+
Examples
|
| 731 |
+
--------
|
| 732 |
+
>>> from scipy.cluster.vq import kmeans2
|
| 733 |
+
>>> import matplotlib.pyplot as plt
|
| 734 |
+
>>> import numpy as np
|
| 735 |
+
|
| 736 |
+
Create z, an array with shape (100, 2) containing a mixture of samples
|
| 737 |
+
from three multivariate normal distributions.
|
| 738 |
+
|
| 739 |
+
>>> rng = np.random.default_rng()
|
| 740 |
+
>>> a = rng.multivariate_normal([0, 6], [[2, 1], [1, 1.5]], size=45)
|
| 741 |
+
>>> b = rng.multivariate_normal([2, 0], [[1, -1], [-1, 3]], size=30)
|
| 742 |
+
>>> c = rng.multivariate_normal([6, 4], [[5, 0], [0, 1.2]], size=25)
|
| 743 |
+
>>> z = np.concatenate((a, b, c))
|
| 744 |
+
>>> rng.shuffle(z)
|
| 745 |
+
|
| 746 |
+
Compute three clusters.
|
| 747 |
+
|
| 748 |
+
>>> centroid, label = kmeans2(z, 3, minit='points')
|
| 749 |
+
>>> centroid
|
| 750 |
+
array([[ 2.22274463, -0.61666946], # may vary
|
| 751 |
+
[ 0.54069047, 5.86541444],
|
| 752 |
+
[ 6.73846769, 4.01991898]])
|
| 753 |
+
|
| 754 |
+
How many points are in each cluster?
|
| 755 |
+
|
| 756 |
+
>>> counts = np.bincount(label)
|
| 757 |
+
>>> counts
|
| 758 |
+
array([29, 51, 20]) # may vary
|
| 759 |
+
|
| 760 |
+
Plot the clusters.
|
| 761 |
+
|
| 762 |
+
>>> w0 = z[label == 0]
|
| 763 |
+
>>> w1 = z[label == 1]
|
| 764 |
+
>>> w2 = z[label == 2]
|
| 765 |
+
>>> plt.plot(w0[:, 0], w0[:, 1], 'o', alpha=0.5, label='cluster 0')
|
| 766 |
+
>>> plt.plot(w1[:, 0], w1[:, 1], 'd', alpha=0.5, label='cluster 1')
|
| 767 |
+
>>> plt.plot(w2[:, 0], w2[:, 1], 's', alpha=0.5, label='cluster 2')
|
| 768 |
+
>>> plt.plot(centroid[:, 0], centroid[:, 1], 'k*', label='centroids')
|
| 769 |
+
>>> plt.axis('equal')
|
| 770 |
+
>>> plt.legend(shadow=True)
|
| 771 |
+
>>> plt.show()
|
| 772 |
+
|
| 773 |
+
"""
|
| 774 |
+
if int(iter) < 1:
|
| 775 |
+
raise ValueError("Invalid iter (%s), "
|
| 776 |
+
"must be a positive integer." % iter)
|
| 777 |
+
try:
|
| 778 |
+
miss_meth = _valid_miss_meth[missing]
|
| 779 |
+
except KeyError as e:
|
| 780 |
+
raise ValueError(f"Unknown missing method {missing!r}") from e
|
| 781 |
+
|
| 782 |
+
if isinstance(k, int):
|
| 783 |
+
xp = array_namespace(data)
|
| 784 |
+
else:
|
| 785 |
+
xp = array_namespace(data, k)
|
| 786 |
+
data = _asarray(data, xp=xp, check_finite=check_finite)
|
| 787 |
+
code_book = copy(k, xp=xp)
|
| 788 |
+
if data.ndim == 1:
|
| 789 |
+
d = 1
|
| 790 |
+
elif data.ndim == 2:
|
| 791 |
+
d = data.shape[1]
|
| 792 |
+
else:
|
| 793 |
+
raise ValueError("Input of rank > 2 is not supported.")
|
| 794 |
+
|
| 795 |
+
if size(data) < 1 or size(code_book) < 1:
|
| 796 |
+
raise ValueError("Empty input is not supported.")
|
| 797 |
+
|
| 798 |
+
# If k is not a single value, it should be compatible with data's shape
|
| 799 |
+
if minit == 'matrix' or size(code_book) > 1:
|
| 800 |
+
if data.ndim != code_book.ndim:
|
| 801 |
+
raise ValueError("k array doesn't match data rank")
|
| 802 |
+
nc = code_book.shape[0]
|
| 803 |
+
if data.ndim > 1 and code_book.shape[1] != d:
|
| 804 |
+
raise ValueError("k array doesn't match data dimension")
|
| 805 |
+
else:
|
| 806 |
+
nc = int(code_book)
|
| 807 |
+
|
| 808 |
+
if nc < 1:
|
| 809 |
+
raise ValueError("Cannot ask kmeans2 for %d clusters"
|
| 810 |
+
" (k was %s)" % (nc, code_book))
|
| 811 |
+
elif nc != code_book:
|
| 812 |
+
warnings.warn("k was not an integer, was converted.", stacklevel=2)
|
| 813 |
+
|
| 814 |
+
try:
|
| 815 |
+
init_meth = _valid_init_meth[minit]
|
| 816 |
+
except KeyError as e:
|
| 817 |
+
raise ValueError(f"Unknown init method {minit!r}") from e
|
| 818 |
+
else:
|
| 819 |
+
rng = check_random_state(seed)
|
| 820 |
+
code_book = init_meth(data, code_book, rng, xp)
|
| 821 |
+
|
| 822 |
+
data = np.asarray(data)
|
| 823 |
+
code_book = np.asarray(code_book)
|
| 824 |
+
for i in range(iter):
|
| 825 |
+
# Compute the nearest neighbor for each obs using the current code book
|
| 826 |
+
label = vq(data, code_book, check_finite=check_finite)[0]
|
| 827 |
+
# Update the code book by computing centroids
|
| 828 |
+
new_code_book, has_members = _vq.update_cluster_means(data, label, nc)
|
| 829 |
+
if not has_members.all():
|
| 830 |
+
miss_meth()
|
| 831 |
+
# Set the empty clusters to their previous positions
|
| 832 |
+
new_code_book[~has_members] = code_book[~has_members]
|
| 833 |
+
code_book = new_code_book
|
| 834 |
+
|
| 835 |
+
return xp.asarray(code_book), xp.asarray(label)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/__init__.py
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
====================================
|
| 3 |
+
Linear algebra (:mod:`scipy.linalg`)
|
| 4 |
+
====================================
|
| 5 |
+
|
| 6 |
+
.. currentmodule:: scipy.linalg
|
| 7 |
+
|
| 8 |
+
.. toctree::
|
| 9 |
+
:hidden:
|
| 10 |
+
|
| 11 |
+
linalg.blas
|
| 12 |
+
linalg.cython_blas
|
| 13 |
+
linalg.cython_lapack
|
| 14 |
+
linalg.interpolative
|
| 15 |
+
linalg.lapack
|
| 16 |
+
|
| 17 |
+
Linear algebra functions.
|
| 18 |
+
|
| 19 |
+
.. eventually, we should replace the numpy.linalg HTML link with just `numpy.linalg`
|
| 20 |
+
|
| 21 |
+
.. seealso::
|
| 22 |
+
|
| 23 |
+
`numpy.linalg <https://www.numpy.org/devdocs/reference/routines.linalg.html>`__
|
| 24 |
+
for more linear algebra functions. Note that
|
| 25 |
+
although `scipy.linalg` imports most of them, identically named
|
| 26 |
+
functions from `scipy.linalg` may offer more or slightly differing
|
| 27 |
+
functionality.
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
Basics
|
| 31 |
+
======
|
| 32 |
+
|
| 33 |
+
.. autosummary::
|
| 34 |
+
:toctree: generated/
|
| 35 |
+
|
| 36 |
+
inv - Find the inverse of a square matrix
|
| 37 |
+
solve - Solve a linear system of equations
|
| 38 |
+
solve_banded - Solve a banded linear system
|
| 39 |
+
solveh_banded - Solve a Hermitian or symmetric banded system
|
| 40 |
+
solve_circulant - Solve a circulant system
|
| 41 |
+
solve_triangular - Solve a triangular matrix
|
| 42 |
+
solve_toeplitz - Solve a toeplitz matrix
|
| 43 |
+
matmul_toeplitz - Multiply a Toeplitz matrix with an array.
|
| 44 |
+
det - Find the determinant of a square matrix
|
| 45 |
+
norm - Matrix and vector norm
|
| 46 |
+
lstsq - Solve a linear least-squares problem
|
| 47 |
+
pinv - Pseudo-inverse (Moore-Penrose) using lstsq
|
| 48 |
+
pinvh - Pseudo-inverse of hermitian matrix
|
| 49 |
+
kron - Kronecker product of two arrays
|
| 50 |
+
khatri_rao - Khatri-Rao product of two arrays
|
| 51 |
+
orthogonal_procrustes - Solve an orthogonal Procrustes problem
|
| 52 |
+
matrix_balance - Balance matrix entries with a similarity transformation
|
| 53 |
+
subspace_angles - Compute the subspace angles between two matrices
|
| 54 |
+
bandwidth - Return the lower and upper bandwidth of an array
|
| 55 |
+
issymmetric - Check if a square 2D array is symmetric
|
| 56 |
+
ishermitian - Check if a square 2D array is Hermitian
|
| 57 |
+
LinAlgError
|
| 58 |
+
LinAlgWarning
|
| 59 |
+
|
| 60 |
+
Eigenvalue Problems
|
| 61 |
+
===================
|
| 62 |
+
|
| 63 |
+
.. autosummary::
|
| 64 |
+
:toctree: generated/
|
| 65 |
+
|
| 66 |
+
eig - Find the eigenvalues and eigenvectors of a square matrix
|
| 67 |
+
eigvals - Find just the eigenvalues of a square matrix
|
| 68 |
+
eigh - Find the e-vals and e-vectors of a Hermitian or symmetric matrix
|
| 69 |
+
eigvalsh - Find just the eigenvalues of a Hermitian or symmetric matrix
|
| 70 |
+
eig_banded - Find the eigenvalues and eigenvectors of a banded matrix
|
| 71 |
+
eigvals_banded - Find just the eigenvalues of a banded matrix
|
| 72 |
+
eigh_tridiagonal - Find the eigenvalues and eigenvectors of a tridiagonal matrix
|
| 73 |
+
eigvalsh_tridiagonal - Find just the eigenvalues of a tridiagonal matrix
|
| 74 |
+
|
| 75 |
+
Decompositions
|
| 76 |
+
==============
|
| 77 |
+
|
| 78 |
+
.. autosummary::
|
| 79 |
+
:toctree: generated/
|
| 80 |
+
|
| 81 |
+
lu - LU decomposition of a matrix
|
| 82 |
+
lu_factor - LU decomposition returning unordered matrix and pivots
|
| 83 |
+
lu_solve - Solve Ax=b using back substitution with output of lu_factor
|
| 84 |
+
svd - Singular value decomposition of a matrix
|
| 85 |
+
svdvals - Singular values of a matrix
|
| 86 |
+
diagsvd - Construct matrix of singular values from output of svd
|
| 87 |
+
orth - Construct orthonormal basis for the range of A using svd
|
| 88 |
+
null_space - Construct orthonormal basis for the null space of A using svd
|
| 89 |
+
ldl - LDL.T decomposition of a Hermitian or a symmetric matrix.
|
| 90 |
+
cholesky - Cholesky decomposition of a matrix
|
| 91 |
+
cholesky_banded - Cholesky decomp. of a sym. or Hermitian banded matrix
|
| 92 |
+
cho_factor - Cholesky decomposition for use in solving a linear system
|
| 93 |
+
cho_solve - Solve previously factored linear system
|
| 94 |
+
cho_solve_banded - Solve previously factored banded linear system
|
| 95 |
+
polar - Compute the polar decomposition.
|
| 96 |
+
qr - QR decomposition of a matrix
|
| 97 |
+
qr_multiply - QR decomposition and multiplication by Q
|
| 98 |
+
qr_update - Rank k QR update
|
| 99 |
+
qr_delete - QR downdate on row or column deletion
|
| 100 |
+
qr_insert - QR update on row or column insertion
|
| 101 |
+
rq - RQ decomposition of a matrix
|
| 102 |
+
qz - QZ decomposition of a pair of matrices
|
| 103 |
+
ordqz - QZ decomposition of a pair of matrices with reordering
|
| 104 |
+
schur - Schur decomposition of a matrix
|
| 105 |
+
rsf2csf - Real to complex Schur form
|
| 106 |
+
hessenberg - Hessenberg form of a matrix
|
| 107 |
+
cdf2rdf - Complex diagonal form to real diagonal block form
|
| 108 |
+
cossin - Cosine sine decomposition of a unitary or orthogonal matrix
|
| 109 |
+
|
| 110 |
+
.. seealso::
|
| 111 |
+
|
| 112 |
+
`scipy.linalg.interpolative` -- Interpolative matrix decompositions
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
Matrix Functions
|
| 116 |
+
================
|
| 117 |
+
|
| 118 |
+
.. autosummary::
|
| 119 |
+
:toctree: generated/
|
| 120 |
+
|
| 121 |
+
expm - Matrix exponential
|
| 122 |
+
logm - Matrix logarithm
|
| 123 |
+
cosm - Matrix cosine
|
| 124 |
+
sinm - Matrix sine
|
| 125 |
+
tanm - Matrix tangent
|
| 126 |
+
coshm - Matrix hyperbolic cosine
|
| 127 |
+
sinhm - Matrix hyperbolic sine
|
| 128 |
+
tanhm - Matrix hyperbolic tangent
|
| 129 |
+
signm - Matrix sign
|
| 130 |
+
sqrtm - Matrix square root
|
| 131 |
+
funm - Evaluating an arbitrary matrix function
|
| 132 |
+
expm_frechet - Frechet derivative of the matrix exponential
|
| 133 |
+
expm_cond - Relative condition number of expm in the Frobenius norm
|
| 134 |
+
fractional_matrix_power - Fractional matrix power
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
Matrix Equation Solvers
|
| 138 |
+
=======================
|
| 139 |
+
|
| 140 |
+
.. autosummary::
|
| 141 |
+
:toctree: generated/
|
| 142 |
+
|
| 143 |
+
solve_sylvester - Solve the Sylvester matrix equation
|
| 144 |
+
solve_continuous_are - Solve the continuous-time algebraic Riccati equation
|
| 145 |
+
solve_discrete_are - Solve the discrete-time algebraic Riccati equation
|
| 146 |
+
solve_continuous_lyapunov - Solve the continuous-time Lyapunov equation
|
| 147 |
+
solve_discrete_lyapunov - Solve the discrete-time Lyapunov equation
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
Sketches and Random Projections
|
| 151 |
+
===============================
|
| 152 |
+
|
| 153 |
+
.. autosummary::
|
| 154 |
+
:toctree: generated/
|
| 155 |
+
|
| 156 |
+
clarkson_woodruff_transform - Applies the Clarkson Woodruff Sketch (a.k.a CountMin Sketch)
|
| 157 |
+
|
| 158 |
+
Special Matrices
|
| 159 |
+
================
|
| 160 |
+
|
| 161 |
+
.. autosummary::
|
| 162 |
+
:toctree: generated/
|
| 163 |
+
|
| 164 |
+
block_diag - Construct a block diagonal matrix from submatrices
|
| 165 |
+
circulant - Circulant matrix
|
| 166 |
+
companion - Companion matrix
|
| 167 |
+
convolution_matrix - Convolution matrix
|
| 168 |
+
dft - Discrete Fourier transform matrix
|
| 169 |
+
fiedler - Fiedler matrix
|
| 170 |
+
fiedler_companion - Fiedler companion matrix
|
| 171 |
+
hadamard - Hadamard matrix of order 2**n
|
| 172 |
+
hankel - Hankel matrix
|
| 173 |
+
helmert - Helmert matrix
|
| 174 |
+
hilbert - Hilbert matrix
|
| 175 |
+
invhilbert - Inverse Hilbert matrix
|
| 176 |
+
leslie - Leslie matrix
|
| 177 |
+
pascal - Pascal matrix
|
| 178 |
+
invpascal - Inverse Pascal matrix
|
| 179 |
+
toeplitz - Toeplitz matrix
|
| 180 |
+
|
| 181 |
+
Low-level routines
|
| 182 |
+
==================
|
| 183 |
+
|
| 184 |
+
.. autosummary::
|
| 185 |
+
:toctree: generated/
|
| 186 |
+
|
| 187 |
+
get_blas_funcs
|
| 188 |
+
get_lapack_funcs
|
| 189 |
+
find_best_blas_type
|
| 190 |
+
|
| 191 |
+
.. seealso::
|
| 192 |
+
|
| 193 |
+
`scipy.linalg.blas` -- Low-level BLAS functions
|
| 194 |
+
|
| 195 |
+
`scipy.linalg.lapack` -- Low-level LAPACK functions
|
| 196 |
+
|
| 197 |
+
`scipy.linalg.cython_blas` -- Low-level BLAS functions for Cython
|
| 198 |
+
|
| 199 |
+
`scipy.linalg.cython_lapack` -- Low-level LAPACK functions for Cython
|
| 200 |
+
|
| 201 |
+
""" # noqa: E501
|
| 202 |
+
|
| 203 |
+
from ._misc import *
|
| 204 |
+
from ._cythonized_array_utils import *
|
| 205 |
+
from ._basic import *
|
| 206 |
+
from ._decomp import *
|
| 207 |
+
from ._decomp_lu import *
|
| 208 |
+
from ._decomp_ldl import *
|
| 209 |
+
from ._decomp_cholesky import *
|
| 210 |
+
from ._decomp_qr import *
|
| 211 |
+
from ._decomp_qz import *
|
| 212 |
+
from ._decomp_svd import *
|
| 213 |
+
from ._decomp_schur import *
|
| 214 |
+
from ._decomp_polar import *
|
| 215 |
+
from ._matfuncs import *
|
| 216 |
+
from .blas import *
|
| 217 |
+
from .lapack import *
|
| 218 |
+
from ._special_matrices import *
|
| 219 |
+
from ._solvers import *
|
| 220 |
+
from ._procrustes import *
|
| 221 |
+
from ._decomp_update import *
|
| 222 |
+
from ._sketches import *
|
| 223 |
+
from ._decomp_cossin import *
|
| 224 |
+
|
| 225 |
+
# Deprecated namespaces, to be removed in v2.0.0
|
| 226 |
+
from . import (
|
| 227 |
+
decomp, decomp_cholesky, decomp_lu, decomp_qr, decomp_svd, decomp_schur,
|
| 228 |
+
basic, misc, special_matrices, matfuncs,
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
__all__ = [s for s in dir() if not s.startswith('_')]
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
from scipy._lib._testutils import PytestTester
|
| 235 |
+
test = PytestTester(__name__)
|
| 236 |
+
del PytestTester
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_basic.py
ADDED
|
@@ -0,0 +1,1919 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Author: Pearu Peterson, March 2002
|
| 3 |
+
#
|
| 4 |
+
# w/ additions by Travis Oliphant, March 2002
|
| 5 |
+
# and Jake Vanderplas, August 2012
|
| 6 |
+
|
| 7 |
+
from warnings import warn
|
| 8 |
+
from itertools import product
|
| 9 |
+
import numpy as np
|
| 10 |
+
from numpy import atleast_1d, atleast_2d
|
| 11 |
+
from .lapack import get_lapack_funcs, _compute_lwork
|
| 12 |
+
from ._misc import LinAlgError, _datacopied, LinAlgWarning
|
| 13 |
+
from ._decomp import _asarray_validated
|
| 14 |
+
from . import _decomp, _decomp_svd
|
| 15 |
+
from ._solve_toeplitz import levinson
|
| 16 |
+
from ._cythonized_array_utils import find_det_from_lu
|
| 17 |
+
from scipy._lib.deprecation import _NoValue, _deprecate_positional_args
|
| 18 |
+
|
| 19 |
+
__all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
|
| 20 |
+
'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
|
| 21 |
+
'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz']
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# The numpy facilities for type-casting checks are too slow for small sized
|
| 25 |
+
# arrays and eat away the time budget for the checkups. Here we set a
|
| 26 |
+
# precomputed dict container of the numpy.can_cast() table.
|
| 27 |
+
|
| 28 |
+
# It can be used to determine quickly what a dtype can be cast to LAPACK
|
| 29 |
+
# compatible types, i.e., 'float32, float64, complex64, complex128'.
|
| 30 |
+
# Then it can be checked via "casting_dict[arr.dtype.char]"
|
| 31 |
+
lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
|
| 32 |
+
for x in np.typecodes['All']}
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# Linear equations
|
| 36 |
+
def _solve_check(n, info, lamch=None, rcond=None):
|
| 37 |
+
""" Check arguments during the different steps of the solution phase """
|
| 38 |
+
if info < 0:
|
| 39 |
+
raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument.')
|
| 40 |
+
elif 0 < info:
|
| 41 |
+
raise LinAlgError('Matrix is singular.')
|
| 42 |
+
|
| 43 |
+
if lamch is None:
|
| 44 |
+
return
|
| 45 |
+
E = lamch('E')
|
| 46 |
+
if rcond < E:
|
| 47 |
+
warn(f'Ill-conditioned matrix (rcond={rcond:.6g}): '
|
| 48 |
+
'result may not be accurate.',
|
| 49 |
+
LinAlgWarning, stacklevel=3)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def solve(a, b, lower=False, overwrite_a=False,
|
| 53 |
+
overwrite_b=False, check_finite=True, assume_a='gen',
|
| 54 |
+
transposed=False):
|
| 55 |
+
"""
|
| 56 |
+
Solves the linear equation set ``a @ x == b`` for the unknown ``x``
|
| 57 |
+
for square `a` matrix.
|
| 58 |
+
|
| 59 |
+
If the data matrix is known to be a particular type then supplying the
|
| 60 |
+
corresponding string to ``assume_a`` key chooses the dedicated solver.
|
| 61 |
+
The available options are
|
| 62 |
+
|
| 63 |
+
=================== ========
|
| 64 |
+
generic matrix 'gen'
|
| 65 |
+
symmetric 'sym'
|
| 66 |
+
hermitian 'her'
|
| 67 |
+
positive definite 'pos'
|
| 68 |
+
=================== ========
|
| 69 |
+
|
| 70 |
+
If omitted, ``'gen'`` is the default structure.
|
| 71 |
+
|
| 72 |
+
The datatype of the arrays define which solver is called regardless
|
| 73 |
+
of the values. In other words, even when the complex array entries have
|
| 74 |
+
precisely zero imaginary parts, the complex solver will be called based
|
| 75 |
+
on the data type of the array.
|
| 76 |
+
|
| 77 |
+
Parameters
|
| 78 |
+
----------
|
| 79 |
+
a : (N, N) array_like
|
| 80 |
+
Square input data
|
| 81 |
+
b : (N, NRHS) array_like
|
| 82 |
+
Input data for the right hand side.
|
| 83 |
+
lower : bool, default: False
|
| 84 |
+
Ignored if ``assume_a == 'gen'`` (the default). If True, the
|
| 85 |
+
calculation uses only the data in the lower triangle of `a`;
|
| 86 |
+
entries above the diagonal are ignored. If False (default), the
|
| 87 |
+
calculation uses only the data in the upper triangle of `a`; entries
|
| 88 |
+
below the diagonal are ignored.
|
| 89 |
+
overwrite_a : bool, default: False
|
| 90 |
+
Allow overwriting data in `a` (may enhance performance).
|
| 91 |
+
overwrite_b : bool, default: False
|
| 92 |
+
Allow overwriting data in `b` (may enhance performance).
|
| 93 |
+
check_finite : bool, default: True
|
| 94 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 95 |
+
Disabling may give a performance gain, but may result in problems
|
| 96 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 97 |
+
assume_a : str, {'gen', 'sym', 'her', 'pos'}
|
| 98 |
+
Valid entries are explained above.
|
| 99 |
+
transposed : bool, default: False
|
| 100 |
+
If True, solve ``a.T @ x == b``. Raises `NotImplementedError`
|
| 101 |
+
for complex `a`.
|
| 102 |
+
|
| 103 |
+
Returns
|
| 104 |
+
-------
|
| 105 |
+
x : (N, NRHS) ndarray
|
| 106 |
+
The solution array.
|
| 107 |
+
|
| 108 |
+
Raises
|
| 109 |
+
------
|
| 110 |
+
ValueError
|
| 111 |
+
If size mismatches detected or input a is not square.
|
| 112 |
+
LinAlgError
|
| 113 |
+
If the matrix is singular.
|
| 114 |
+
LinAlgWarning
|
| 115 |
+
If an ill-conditioned input a is detected.
|
| 116 |
+
NotImplementedError
|
| 117 |
+
If transposed is True and input a is a complex matrix.
|
| 118 |
+
|
| 119 |
+
Notes
|
| 120 |
+
-----
|
| 121 |
+
If the input b matrix is a 1-D array with N elements, when supplied
|
| 122 |
+
together with an NxN input a, it is assumed as a valid column vector
|
| 123 |
+
despite the apparent size mismatch. This is compatible with the
|
| 124 |
+
numpy.dot() behavior and the returned result is still 1-D array.
|
| 125 |
+
|
| 126 |
+
The generic, symmetric, Hermitian and positive definite solutions are
|
| 127 |
+
obtained via calling ?GESV, ?SYSV, ?HESV, and ?POSV routines of
|
| 128 |
+
LAPACK respectively.
|
| 129 |
+
|
| 130 |
+
Examples
|
| 131 |
+
--------
|
| 132 |
+
Given `a` and `b`, solve for `x`:
|
| 133 |
+
|
| 134 |
+
>>> import numpy as np
|
| 135 |
+
>>> a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]])
|
| 136 |
+
>>> b = np.array([2, 4, -1])
|
| 137 |
+
>>> from scipy import linalg
|
| 138 |
+
>>> x = linalg.solve(a, b)
|
| 139 |
+
>>> x
|
| 140 |
+
array([ 2., -2., 9.])
|
| 141 |
+
>>> np.dot(a, x) == b
|
| 142 |
+
array([ True, True, True], dtype=bool)
|
| 143 |
+
|
| 144 |
+
"""
|
| 145 |
+
# Flags for 1-D or N-D right-hand side
|
| 146 |
+
b_is_1D = False
|
| 147 |
+
|
| 148 |
+
a1 = atleast_2d(_asarray_validated(a, check_finite=check_finite))
|
| 149 |
+
b1 = atleast_1d(_asarray_validated(b, check_finite=check_finite))
|
| 150 |
+
n = a1.shape[0]
|
| 151 |
+
|
| 152 |
+
overwrite_a = overwrite_a or _datacopied(a1, a)
|
| 153 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 154 |
+
|
| 155 |
+
if a1.shape[0] != a1.shape[1]:
|
| 156 |
+
raise ValueError('Input a needs to be a square matrix.')
|
| 157 |
+
|
| 158 |
+
if n != b1.shape[0]:
|
| 159 |
+
# Last chance to catch 1x1 scalar a and 1-D b arrays
|
| 160 |
+
if not (n == 1 and b1.size != 0):
|
| 161 |
+
raise ValueError('Input b has to have same number of rows as '
|
| 162 |
+
'input a')
|
| 163 |
+
|
| 164 |
+
# accommodate empty arrays
|
| 165 |
+
if b1.size == 0:
|
| 166 |
+
return np.asfortranarray(b1.copy())
|
| 167 |
+
|
| 168 |
+
# regularize 1-D b arrays to 2D
|
| 169 |
+
if b1.ndim == 1:
|
| 170 |
+
if n == 1:
|
| 171 |
+
b1 = b1[None, :]
|
| 172 |
+
else:
|
| 173 |
+
b1 = b1[:, None]
|
| 174 |
+
b_is_1D = True
|
| 175 |
+
|
| 176 |
+
if assume_a not in ('gen', 'sym', 'her', 'pos'):
|
| 177 |
+
raise ValueError(f'{assume_a} is not a recognized matrix structure')
|
| 178 |
+
|
| 179 |
+
# for a real matrix, describe it as "symmetric", not "hermitian"
|
| 180 |
+
# (lapack doesn't know what to do with real hermitian matrices)
|
| 181 |
+
if assume_a == 'her' and not np.iscomplexobj(a1):
|
| 182 |
+
assume_a = 'sym'
|
| 183 |
+
|
| 184 |
+
# Get the correct lamch function.
|
| 185 |
+
# The LAMCH functions only exists for S and D
|
| 186 |
+
# So for complex values we have to convert to real/double.
|
| 187 |
+
if a1.dtype.char in 'fF': # single precision
|
| 188 |
+
lamch = get_lapack_funcs('lamch', dtype='f')
|
| 189 |
+
else:
|
| 190 |
+
lamch = get_lapack_funcs('lamch', dtype='d')
|
| 191 |
+
|
| 192 |
+
# Currently we do not have the other forms of the norm calculators
|
| 193 |
+
# lansy, lanpo, lanhe.
|
| 194 |
+
# However, in any case they only reduce computations slightly...
|
| 195 |
+
lange = get_lapack_funcs('lange', (a1,))
|
| 196 |
+
|
| 197 |
+
# Since the I-norm and 1-norm are the same for symmetric matrices
|
| 198 |
+
# we can collect them all in this one call
|
| 199 |
+
# Note however, that when issuing 'gen' and form!='none', then
|
| 200 |
+
# the I-norm should be used
|
| 201 |
+
if transposed:
|
| 202 |
+
trans = 1
|
| 203 |
+
norm = 'I'
|
| 204 |
+
if np.iscomplexobj(a1):
|
| 205 |
+
raise NotImplementedError('scipy.linalg.solve can currently '
|
| 206 |
+
'not solve a^T x = b or a^H x = b '
|
| 207 |
+
'for complex matrices.')
|
| 208 |
+
else:
|
| 209 |
+
trans = 0
|
| 210 |
+
norm = '1'
|
| 211 |
+
|
| 212 |
+
anorm = lange(norm, a1)
|
| 213 |
+
|
| 214 |
+
# Generalized case 'gesv'
|
| 215 |
+
if assume_a == 'gen':
|
| 216 |
+
gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'),
|
| 217 |
+
(a1, b1))
|
| 218 |
+
lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a)
|
| 219 |
+
_solve_check(n, info)
|
| 220 |
+
x, info = getrs(lu, ipvt, b1,
|
| 221 |
+
trans=trans, overwrite_b=overwrite_b)
|
| 222 |
+
_solve_check(n, info)
|
| 223 |
+
rcond, info = gecon(lu, anorm, norm=norm)
|
| 224 |
+
# Hermitian case 'hesv'
|
| 225 |
+
elif assume_a == 'her':
|
| 226 |
+
hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv',
|
| 227 |
+
'hesv_lwork'), (a1, b1))
|
| 228 |
+
lwork = _compute_lwork(hesv_lw, n, lower)
|
| 229 |
+
lu, ipvt, x, info = hesv(a1, b1, lwork=lwork,
|
| 230 |
+
lower=lower,
|
| 231 |
+
overwrite_a=overwrite_a,
|
| 232 |
+
overwrite_b=overwrite_b)
|
| 233 |
+
_solve_check(n, info)
|
| 234 |
+
rcond, info = hecon(lu, ipvt, anorm)
|
| 235 |
+
# Symmetric case 'sysv'
|
| 236 |
+
elif assume_a == 'sym':
|
| 237 |
+
sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv',
|
| 238 |
+
'sysv_lwork'), (a1, b1))
|
| 239 |
+
lwork = _compute_lwork(sysv_lw, n, lower)
|
| 240 |
+
lu, ipvt, x, info = sysv(a1, b1, lwork=lwork,
|
| 241 |
+
lower=lower,
|
| 242 |
+
overwrite_a=overwrite_a,
|
| 243 |
+
overwrite_b=overwrite_b)
|
| 244 |
+
_solve_check(n, info)
|
| 245 |
+
rcond, info = sycon(lu, ipvt, anorm)
|
| 246 |
+
# Positive definite case 'posv'
|
| 247 |
+
else:
|
| 248 |
+
pocon, posv = get_lapack_funcs(('pocon', 'posv'),
|
| 249 |
+
(a1, b1))
|
| 250 |
+
lu, x, info = posv(a1, b1, lower=lower,
|
| 251 |
+
overwrite_a=overwrite_a,
|
| 252 |
+
overwrite_b=overwrite_b)
|
| 253 |
+
_solve_check(n, info)
|
| 254 |
+
rcond, info = pocon(lu, anorm)
|
| 255 |
+
|
| 256 |
+
_solve_check(n, info, lamch, rcond)
|
| 257 |
+
|
| 258 |
+
if b_is_1D:
|
| 259 |
+
x = x.ravel()
|
| 260 |
+
|
| 261 |
+
return x
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False,
|
| 265 |
+
overwrite_b=False, check_finite=True):
|
| 266 |
+
"""
|
| 267 |
+
Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.
|
| 268 |
+
|
| 269 |
+
Parameters
|
| 270 |
+
----------
|
| 271 |
+
a : (M, M) array_like
|
| 272 |
+
A triangular matrix
|
| 273 |
+
b : (M,) or (M, N) array_like
|
| 274 |
+
Right-hand side matrix in `a x = b`
|
| 275 |
+
lower : bool, optional
|
| 276 |
+
Use only data contained in the lower triangle of `a`.
|
| 277 |
+
Default is to use upper triangle.
|
| 278 |
+
trans : {0, 1, 2, 'N', 'T', 'C'}, optional
|
| 279 |
+
Type of system to solve:
|
| 280 |
+
|
| 281 |
+
======== =========
|
| 282 |
+
trans system
|
| 283 |
+
======== =========
|
| 284 |
+
0 or 'N' a x = b
|
| 285 |
+
1 or 'T' a^T x = b
|
| 286 |
+
2 or 'C' a^H x = b
|
| 287 |
+
======== =========
|
| 288 |
+
unit_diagonal : bool, optional
|
| 289 |
+
If True, diagonal elements of `a` are assumed to be 1 and
|
| 290 |
+
will not be referenced.
|
| 291 |
+
overwrite_b : bool, optional
|
| 292 |
+
Allow overwriting data in `b` (may enhance performance)
|
| 293 |
+
check_finite : bool, optional
|
| 294 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 295 |
+
Disabling may give a performance gain, but may result in problems
|
| 296 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 297 |
+
|
| 298 |
+
Returns
|
| 299 |
+
-------
|
| 300 |
+
x : (M,) or (M, N) ndarray
|
| 301 |
+
Solution to the system `a x = b`. Shape of return matches `b`.
|
| 302 |
+
|
| 303 |
+
Raises
|
| 304 |
+
------
|
| 305 |
+
LinAlgError
|
| 306 |
+
If `a` is singular
|
| 307 |
+
|
| 308 |
+
Notes
|
| 309 |
+
-----
|
| 310 |
+
.. versionadded:: 0.9.0
|
| 311 |
+
|
| 312 |
+
Examples
|
| 313 |
+
--------
|
| 314 |
+
Solve the lower triangular system a x = b, where::
|
| 315 |
+
|
| 316 |
+
[3 0 0 0] [4]
|
| 317 |
+
a = [2 1 0 0] b = [2]
|
| 318 |
+
[1 0 1 0] [4]
|
| 319 |
+
[1 1 1 1] [2]
|
| 320 |
+
|
| 321 |
+
>>> import numpy as np
|
| 322 |
+
>>> from scipy.linalg import solve_triangular
|
| 323 |
+
>>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]])
|
| 324 |
+
>>> b = np.array([4, 2, 4, 2])
|
| 325 |
+
>>> x = solve_triangular(a, b, lower=True)
|
| 326 |
+
>>> x
|
| 327 |
+
array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333])
|
| 328 |
+
>>> a.dot(x) # Check the result
|
| 329 |
+
array([ 4., 2., 4., 2.])
|
| 330 |
+
|
| 331 |
+
"""
|
| 332 |
+
|
| 333 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 334 |
+
b1 = _asarray_validated(b, check_finite=check_finite)
|
| 335 |
+
if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
|
| 336 |
+
raise ValueError('expected square matrix')
|
| 337 |
+
if a1.shape[0] != b1.shape[0]:
|
| 338 |
+
raise ValueError(f'shapes of a {a1.shape} and b {b1.shape} are incompatible')
|
| 339 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 340 |
+
|
| 341 |
+
trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans)
|
| 342 |
+
trtrs, = get_lapack_funcs(('trtrs',), (a1, b1))
|
| 343 |
+
if a1.flags.f_contiguous or trans == 2:
|
| 344 |
+
x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower,
|
| 345 |
+
trans=trans, unitdiag=unit_diagonal)
|
| 346 |
+
else:
|
| 347 |
+
# transposed system is solved since trtrs expects Fortran ordering
|
| 348 |
+
x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower,
|
| 349 |
+
trans=not trans, unitdiag=unit_diagonal)
|
| 350 |
+
|
| 351 |
+
if info == 0:
|
| 352 |
+
return x
|
| 353 |
+
if info > 0:
|
| 354 |
+
raise LinAlgError("singular matrix: resolution failed at diagonal %d" %
|
| 355 |
+
(info-1))
|
| 356 |
+
raise ValueError('illegal value in %dth argument of internal trtrs' %
|
| 357 |
+
(-info))
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False,
|
| 361 |
+
check_finite=True):
|
| 362 |
+
"""
|
| 363 |
+
Solve the equation a x = b for x, assuming a is banded matrix.
|
| 364 |
+
|
| 365 |
+
The matrix a is stored in `ab` using the matrix diagonal ordered form::
|
| 366 |
+
|
| 367 |
+
ab[u + i - j, j] == a[i,j]
|
| 368 |
+
|
| 369 |
+
Example of `ab` (shape of a is (6,6), `u` =1, `l` =2)::
|
| 370 |
+
|
| 371 |
+
* a01 a12 a23 a34 a45
|
| 372 |
+
a00 a11 a22 a33 a44 a55
|
| 373 |
+
a10 a21 a32 a43 a54 *
|
| 374 |
+
a20 a31 a42 a53 * *
|
| 375 |
+
|
| 376 |
+
Parameters
|
| 377 |
+
----------
|
| 378 |
+
(l, u) : (integer, integer)
|
| 379 |
+
Number of non-zero lower and upper diagonals
|
| 380 |
+
ab : (`l` + `u` + 1, M) array_like
|
| 381 |
+
Banded matrix
|
| 382 |
+
b : (M,) or (M, K) array_like
|
| 383 |
+
Right-hand side
|
| 384 |
+
overwrite_ab : bool, optional
|
| 385 |
+
Discard data in `ab` (may enhance performance)
|
| 386 |
+
overwrite_b : bool, optional
|
| 387 |
+
Discard data in `b` (may enhance performance)
|
| 388 |
+
check_finite : bool, optional
|
| 389 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 390 |
+
Disabling may give a performance gain, but may result in problems
|
| 391 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 392 |
+
|
| 393 |
+
Returns
|
| 394 |
+
-------
|
| 395 |
+
x : (M,) or (M, K) ndarray
|
| 396 |
+
The solution to the system a x = b. Returned shape depends on the
|
| 397 |
+
shape of `b`.
|
| 398 |
+
|
| 399 |
+
Examples
|
| 400 |
+
--------
|
| 401 |
+
Solve the banded system a x = b, where::
|
| 402 |
+
|
| 403 |
+
[5 2 -1 0 0] [0]
|
| 404 |
+
[1 4 2 -1 0] [1]
|
| 405 |
+
a = [0 1 3 2 -1] b = [2]
|
| 406 |
+
[0 0 1 2 2] [2]
|
| 407 |
+
[0 0 0 1 1] [3]
|
| 408 |
+
|
| 409 |
+
There is one nonzero diagonal below the main diagonal (l = 1), and
|
| 410 |
+
two above (u = 2). The diagonal banded form of the matrix is::
|
| 411 |
+
|
| 412 |
+
[* * -1 -1 -1]
|
| 413 |
+
ab = [* 2 2 2 2]
|
| 414 |
+
[5 4 3 2 1]
|
| 415 |
+
[1 1 1 1 *]
|
| 416 |
+
|
| 417 |
+
>>> import numpy as np
|
| 418 |
+
>>> from scipy.linalg import solve_banded
|
| 419 |
+
>>> ab = np.array([[0, 0, -1, -1, -1],
|
| 420 |
+
... [0, 2, 2, 2, 2],
|
| 421 |
+
... [5, 4, 3, 2, 1],
|
| 422 |
+
... [1, 1, 1, 1, 0]])
|
| 423 |
+
>>> b = np.array([0, 1, 2, 2, 3])
|
| 424 |
+
>>> x = solve_banded((1, 2), ab, b)
|
| 425 |
+
>>> x
|
| 426 |
+
array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ])
|
| 427 |
+
|
| 428 |
+
"""
|
| 429 |
+
|
| 430 |
+
a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True)
|
| 431 |
+
b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True)
|
| 432 |
+
# Validate shapes.
|
| 433 |
+
if a1.shape[-1] != b1.shape[0]:
|
| 434 |
+
raise ValueError("shapes of ab and b are not compatible.")
|
| 435 |
+
(nlower, nupper) = l_and_u
|
| 436 |
+
if nlower + nupper + 1 != a1.shape[0]:
|
| 437 |
+
raise ValueError("invalid values for the number of lower and upper "
|
| 438 |
+
"diagonals: l+u+1 (%d) does not equal ab.shape[0] "
|
| 439 |
+
"(%d)" % (nlower + nupper + 1, ab.shape[0]))
|
| 440 |
+
|
| 441 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 442 |
+
if a1.shape[-1] == 1:
|
| 443 |
+
b2 = np.array(b1, copy=(not overwrite_b))
|
| 444 |
+
b2 /= a1[1, 0]
|
| 445 |
+
return b2
|
| 446 |
+
if nlower == nupper == 1:
|
| 447 |
+
overwrite_ab = overwrite_ab or _datacopied(a1, ab)
|
| 448 |
+
gtsv, = get_lapack_funcs(('gtsv',), (a1, b1))
|
| 449 |
+
du = a1[0, 1:]
|
| 450 |
+
d = a1[1, :]
|
| 451 |
+
dl = a1[2, :-1]
|
| 452 |
+
du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab,
|
| 453 |
+
overwrite_ab, overwrite_b)
|
| 454 |
+
else:
|
| 455 |
+
gbsv, = get_lapack_funcs(('gbsv',), (a1, b1))
|
| 456 |
+
a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype)
|
| 457 |
+
a2[nlower:, :] = a1
|
| 458 |
+
lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True,
|
| 459 |
+
overwrite_b=overwrite_b)
|
| 460 |
+
if info == 0:
|
| 461 |
+
return x
|
| 462 |
+
if info > 0:
|
| 463 |
+
raise LinAlgError("singular matrix")
|
| 464 |
+
raise ValueError('illegal value in %d-th argument of internal '
|
| 465 |
+
'gbsv/gtsv' % -info)
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False,
|
| 469 |
+
check_finite=True):
|
| 470 |
+
"""
|
| 471 |
+
Solve equation a x = b. a is Hermitian positive-definite banded matrix.
|
| 472 |
+
|
| 473 |
+
Uses Thomas' Algorithm, which is more efficient than standard LU
|
| 474 |
+
factorization, but should only be used for Hermitian positive-definite
|
| 475 |
+
matrices.
|
| 476 |
+
|
| 477 |
+
The matrix ``a`` is stored in `ab` either in lower diagonal or upper
|
| 478 |
+
diagonal ordered form:
|
| 479 |
+
|
| 480 |
+
ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
|
| 481 |
+
ab[ i - j, j] == a[i,j] (if lower form; i >= j)
|
| 482 |
+
|
| 483 |
+
Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals,
|
| 484 |
+
``u`` =2)::
|
| 485 |
+
|
| 486 |
+
upper form:
|
| 487 |
+
* * a02 a13 a24 a35
|
| 488 |
+
* a01 a12 a23 a34 a45
|
| 489 |
+
a00 a11 a22 a33 a44 a55
|
| 490 |
+
|
| 491 |
+
lower form:
|
| 492 |
+
a00 a11 a22 a33 a44 a55
|
| 493 |
+
a10 a21 a32 a43 a54 *
|
| 494 |
+
a20 a31 a42 a53 * *
|
| 495 |
+
|
| 496 |
+
Cells marked with * are not used.
|
| 497 |
+
|
| 498 |
+
Parameters
|
| 499 |
+
----------
|
| 500 |
+
ab : (``u`` + 1, M) array_like
|
| 501 |
+
Banded matrix
|
| 502 |
+
b : (M,) or (M, K) array_like
|
| 503 |
+
Right-hand side
|
| 504 |
+
overwrite_ab : bool, optional
|
| 505 |
+
Discard data in `ab` (may enhance performance)
|
| 506 |
+
overwrite_b : bool, optional
|
| 507 |
+
Discard data in `b` (may enhance performance)
|
| 508 |
+
lower : bool, optional
|
| 509 |
+
Is the matrix in the lower form. (Default is upper form)
|
| 510 |
+
check_finite : bool, optional
|
| 511 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 512 |
+
Disabling may give a performance gain, but may result in problems
|
| 513 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 514 |
+
|
| 515 |
+
Returns
|
| 516 |
+
-------
|
| 517 |
+
x : (M,) or (M, K) ndarray
|
| 518 |
+
The solution to the system ``a x = b``. Shape of return matches shape
|
| 519 |
+
of `b`.
|
| 520 |
+
|
| 521 |
+
Notes
|
| 522 |
+
-----
|
| 523 |
+
In the case of a non-positive definite matrix ``a``, the solver
|
| 524 |
+
`solve_banded` may be used.
|
| 525 |
+
|
| 526 |
+
Examples
|
| 527 |
+
--------
|
| 528 |
+
Solve the banded system ``A x = b``, where::
|
| 529 |
+
|
| 530 |
+
[ 4 2 -1 0 0 0] [1]
|
| 531 |
+
[ 2 5 2 -1 0 0] [2]
|
| 532 |
+
A = [-1 2 6 2 -1 0] b = [2]
|
| 533 |
+
[ 0 -1 2 7 2 -1] [3]
|
| 534 |
+
[ 0 0 -1 2 8 2] [3]
|
| 535 |
+
[ 0 0 0 -1 2 9] [3]
|
| 536 |
+
|
| 537 |
+
>>> import numpy as np
|
| 538 |
+
>>> from scipy.linalg import solveh_banded
|
| 539 |
+
|
| 540 |
+
``ab`` contains the main diagonal and the nonzero diagonals below the
|
| 541 |
+
main diagonal. That is, we use the lower form:
|
| 542 |
+
|
| 543 |
+
>>> ab = np.array([[ 4, 5, 6, 7, 8, 9],
|
| 544 |
+
... [ 2, 2, 2, 2, 2, 0],
|
| 545 |
+
... [-1, -1, -1, -1, 0, 0]])
|
| 546 |
+
>>> b = np.array([1, 2, 2, 3, 3, 3])
|
| 547 |
+
>>> x = solveh_banded(ab, b, lower=True)
|
| 548 |
+
>>> x
|
| 549 |
+
array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031,
|
| 550 |
+
0.34733894])
|
| 551 |
+
|
| 552 |
+
|
| 553 |
+
Solve the Hermitian banded system ``H x = b``, where::
|
| 554 |
+
|
| 555 |
+
[ 8 2-1j 0 0 ] [ 1 ]
|
| 556 |
+
H = [2+1j 5 1j 0 ] b = [1+1j]
|
| 557 |
+
[ 0 -1j 9 -2-1j] [1-2j]
|
| 558 |
+
[ 0 0 -2+1j 6 ] [ 0 ]
|
| 559 |
+
|
| 560 |
+
In this example, we put the upper diagonals in the array ``hb``:
|
| 561 |
+
|
| 562 |
+
>>> hb = np.array([[0, 2-1j, 1j, -2-1j],
|
| 563 |
+
... [8, 5, 9, 6 ]])
|
| 564 |
+
>>> b = np.array([1, 1+1j, 1-2j, 0])
|
| 565 |
+
>>> x = solveh_banded(hb, b)
|
| 566 |
+
>>> x
|
| 567 |
+
array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j,
|
| 568 |
+
0.10077984-0.23035393j, -0.00479904-0.09358128j])
|
| 569 |
+
|
| 570 |
+
"""
|
| 571 |
+
a1 = _asarray_validated(ab, check_finite=check_finite)
|
| 572 |
+
b1 = _asarray_validated(b, check_finite=check_finite)
|
| 573 |
+
# Validate shapes.
|
| 574 |
+
if a1.shape[-1] != b1.shape[0]:
|
| 575 |
+
raise ValueError("shapes of ab and b are not compatible.")
|
| 576 |
+
|
| 577 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 578 |
+
overwrite_ab = overwrite_ab or _datacopied(a1, ab)
|
| 579 |
+
|
| 580 |
+
if a1.shape[0] == 2:
|
| 581 |
+
ptsv, = get_lapack_funcs(('ptsv',), (a1, b1))
|
| 582 |
+
if lower:
|
| 583 |
+
d = a1[0, :].real
|
| 584 |
+
e = a1[1, :-1]
|
| 585 |
+
else:
|
| 586 |
+
d = a1[1, :].real
|
| 587 |
+
e = a1[0, 1:].conj()
|
| 588 |
+
d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab,
|
| 589 |
+
overwrite_b)
|
| 590 |
+
else:
|
| 591 |
+
pbsv, = get_lapack_funcs(('pbsv',), (a1, b1))
|
| 592 |
+
c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab,
|
| 593 |
+
overwrite_b=overwrite_b)
|
| 594 |
+
if info > 0:
|
| 595 |
+
raise LinAlgError("%dth leading minor not positive definite" % info)
|
| 596 |
+
if info < 0:
|
| 597 |
+
raise ValueError('illegal value in %dth argument of internal '
|
| 598 |
+
'pbsv' % -info)
|
| 599 |
+
return x
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
def solve_toeplitz(c_or_cr, b, check_finite=True):
|
| 603 |
+
"""Solve a Toeplitz system using Levinson Recursion
|
| 604 |
+
|
| 605 |
+
The Toeplitz matrix has constant diagonals, with c as its first column
|
| 606 |
+
and r as its first row. If r is not given, ``r == conjugate(c)`` is
|
| 607 |
+
assumed.
|
| 608 |
+
|
| 609 |
+
Parameters
|
| 610 |
+
----------
|
| 611 |
+
c_or_cr : array_like or tuple of (array_like, array_like)
|
| 612 |
+
The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
|
| 613 |
+
actual shape of ``c``, it will be converted to a 1-D array. If not
|
| 614 |
+
supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
|
| 615 |
+
real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
|
| 616 |
+
of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
|
| 617 |
+
of ``r``, it will be converted to a 1-D array.
|
| 618 |
+
b : (M,) or (M, K) array_like
|
| 619 |
+
Right-hand side in ``T x = b``.
|
| 620 |
+
check_finite : bool, optional
|
| 621 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 622 |
+
Disabling may give a performance gain, but may result in problems
|
| 623 |
+
(result entirely NaNs) if the inputs do contain infinities or NaNs.
|
| 624 |
+
|
| 625 |
+
Returns
|
| 626 |
+
-------
|
| 627 |
+
x : (M,) or (M, K) ndarray
|
| 628 |
+
The solution to the system ``T x = b``. Shape of return matches shape
|
| 629 |
+
of `b`.
|
| 630 |
+
|
| 631 |
+
See Also
|
| 632 |
+
--------
|
| 633 |
+
toeplitz : Toeplitz matrix
|
| 634 |
+
|
| 635 |
+
Notes
|
| 636 |
+
-----
|
| 637 |
+
The solution is computed using Levinson-Durbin recursion, which is faster
|
| 638 |
+
than generic least-squares methods, but can be less numerically stable.
|
| 639 |
+
|
| 640 |
+
Examples
|
| 641 |
+
--------
|
| 642 |
+
Solve the Toeplitz system T x = b, where::
|
| 643 |
+
|
| 644 |
+
[ 1 -1 -2 -3] [1]
|
| 645 |
+
T = [ 3 1 -1 -2] b = [2]
|
| 646 |
+
[ 6 3 1 -1] [2]
|
| 647 |
+
[10 6 3 1] [5]
|
| 648 |
+
|
| 649 |
+
To specify the Toeplitz matrix, only the first column and the first
|
| 650 |
+
row are needed.
|
| 651 |
+
|
| 652 |
+
>>> import numpy as np
|
| 653 |
+
>>> c = np.array([1, 3, 6, 10]) # First column of T
|
| 654 |
+
>>> r = np.array([1, -1, -2, -3]) # First row of T
|
| 655 |
+
>>> b = np.array([1, 2, 2, 5])
|
| 656 |
+
|
| 657 |
+
>>> from scipy.linalg import solve_toeplitz, toeplitz
|
| 658 |
+
>>> x = solve_toeplitz((c, r), b)
|
| 659 |
+
>>> x
|
| 660 |
+
array([ 1.66666667, -1. , -2.66666667, 2.33333333])
|
| 661 |
+
|
| 662 |
+
Check the result by creating the full Toeplitz matrix and
|
| 663 |
+
multiplying it by `x`. We should get `b`.
|
| 664 |
+
|
| 665 |
+
>>> T = toeplitz(c, r)
|
| 666 |
+
>>> T.dot(x)
|
| 667 |
+
array([ 1., 2., 2., 5.])
|
| 668 |
+
|
| 669 |
+
"""
|
| 670 |
+
# If numerical stability of this algorithm is a problem, a future
|
| 671 |
+
# developer might consider implementing other O(N^2) Toeplitz solvers,
|
| 672 |
+
# such as GKO (https://www.jstor.org/stable/2153371) or Bareiss.
|
| 673 |
+
|
| 674 |
+
r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops(
|
| 675 |
+
c_or_cr, b, check_finite, keep_b_shape=True)
|
| 676 |
+
|
| 677 |
+
# Form a 1-D array of values to be used in the matrix, containing a
|
| 678 |
+
# reversed copy of r[1:], followed by c.
|
| 679 |
+
vals = np.concatenate((r[-1:0:-1], c))
|
| 680 |
+
if b is None:
|
| 681 |
+
raise ValueError('illegal value, `b` is a required argument')
|
| 682 |
+
|
| 683 |
+
if b.ndim == 1:
|
| 684 |
+
x, _ = levinson(vals, np.ascontiguousarray(b))
|
| 685 |
+
else:
|
| 686 |
+
x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0]
|
| 687 |
+
for i in range(b.shape[1])])
|
| 688 |
+
x = x.reshape(*b_shape)
|
| 689 |
+
|
| 690 |
+
return x
|
| 691 |
+
|
| 692 |
+
|
| 693 |
+
def _get_axis_len(aname, a, axis):
|
| 694 |
+
ax = axis
|
| 695 |
+
if ax < 0:
|
| 696 |
+
ax += a.ndim
|
| 697 |
+
if 0 <= ax < a.ndim:
|
| 698 |
+
return a.shape[ax]
|
| 699 |
+
raise ValueError(f"'{aname}axis' entry is out of bounds")
|
| 700 |
+
|
| 701 |
+
|
| 702 |
+
def solve_circulant(c, b, singular='raise', tol=None,
|
| 703 |
+
caxis=-1, baxis=0, outaxis=0):
|
| 704 |
+
"""Solve C x = b for x, where C is a circulant matrix.
|
| 705 |
+
|
| 706 |
+
`C` is the circulant matrix associated with the vector `c`.
|
| 707 |
+
|
| 708 |
+
The system is solved by doing division in Fourier space. The
|
| 709 |
+
calculation is::
|
| 710 |
+
|
| 711 |
+
x = ifft(fft(b) / fft(c))
|
| 712 |
+
|
| 713 |
+
where `fft` and `ifft` are the fast Fourier transform and its inverse,
|
| 714 |
+
respectively. For a large vector `c`, this is *much* faster than
|
| 715 |
+
solving the system with the full circulant matrix.
|
| 716 |
+
|
| 717 |
+
Parameters
|
| 718 |
+
----------
|
| 719 |
+
c : array_like
|
| 720 |
+
The coefficients of the circulant matrix.
|
| 721 |
+
b : array_like
|
| 722 |
+
Right-hand side matrix in ``a x = b``.
|
| 723 |
+
singular : str, optional
|
| 724 |
+
This argument controls how a near singular circulant matrix is
|
| 725 |
+
handled. If `singular` is "raise" and the circulant matrix is
|
| 726 |
+
near singular, a `LinAlgError` is raised. If `singular` is
|
| 727 |
+
"lstsq", the least squares solution is returned. Default is "raise".
|
| 728 |
+
tol : float, optional
|
| 729 |
+
If any eigenvalue of the circulant matrix has an absolute value
|
| 730 |
+
that is less than or equal to `tol`, the matrix is considered to be
|
| 731 |
+
near singular. If not given, `tol` is set to::
|
| 732 |
+
|
| 733 |
+
tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps
|
| 734 |
+
|
| 735 |
+
where `abs_eigs` is the array of absolute values of the eigenvalues
|
| 736 |
+
of the circulant matrix.
|
| 737 |
+
caxis : int
|
| 738 |
+
When `c` has dimension greater than 1, it is viewed as a collection
|
| 739 |
+
of circulant vectors. In this case, `caxis` is the axis of `c` that
|
| 740 |
+
holds the vectors of circulant coefficients.
|
| 741 |
+
baxis : int
|
| 742 |
+
When `b` has dimension greater than 1, it is viewed as a collection
|
| 743 |
+
of vectors. In this case, `baxis` is the axis of `b` that holds the
|
| 744 |
+
right-hand side vectors.
|
| 745 |
+
outaxis : int
|
| 746 |
+
When `c` or `b` are multidimensional, the value returned by
|
| 747 |
+
`solve_circulant` is multidimensional. In this case, `outaxis` is
|
| 748 |
+
the axis of the result that holds the solution vectors.
|
| 749 |
+
|
| 750 |
+
Returns
|
| 751 |
+
-------
|
| 752 |
+
x : ndarray
|
| 753 |
+
Solution to the system ``C x = b``.
|
| 754 |
+
|
| 755 |
+
Raises
|
| 756 |
+
------
|
| 757 |
+
LinAlgError
|
| 758 |
+
If the circulant matrix associated with `c` is near singular.
|
| 759 |
+
|
| 760 |
+
See Also
|
| 761 |
+
--------
|
| 762 |
+
circulant : circulant matrix
|
| 763 |
+
|
| 764 |
+
Notes
|
| 765 |
+
-----
|
| 766 |
+
For a 1-D vector `c` with length `m`, and an array `b`
|
| 767 |
+
with shape ``(m, ...)``,
|
| 768 |
+
|
| 769 |
+
solve_circulant(c, b)
|
| 770 |
+
|
| 771 |
+
returns the same result as
|
| 772 |
+
|
| 773 |
+
solve(circulant(c), b)
|
| 774 |
+
|
| 775 |
+
where `solve` and `circulant` are from `scipy.linalg`.
|
| 776 |
+
|
| 777 |
+
.. versionadded:: 0.16.0
|
| 778 |
+
|
| 779 |
+
Examples
|
| 780 |
+
--------
|
| 781 |
+
>>> import numpy as np
|
| 782 |
+
>>> from scipy.linalg import solve_circulant, solve, circulant, lstsq
|
| 783 |
+
|
| 784 |
+
>>> c = np.array([2, 2, 4])
|
| 785 |
+
>>> b = np.array([1, 2, 3])
|
| 786 |
+
>>> solve_circulant(c, b)
|
| 787 |
+
array([ 0.75, -0.25, 0.25])
|
| 788 |
+
|
| 789 |
+
Compare that result to solving the system with `scipy.linalg.solve`:
|
| 790 |
+
|
| 791 |
+
>>> solve(circulant(c), b)
|
| 792 |
+
array([ 0.75, -0.25, 0.25])
|
| 793 |
+
|
| 794 |
+
A singular example:
|
| 795 |
+
|
| 796 |
+
>>> c = np.array([1, 1, 0, 0])
|
| 797 |
+
>>> b = np.array([1, 2, 3, 4])
|
| 798 |
+
|
| 799 |
+
Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the
|
| 800 |
+
least square solution, use the option ``singular='lstsq'``:
|
| 801 |
+
|
| 802 |
+
>>> solve_circulant(c, b, singular='lstsq')
|
| 803 |
+
array([ 0.25, 1.25, 2.25, 1.25])
|
| 804 |
+
|
| 805 |
+
Compare to `scipy.linalg.lstsq`:
|
| 806 |
+
|
| 807 |
+
>>> x, resid, rnk, s = lstsq(circulant(c), b)
|
| 808 |
+
>>> x
|
| 809 |
+
array([ 0.25, 1.25, 2.25, 1.25])
|
| 810 |
+
|
| 811 |
+
A broadcasting example:
|
| 812 |
+
|
| 813 |
+
Suppose we have the vectors of two circulant matrices stored in an array
|
| 814 |
+
with shape (2, 5), and three `b` vectors stored in an array with shape
|
| 815 |
+
(3, 5). For example,
|
| 816 |
+
|
| 817 |
+
>>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]])
|
| 818 |
+
>>> b = np.arange(15).reshape(-1, 5)
|
| 819 |
+
|
| 820 |
+
We want to solve all combinations of circulant matrices and `b` vectors,
|
| 821 |
+
with the result stored in an array with shape (2, 3, 5). When we
|
| 822 |
+
disregard the axes of `c` and `b` that hold the vectors of coefficients,
|
| 823 |
+
the shapes of the collections are (2,) and (3,), respectively, which are
|
| 824 |
+
not compatible for broadcasting. To have a broadcast result with shape
|
| 825 |
+
(2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has
|
| 826 |
+
shape (2, 1, 5). The last dimension holds the coefficients of the
|
| 827 |
+
circulant matrices, so when we call `solve_circulant`, we can use the
|
| 828 |
+
default ``caxis=-1``. The coefficients of the `b` vectors are in the last
|
| 829 |
+
dimension of the array `b`, so we use ``baxis=-1``. If we use the
|
| 830 |
+
default `outaxis`, the result will have shape (5, 2, 3), so we'll use
|
| 831 |
+
``outaxis=-1`` to put the solution vectors in the last dimension.
|
| 832 |
+
|
| 833 |
+
>>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1)
|
| 834 |
+
>>> x.shape
|
| 835 |
+
(2, 3, 5)
|
| 836 |
+
>>> np.set_printoptions(precision=3) # For compact output of numbers.
|
| 837 |
+
>>> x
|
| 838 |
+
array([[[-0.118, 0.22 , 1.277, -0.142, 0.302],
|
| 839 |
+
[ 0.651, 0.989, 2.046, 0.627, 1.072],
|
| 840 |
+
[ 1.42 , 1.758, 2.816, 1.396, 1.841]],
|
| 841 |
+
[[ 0.401, 0.304, 0.694, -0.867, 0.377],
|
| 842 |
+
[ 0.856, 0.758, 1.149, -0.412, 0.831],
|
| 843 |
+
[ 1.31 , 1.213, 1.603, 0.042, 1.286]]])
|
| 844 |
+
|
| 845 |
+
Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``):
|
| 846 |
+
|
| 847 |
+
>>> solve_circulant(c[1], b[1, :])
|
| 848 |
+
array([ 0.856, 0.758, 1.149, -0.412, 0.831])
|
| 849 |
+
|
| 850 |
+
"""
|
| 851 |
+
c = np.atleast_1d(c)
|
| 852 |
+
nc = _get_axis_len("c", c, caxis)
|
| 853 |
+
b = np.atleast_1d(b)
|
| 854 |
+
nb = _get_axis_len("b", b, baxis)
|
| 855 |
+
if nc != nb:
|
| 856 |
+
raise ValueError(f'Shapes of c {c.shape} and b {b.shape} are incompatible')
|
| 857 |
+
|
| 858 |
+
fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1)
|
| 859 |
+
abs_fc = np.abs(fc)
|
| 860 |
+
if tol is None:
|
| 861 |
+
# This is the same tolerance as used in np.linalg.matrix_rank.
|
| 862 |
+
tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps
|
| 863 |
+
if tol.shape != ():
|
| 864 |
+
tol.shape = tol.shape + (1,)
|
| 865 |
+
else:
|
| 866 |
+
tol = np.atleast_1d(tol)
|
| 867 |
+
|
| 868 |
+
near_zeros = abs_fc <= tol
|
| 869 |
+
is_near_singular = np.any(near_zeros)
|
| 870 |
+
if is_near_singular:
|
| 871 |
+
if singular == 'raise':
|
| 872 |
+
raise LinAlgError("near singular circulant matrix.")
|
| 873 |
+
else:
|
| 874 |
+
# Replace the small values with 1 to avoid errors in the
|
| 875 |
+
# division fb/fc below.
|
| 876 |
+
fc[near_zeros] = 1
|
| 877 |
+
|
| 878 |
+
fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1)
|
| 879 |
+
|
| 880 |
+
q = fb / fc
|
| 881 |
+
|
| 882 |
+
if is_near_singular:
|
| 883 |
+
# `near_zeros` is a boolean array, same shape as `c`, that is
|
| 884 |
+
# True where `fc` is (near) zero. `q` is the broadcasted result
|
| 885 |
+
# of fb / fc, so to set the values of `q` to 0 where `fc` is near
|
| 886 |
+
# zero, we use a mask that is the broadcast result of an array
|
| 887 |
+
# of True values shaped like `b` with `near_zeros`.
|
| 888 |
+
mask = np.ones_like(b, dtype=bool) & near_zeros
|
| 889 |
+
q[mask] = 0
|
| 890 |
+
|
| 891 |
+
x = np.fft.ifft(q, axis=-1)
|
| 892 |
+
if not (np.iscomplexobj(c) or np.iscomplexobj(b)):
|
| 893 |
+
x = x.real
|
| 894 |
+
if outaxis != -1:
|
| 895 |
+
x = np.moveaxis(x, -1, outaxis)
|
| 896 |
+
return x
|
| 897 |
+
|
| 898 |
+
|
| 899 |
+
# matrix inversion
|
| 900 |
+
def inv(a, overwrite_a=False, check_finite=True):
|
| 901 |
+
"""
|
| 902 |
+
Compute the inverse of a matrix.
|
| 903 |
+
|
| 904 |
+
Parameters
|
| 905 |
+
----------
|
| 906 |
+
a : array_like
|
| 907 |
+
Square matrix to be inverted.
|
| 908 |
+
overwrite_a : bool, optional
|
| 909 |
+
Discard data in `a` (may improve performance). Default is False.
|
| 910 |
+
check_finite : bool, optional
|
| 911 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 912 |
+
Disabling may give a performance gain, but may result in problems
|
| 913 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 914 |
+
|
| 915 |
+
Returns
|
| 916 |
+
-------
|
| 917 |
+
ainv : ndarray
|
| 918 |
+
Inverse of the matrix `a`.
|
| 919 |
+
|
| 920 |
+
Raises
|
| 921 |
+
------
|
| 922 |
+
LinAlgError
|
| 923 |
+
If `a` is singular.
|
| 924 |
+
ValueError
|
| 925 |
+
If `a` is not square, or not 2D.
|
| 926 |
+
|
| 927 |
+
Examples
|
| 928 |
+
--------
|
| 929 |
+
>>> import numpy as np
|
| 930 |
+
>>> from scipy import linalg
|
| 931 |
+
>>> a = np.array([[1., 2.], [3., 4.]])
|
| 932 |
+
>>> linalg.inv(a)
|
| 933 |
+
array([[-2. , 1. ],
|
| 934 |
+
[ 1.5, -0.5]])
|
| 935 |
+
>>> np.dot(a, linalg.inv(a))
|
| 936 |
+
array([[ 1., 0.],
|
| 937 |
+
[ 0., 1.]])
|
| 938 |
+
|
| 939 |
+
"""
|
| 940 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 941 |
+
if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
|
| 942 |
+
raise ValueError('expected square matrix')
|
| 943 |
+
overwrite_a = overwrite_a or _datacopied(a1, a)
|
| 944 |
+
getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri',
|
| 945 |
+
'getri_lwork'),
|
| 946 |
+
(a1,))
|
| 947 |
+
lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
|
| 948 |
+
if info == 0:
|
| 949 |
+
lwork = _compute_lwork(getri_lwork, a1.shape[0])
|
| 950 |
+
|
| 951 |
+
# XXX: the following line fixes curious SEGFAULT when
|
| 952 |
+
# benchmarking 500x500 matrix inverse. This seems to
|
| 953 |
+
# be a bug in LAPACK ?getri routine because if lwork is
|
| 954 |
+
# minimal (when using lwork[0] instead of lwork[1]) then
|
| 955 |
+
# all tests pass. Further investigation is required if
|
| 956 |
+
# more such SEGFAULTs occur.
|
| 957 |
+
lwork = int(1.01 * lwork)
|
| 958 |
+
inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1)
|
| 959 |
+
if info > 0:
|
| 960 |
+
raise LinAlgError("singular matrix")
|
| 961 |
+
if info < 0:
|
| 962 |
+
raise ValueError('illegal value in %d-th argument of internal '
|
| 963 |
+
'getrf|getri' % -info)
|
| 964 |
+
return inv_a
|
| 965 |
+
|
| 966 |
+
|
| 967 |
+
# Determinant
|
| 968 |
+
|
| 969 |
+
def det(a, overwrite_a=False, check_finite=True):
|
| 970 |
+
"""
|
| 971 |
+
Compute the determinant of a matrix
|
| 972 |
+
|
| 973 |
+
The determinant is a scalar that is a function of the associated square
|
| 974 |
+
matrix coefficients. The determinant value is zero for singular matrices.
|
| 975 |
+
|
| 976 |
+
Parameters
|
| 977 |
+
----------
|
| 978 |
+
a : (..., M, M) array_like
|
| 979 |
+
Input array to compute determinants for.
|
| 980 |
+
overwrite_a : bool, optional
|
| 981 |
+
Allow overwriting data in a (may enhance performance).
|
| 982 |
+
check_finite : bool, optional
|
| 983 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 984 |
+
Disabling may give a performance gain, but may result in problems
|
| 985 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 986 |
+
|
| 987 |
+
Returns
|
| 988 |
+
-------
|
| 989 |
+
det : (...) float or complex
|
| 990 |
+
Determinant of `a`. For stacked arrays, a scalar is returned for each
|
| 991 |
+
(m, m) slice in the last two dimensions of the input. For example, an
|
| 992 |
+
input of shape (p, q, m, m) will produce a result of shape (p, q). If
|
| 993 |
+
all dimensions are 1 a scalar is returned regardless of ndim.
|
| 994 |
+
|
| 995 |
+
Notes
|
| 996 |
+
-----
|
| 997 |
+
The determinant is computed by performing an LU factorization of the
|
| 998 |
+
input with LAPACK routine 'getrf', and then calculating the product of
|
| 999 |
+
diagonal entries of the U factor.
|
| 1000 |
+
|
| 1001 |
+
Even the input array is single precision (float32 or complex64), the result
|
| 1002 |
+
will be returned in double precision (float64 or complex128) to prevent
|
| 1003 |
+
overflows.
|
| 1004 |
+
|
| 1005 |
+
Examples
|
| 1006 |
+
--------
|
| 1007 |
+
>>> import numpy as np
|
| 1008 |
+
>>> from scipy import linalg
|
| 1009 |
+
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) # A singular matrix
|
| 1010 |
+
>>> linalg.det(a)
|
| 1011 |
+
0.0
|
| 1012 |
+
>>> b = np.array([[0,2,3], [4,5,6], [7,8,9]])
|
| 1013 |
+
>>> linalg.det(b)
|
| 1014 |
+
3.0
|
| 1015 |
+
>>> # An array with the shape (3, 2, 2, 2)
|
| 1016 |
+
>>> c = np.array([[[[1., 2.], [3., 4.]],
|
| 1017 |
+
... [[5., 6.], [7., 8.]]],
|
| 1018 |
+
... [[[9., 10.], [11., 12.]],
|
| 1019 |
+
... [[13., 14.], [15., 16.]]],
|
| 1020 |
+
... [[[17., 18.], [19., 20.]],
|
| 1021 |
+
... [[21., 22.], [23., 24.]]]])
|
| 1022 |
+
>>> linalg.det(c) # The resulting shape is (3, 2)
|
| 1023 |
+
array([[-2., -2.],
|
| 1024 |
+
[-2., -2.],
|
| 1025 |
+
[-2., -2.]])
|
| 1026 |
+
>>> linalg.det(c[0, 0]) # Confirm the (0, 0) slice, [[1, 2], [3, 4]]
|
| 1027 |
+
-2.0
|
| 1028 |
+
"""
|
| 1029 |
+
# The goal is to end up with a writable contiguous array to pass to Cython
|
| 1030 |
+
|
| 1031 |
+
# First we check and make arrays.
|
| 1032 |
+
a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
|
| 1033 |
+
if a1.ndim < 2:
|
| 1034 |
+
raise ValueError('The input array must be at least two-dimensional.')
|
| 1035 |
+
if a1.shape[-1] != a1.shape[-2]:
|
| 1036 |
+
raise ValueError('Last 2 dimensions of the array must be square'
|
| 1037 |
+
f' but received shape {a1.shape}.')
|
| 1038 |
+
|
| 1039 |
+
# Also check if dtype is LAPACK compatible
|
| 1040 |
+
if a1.dtype.char not in 'fdFD':
|
| 1041 |
+
dtype_char = lapack_cast_dict[a1.dtype.char]
|
| 1042 |
+
if not dtype_char: # No casting possible
|
| 1043 |
+
raise TypeError(f'The dtype "{a1.dtype.name}" cannot be cast '
|
| 1044 |
+
'to float(32, 64) or complex(64, 128).')
|
| 1045 |
+
|
| 1046 |
+
a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
|
| 1047 |
+
overwrite_a = True
|
| 1048 |
+
|
| 1049 |
+
# Empty array has determinant 1 because math.
|
| 1050 |
+
if min(*a1.shape) == 0:
|
| 1051 |
+
if a1.ndim == 2:
|
| 1052 |
+
return np.float64(1.)
|
| 1053 |
+
else:
|
| 1054 |
+
return np.ones(shape=a1.shape[:-2], dtype=np.float64)
|
| 1055 |
+
|
| 1056 |
+
# Scalar case
|
| 1057 |
+
if a1.shape[-2:] == (1, 1):
|
| 1058 |
+
# Either ndarray with spurious singletons or a single element
|
| 1059 |
+
if max(*a1.shape) > 1:
|
| 1060 |
+
temp = np.squeeze(a1)
|
| 1061 |
+
if a1.dtype.char in 'dD':
|
| 1062 |
+
return temp
|
| 1063 |
+
else:
|
| 1064 |
+
return (temp.astype('d') if a1.dtype.char == 'f' else
|
| 1065 |
+
temp.astype('D'))
|
| 1066 |
+
else:
|
| 1067 |
+
return (np.float64(a1.item()) if a1.dtype.char in 'fd' else
|
| 1068 |
+
np.complex128(a1.item()))
|
| 1069 |
+
|
| 1070 |
+
# Then check overwrite permission
|
| 1071 |
+
if not _datacopied(a1, a): # "a" still alive through "a1"
|
| 1072 |
+
if not overwrite_a:
|
| 1073 |
+
# Data belongs to "a" so make a copy
|
| 1074 |
+
a1 = a1.copy(order='C')
|
| 1075 |
+
# else: Do nothing we'll use "a" if possible
|
| 1076 |
+
# else: a1 has its own data thus free to scratch
|
| 1077 |
+
|
| 1078 |
+
# Then layout checks, might happen that overwrite is allowed but original
|
| 1079 |
+
# array was read-only or non-C-contiguous.
|
| 1080 |
+
if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
|
| 1081 |
+
a1 = a1.copy(order='C')
|
| 1082 |
+
|
| 1083 |
+
if a1.ndim == 2:
|
| 1084 |
+
det = find_det_from_lu(a1)
|
| 1085 |
+
# Convert float, complex to to NumPy scalars
|
| 1086 |
+
return (np.float64(det) if np.isrealobj(det) else np.complex128(det))
|
| 1087 |
+
|
| 1088 |
+
# loop over the stacked array, and avoid overflows for single precision
|
| 1089 |
+
# Cf. np.linalg.det(np.diag([1e+38, 1e+38]).astype(np.float32))
|
| 1090 |
+
dtype_char = a1.dtype.char
|
| 1091 |
+
if dtype_char in 'fF':
|
| 1092 |
+
dtype_char = 'd' if dtype_char.islower() else 'D'
|
| 1093 |
+
|
| 1094 |
+
det = np.empty(a1.shape[:-2], dtype=dtype_char)
|
| 1095 |
+
for ind in product(*[range(x) for x in a1.shape[:-2]]):
|
| 1096 |
+
det[ind] = find_det_from_lu(a1[ind])
|
| 1097 |
+
return det
|
| 1098 |
+
|
| 1099 |
+
|
| 1100 |
+
# Linear Least Squares
|
| 1101 |
+
def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False,
|
| 1102 |
+
check_finite=True, lapack_driver=None):
|
| 1103 |
+
"""
|
| 1104 |
+
Compute least-squares solution to equation Ax = b.
|
| 1105 |
+
|
| 1106 |
+
Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
|
| 1107 |
+
|
| 1108 |
+
Parameters
|
| 1109 |
+
----------
|
| 1110 |
+
a : (M, N) array_like
|
| 1111 |
+
Left-hand side array
|
| 1112 |
+
b : (M,) or (M, K) array_like
|
| 1113 |
+
Right hand side array
|
| 1114 |
+
cond : float, optional
|
| 1115 |
+
Cutoff for 'small' singular values; used to determine effective
|
| 1116 |
+
rank of a. Singular values smaller than
|
| 1117 |
+
``cond * largest_singular_value`` are considered zero.
|
| 1118 |
+
overwrite_a : bool, optional
|
| 1119 |
+
Discard data in `a` (may enhance performance). Default is False.
|
| 1120 |
+
overwrite_b : bool, optional
|
| 1121 |
+
Discard data in `b` (may enhance performance). Default is False.
|
| 1122 |
+
check_finite : bool, optional
|
| 1123 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 1124 |
+
Disabling may give a performance gain, but may result in problems
|
| 1125 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1126 |
+
lapack_driver : str, optional
|
| 1127 |
+
Which LAPACK driver is used to solve the least-squares problem.
|
| 1128 |
+
Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
|
| 1129 |
+
(``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly
|
| 1130 |
+
faster on many problems. ``'gelss'`` was used historically. It is
|
| 1131 |
+
generally slow but uses less memory.
|
| 1132 |
+
|
| 1133 |
+
.. versionadded:: 0.17.0
|
| 1134 |
+
|
| 1135 |
+
Returns
|
| 1136 |
+
-------
|
| 1137 |
+
x : (N,) or (N, K) ndarray
|
| 1138 |
+
Least-squares solution.
|
| 1139 |
+
residues : (K,) ndarray or float
|
| 1140 |
+
Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and
|
| 1141 |
+
``rank(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a
|
| 1142 |
+
(0,)-shaped array is returned.
|
| 1143 |
+
rank : int
|
| 1144 |
+
Effective rank of `a`.
|
| 1145 |
+
s : (min(M, N),) ndarray or None
|
| 1146 |
+
Singular values of `a`. The condition number of ``a`` is
|
| 1147 |
+
``s[0] / s[-1]``.
|
| 1148 |
+
|
| 1149 |
+
Raises
|
| 1150 |
+
------
|
| 1151 |
+
LinAlgError
|
| 1152 |
+
If computation does not converge.
|
| 1153 |
+
|
| 1154 |
+
ValueError
|
| 1155 |
+
When parameters are not compatible.
|
| 1156 |
+
|
| 1157 |
+
See Also
|
| 1158 |
+
--------
|
| 1159 |
+
scipy.optimize.nnls : linear least squares with non-negativity constraint
|
| 1160 |
+
|
| 1161 |
+
Notes
|
| 1162 |
+
-----
|
| 1163 |
+
When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped
|
| 1164 |
+
array and `s` is always ``None``.
|
| 1165 |
+
|
| 1166 |
+
Examples
|
| 1167 |
+
--------
|
| 1168 |
+
>>> import numpy as np
|
| 1169 |
+
>>> from scipy.linalg import lstsq
|
| 1170 |
+
>>> import matplotlib.pyplot as plt
|
| 1171 |
+
|
| 1172 |
+
Suppose we have the following data:
|
| 1173 |
+
|
| 1174 |
+
>>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
|
| 1175 |
+
>>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
|
| 1176 |
+
|
| 1177 |
+
We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
|
| 1178 |
+
to this data. We first form the "design matrix" M, with a constant
|
| 1179 |
+
column of 1s and a column containing ``x**2``:
|
| 1180 |
+
|
| 1181 |
+
>>> M = x[:, np.newaxis]**[0, 2]
|
| 1182 |
+
>>> M
|
| 1183 |
+
array([[ 1. , 1. ],
|
| 1184 |
+
[ 1. , 6.25],
|
| 1185 |
+
[ 1. , 12.25],
|
| 1186 |
+
[ 1. , 16. ],
|
| 1187 |
+
[ 1. , 25. ],
|
| 1188 |
+
[ 1. , 49. ],
|
| 1189 |
+
[ 1. , 72.25]])
|
| 1190 |
+
|
| 1191 |
+
We want to find the least-squares solution to ``M.dot(p) = y``,
|
| 1192 |
+
where ``p`` is a vector with length 2 that holds the parameters
|
| 1193 |
+
``a`` and ``b``.
|
| 1194 |
+
|
| 1195 |
+
>>> p, res, rnk, s = lstsq(M, y)
|
| 1196 |
+
>>> p
|
| 1197 |
+
array([ 0.20925829, 0.12013861])
|
| 1198 |
+
|
| 1199 |
+
Plot the data and the fitted curve.
|
| 1200 |
+
|
| 1201 |
+
>>> plt.plot(x, y, 'o', label='data')
|
| 1202 |
+
>>> xx = np.linspace(0, 9, 101)
|
| 1203 |
+
>>> yy = p[0] + p[1]*xx**2
|
| 1204 |
+
>>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
|
| 1205 |
+
>>> plt.xlabel('x')
|
| 1206 |
+
>>> plt.ylabel('y')
|
| 1207 |
+
>>> plt.legend(framealpha=1, shadow=True)
|
| 1208 |
+
>>> plt.grid(alpha=0.25)
|
| 1209 |
+
>>> plt.show()
|
| 1210 |
+
|
| 1211 |
+
"""
|
| 1212 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 1213 |
+
b1 = _asarray_validated(b, check_finite=check_finite)
|
| 1214 |
+
if len(a1.shape) != 2:
|
| 1215 |
+
raise ValueError('Input array a should be 2D')
|
| 1216 |
+
m, n = a1.shape
|
| 1217 |
+
if len(b1.shape) == 2:
|
| 1218 |
+
nrhs = b1.shape[1]
|
| 1219 |
+
else:
|
| 1220 |
+
nrhs = 1
|
| 1221 |
+
if m != b1.shape[0]:
|
| 1222 |
+
raise ValueError('Shape mismatch: a and b should have the same number'
|
| 1223 |
+
f' of rows ({m} != {b1.shape[0]}).')
|
| 1224 |
+
if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK
|
| 1225 |
+
x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1))
|
| 1226 |
+
if n == 0:
|
| 1227 |
+
residues = np.linalg.norm(b1, axis=0)**2
|
| 1228 |
+
else:
|
| 1229 |
+
residues = np.empty((0,))
|
| 1230 |
+
return x, residues, 0, np.empty((0,))
|
| 1231 |
+
|
| 1232 |
+
driver = lapack_driver
|
| 1233 |
+
if driver is None:
|
| 1234 |
+
driver = lstsq.default_lapack_driver
|
| 1235 |
+
if driver not in ('gelsd', 'gelsy', 'gelss'):
|
| 1236 |
+
raise ValueError('LAPACK driver "%s" is not found' % driver)
|
| 1237 |
+
|
| 1238 |
+
lapack_func, lapack_lwork = get_lapack_funcs((driver,
|
| 1239 |
+
'%s_lwork' % driver),
|
| 1240 |
+
(a1, b1))
|
| 1241 |
+
real_data = True if (lapack_func.dtype.kind == 'f') else False
|
| 1242 |
+
|
| 1243 |
+
if m < n:
|
| 1244 |
+
# need to extend b matrix as it will be filled with
|
| 1245 |
+
# a larger solution matrix
|
| 1246 |
+
if len(b1.shape) == 2:
|
| 1247 |
+
b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
|
| 1248 |
+
b2[:m, :] = b1
|
| 1249 |
+
else:
|
| 1250 |
+
b2 = np.zeros(n, dtype=lapack_func.dtype)
|
| 1251 |
+
b2[:m] = b1
|
| 1252 |
+
b1 = b2
|
| 1253 |
+
|
| 1254 |
+
overwrite_a = overwrite_a or _datacopied(a1, a)
|
| 1255 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 1256 |
+
|
| 1257 |
+
if cond is None:
|
| 1258 |
+
cond = np.finfo(lapack_func.dtype).eps
|
| 1259 |
+
|
| 1260 |
+
if driver in ('gelss', 'gelsd'):
|
| 1261 |
+
if driver == 'gelss':
|
| 1262 |
+
lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
|
| 1263 |
+
v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork,
|
| 1264 |
+
overwrite_a=overwrite_a,
|
| 1265 |
+
overwrite_b=overwrite_b)
|
| 1266 |
+
|
| 1267 |
+
elif driver == 'gelsd':
|
| 1268 |
+
if real_data:
|
| 1269 |
+
lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
|
| 1270 |
+
x, s, rank, info = lapack_func(a1, b1, lwork,
|
| 1271 |
+
iwork, cond, False, False)
|
| 1272 |
+
else: # complex data
|
| 1273 |
+
lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n,
|
| 1274 |
+
nrhs, cond)
|
| 1275 |
+
x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork,
|
| 1276 |
+
cond, False, False)
|
| 1277 |
+
if info > 0:
|
| 1278 |
+
raise LinAlgError("SVD did not converge in Linear Least Squares")
|
| 1279 |
+
if info < 0:
|
| 1280 |
+
raise ValueError('illegal value in %d-th argument of internal %s'
|
| 1281 |
+
% (-info, lapack_driver))
|
| 1282 |
+
resids = np.asarray([], dtype=x.dtype)
|
| 1283 |
+
if m > n:
|
| 1284 |
+
x1 = x[:n]
|
| 1285 |
+
if rank == n:
|
| 1286 |
+
resids = np.sum(np.abs(x[n:])**2, axis=0)
|
| 1287 |
+
x = x1
|
| 1288 |
+
return x, resids, rank, s
|
| 1289 |
+
|
| 1290 |
+
elif driver == 'gelsy':
|
| 1291 |
+
lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
|
| 1292 |
+
jptv = np.zeros((a1.shape[1], 1), dtype=np.int32)
|
| 1293 |
+
v, x, j, rank, info = lapack_func(a1, b1, jptv, cond,
|
| 1294 |
+
lwork, False, False)
|
| 1295 |
+
if info < 0:
|
| 1296 |
+
raise ValueError("illegal value in %d-th argument of internal "
|
| 1297 |
+
"gelsy" % -info)
|
| 1298 |
+
if m > n:
|
| 1299 |
+
x1 = x[:n]
|
| 1300 |
+
x = x1
|
| 1301 |
+
return x, np.array([], x.dtype), rank, None
|
| 1302 |
+
|
| 1303 |
+
|
| 1304 |
+
lstsq.default_lapack_driver = 'gelsd'
|
| 1305 |
+
|
| 1306 |
+
|
| 1307 |
+
@_deprecate_positional_args(version="1.14")
|
| 1308 |
+
def pinv(a, *, atol=None, rtol=None, return_rank=False, check_finite=True,
|
| 1309 |
+
cond=_NoValue, rcond=_NoValue):
|
| 1310 |
+
"""
|
| 1311 |
+
Compute the (Moore-Penrose) pseudo-inverse of a matrix.
|
| 1312 |
+
|
| 1313 |
+
Calculate a generalized inverse of a matrix using its
|
| 1314 |
+
singular-value decomposition ``U @ S @ V`` in the economy mode and picking
|
| 1315 |
+
up only the columns/rows that are associated with significant singular
|
| 1316 |
+
values.
|
| 1317 |
+
|
| 1318 |
+
If ``s`` is the maximum singular value of ``a``, then the
|
| 1319 |
+
significance cut-off value is determined by ``atol + rtol * s``. Any
|
| 1320 |
+
singular value below this value is assumed insignificant.
|
| 1321 |
+
|
| 1322 |
+
Parameters
|
| 1323 |
+
----------
|
| 1324 |
+
a : (M, N) array_like
|
| 1325 |
+
Matrix to be pseudo-inverted.
|
| 1326 |
+
atol : float, optional
|
| 1327 |
+
Absolute threshold term, default value is 0.
|
| 1328 |
+
|
| 1329 |
+
.. versionadded:: 1.7.0
|
| 1330 |
+
|
| 1331 |
+
rtol : float, optional
|
| 1332 |
+
Relative threshold term, default value is ``max(M, N) * eps`` where
|
| 1333 |
+
``eps`` is the machine precision value of the datatype of ``a``.
|
| 1334 |
+
|
| 1335 |
+
.. versionadded:: 1.7.0
|
| 1336 |
+
|
| 1337 |
+
return_rank : bool, optional
|
| 1338 |
+
If True, return the effective rank of the matrix.
|
| 1339 |
+
check_finite : bool, optional
|
| 1340 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1341 |
+
Disabling may give a performance gain, but may result in problems
|
| 1342 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1343 |
+
cond, rcond : float, optional
|
| 1344 |
+
In older versions, these values were meant to be used as ``atol`` with
|
| 1345 |
+
``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence
|
| 1346 |
+
the code was not correct. Thus using these are strongly discouraged and
|
| 1347 |
+
the tolerances above are recommended instead. In fact, if provided,
|
| 1348 |
+
atol, rtol takes precedence over these keywords.
|
| 1349 |
+
|
| 1350 |
+
.. deprecated:: 1.7.0
|
| 1351 |
+
Deprecated in favor of ``rtol`` and ``atol`` parameters above and
|
| 1352 |
+
will be removed in SciPy 1.14.0.
|
| 1353 |
+
|
| 1354 |
+
.. versionchanged:: 1.3.0
|
| 1355 |
+
Previously the default cutoff value was just ``eps*f`` where ``f``
|
| 1356 |
+
was ``1e3`` for single precision and ``1e6`` for double precision.
|
| 1357 |
+
|
| 1358 |
+
Returns
|
| 1359 |
+
-------
|
| 1360 |
+
B : (N, M) ndarray
|
| 1361 |
+
The pseudo-inverse of matrix `a`.
|
| 1362 |
+
rank : int
|
| 1363 |
+
The effective rank of the matrix. Returned if `return_rank` is True.
|
| 1364 |
+
|
| 1365 |
+
Raises
|
| 1366 |
+
------
|
| 1367 |
+
LinAlgError
|
| 1368 |
+
If SVD computation does not converge.
|
| 1369 |
+
|
| 1370 |
+
See Also
|
| 1371 |
+
--------
|
| 1372 |
+
pinvh : Moore-Penrose pseudoinverse of a hermitian matrix.
|
| 1373 |
+
|
| 1374 |
+
Notes
|
| 1375 |
+
-----
|
| 1376 |
+
If ``A`` is invertible then the Moore-Penrose pseudoinverse is exactly
|
| 1377 |
+
the inverse of ``A`` [1]_. If ``A`` is not invertible then the
|
| 1378 |
+
Moore-Penrose pseudoinverse computes the ``x`` solution to ``Ax = b`` such
|
| 1379 |
+
that ``||Ax - b||`` is minimized [1]_.
|
| 1380 |
+
|
| 1381 |
+
References
|
| 1382 |
+
----------
|
| 1383 |
+
.. [1] Penrose, R. (1956). On best approximate solutions of linear matrix
|
| 1384 |
+
equations. Mathematical Proceedings of the Cambridge Philosophical
|
| 1385 |
+
Society, 52(1), 17-19. doi:10.1017/S0305004100030929
|
| 1386 |
+
|
| 1387 |
+
Examples
|
| 1388 |
+
--------
|
| 1389 |
+
|
| 1390 |
+
Given an ``m x n`` matrix ``A`` and an ``n x m`` matrix ``B`` the four
|
| 1391 |
+
Moore-Penrose conditions are:
|
| 1392 |
+
|
| 1393 |
+
1. ``ABA = A`` (``B`` is a generalized inverse of ``A``),
|
| 1394 |
+
2. ``BAB = B`` (``A`` is a generalized inverse of ``B``),
|
| 1395 |
+
3. ``(AB)* = AB`` (``AB`` is hermitian),
|
| 1396 |
+
4. ``(BA)* = BA`` (``BA`` is hermitian) [1]_.
|
| 1397 |
+
|
| 1398 |
+
Here, ``A*`` denotes the conjugate transpose. The Moore-Penrose
|
| 1399 |
+
pseudoinverse is a unique ``B`` that satisfies all four of these
|
| 1400 |
+
conditions and exists for any ``A``. Note that, unlike the standard
|
| 1401 |
+
matrix inverse, ``A`` does not have to be a square matrix or have
|
| 1402 |
+
linearly independent columns/rows.
|
| 1403 |
+
|
| 1404 |
+
As an example, we can calculate the Moore-Penrose pseudoinverse of a
|
| 1405 |
+
random non-square matrix and verify it satisfies the four conditions.
|
| 1406 |
+
|
| 1407 |
+
>>> import numpy as np
|
| 1408 |
+
>>> from scipy import linalg
|
| 1409 |
+
>>> rng = np.random.default_rng()
|
| 1410 |
+
>>> A = rng.standard_normal((9, 6))
|
| 1411 |
+
>>> B = linalg.pinv(A)
|
| 1412 |
+
>>> np.allclose(A @ B @ A, A) # Condition 1
|
| 1413 |
+
True
|
| 1414 |
+
>>> np.allclose(B @ A @ B, B) # Condition 2
|
| 1415 |
+
True
|
| 1416 |
+
>>> np.allclose((A @ B).conj().T, A @ B) # Condition 3
|
| 1417 |
+
True
|
| 1418 |
+
>>> np.allclose((B @ A).conj().T, B @ A) # Condition 4
|
| 1419 |
+
True
|
| 1420 |
+
|
| 1421 |
+
"""
|
| 1422 |
+
a = _asarray_validated(a, check_finite=check_finite)
|
| 1423 |
+
u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False)
|
| 1424 |
+
t = u.dtype.char.lower()
|
| 1425 |
+
maxS = np.max(s)
|
| 1426 |
+
|
| 1427 |
+
if rcond is not _NoValue or cond is not _NoValue:
|
| 1428 |
+
warn('Use of the "cond" and "rcond" keywords are deprecated and '
|
| 1429 |
+
'will be removed in SciPy 1.14.0. Use "atol" and '
|
| 1430 |
+
'"rtol" keywords instead', DeprecationWarning, stacklevel=2)
|
| 1431 |
+
|
| 1432 |
+
# backwards compatible only atol and rtol are both missing
|
| 1433 |
+
if ((rcond not in (_NoValue, None) or cond not in (_NoValue, None))
|
| 1434 |
+
and (atol is None) and (rtol is None)):
|
| 1435 |
+
atol = rcond if rcond not in (_NoValue, None) else cond
|
| 1436 |
+
rtol = 0.
|
| 1437 |
+
|
| 1438 |
+
atol = 0. if atol is None else atol
|
| 1439 |
+
rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
|
| 1440 |
+
|
| 1441 |
+
if (atol < 0.) or (rtol < 0.):
|
| 1442 |
+
raise ValueError("atol and rtol values must be positive.")
|
| 1443 |
+
|
| 1444 |
+
val = atol + maxS * rtol
|
| 1445 |
+
rank = np.sum(s > val)
|
| 1446 |
+
|
| 1447 |
+
u = u[:, :rank]
|
| 1448 |
+
u /= s[:rank]
|
| 1449 |
+
B = (u @ vh[:rank]).conj().T
|
| 1450 |
+
|
| 1451 |
+
if return_rank:
|
| 1452 |
+
return B, rank
|
| 1453 |
+
else:
|
| 1454 |
+
return B
|
| 1455 |
+
|
| 1456 |
+
|
| 1457 |
+
def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False,
|
| 1458 |
+
check_finite=True):
|
| 1459 |
+
"""
|
| 1460 |
+
Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix.
|
| 1461 |
+
|
| 1462 |
+
Calculate a generalized inverse of a complex Hermitian/real symmetric
|
| 1463 |
+
matrix using its eigenvalue decomposition and including all eigenvalues
|
| 1464 |
+
with 'large' absolute value.
|
| 1465 |
+
|
| 1466 |
+
Parameters
|
| 1467 |
+
----------
|
| 1468 |
+
a : (N, N) array_like
|
| 1469 |
+
Real symmetric or complex hermetian matrix to be pseudo-inverted
|
| 1470 |
+
|
| 1471 |
+
atol : float, optional
|
| 1472 |
+
Absolute threshold term, default value is 0.
|
| 1473 |
+
|
| 1474 |
+
.. versionadded:: 1.7.0
|
| 1475 |
+
|
| 1476 |
+
rtol : float, optional
|
| 1477 |
+
Relative threshold term, default value is ``N * eps`` where
|
| 1478 |
+
``eps`` is the machine precision value of the datatype of ``a``.
|
| 1479 |
+
|
| 1480 |
+
.. versionadded:: 1.7.0
|
| 1481 |
+
|
| 1482 |
+
lower : bool, optional
|
| 1483 |
+
Whether the pertinent array data is taken from the lower or upper
|
| 1484 |
+
triangle of `a`. (Default: lower)
|
| 1485 |
+
return_rank : bool, optional
|
| 1486 |
+
If True, return the effective rank of the matrix.
|
| 1487 |
+
check_finite : bool, optional
|
| 1488 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1489 |
+
Disabling may give a performance gain, but may result in problems
|
| 1490 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1491 |
+
|
| 1492 |
+
Returns
|
| 1493 |
+
-------
|
| 1494 |
+
B : (N, N) ndarray
|
| 1495 |
+
The pseudo-inverse of matrix `a`.
|
| 1496 |
+
rank : int
|
| 1497 |
+
The effective rank of the matrix. Returned if `return_rank` is True.
|
| 1498 |
+
|
| 1499 |
+
Raises
|
| 1500 |
+
------
|
| 1501 |
+
LinAlgError
|
| 1502 |
+
If eigenvalue algorithm does not converge.
|
| 1503 |
+
|
| 1504 |
+
See Also
|
| 1505 |
+
--------
|
| 1506 |
+
pinv : Moore-Penrose pseudoinverse of a matrix.
|
| 1507 |
+
|
| 1508 |
+
Examples
|
| 1509 |
+
--------
|
| 1510 |
+
|
| 1511 |
+
For a more detailed example see `pinv`.
|
| 1512 |
+
|
| 1513 |
+
>>> import numpy as np
|
| 1514 |
+
>>> from scipy.linalg import pinvh
|
| 1515 |
+
>>> rng = np.random.default_rng()
|
| 1516 |
+
>>> a = rng.standard_normal((9, 6))
|
| 1517 |
+
>>> a = np.dot(a, a.T)
|
| 1518 |
+
>>> B = pinvh(a)
|
| 1519 |
+
>>> np.allclose(a, a @ B @ a)
|
| 1520 |
+
True
|
| 1521 |
+
>>> np.allclose(B, B @ a @ B)
|
| 1522 |
+
True
|
| 1523 |
+
|
| 1524 |
+
"""
|
| 1525 |
+
a = _asarray_validated(a, check_finite=check_finite)
|
| 1526 |
+
s, u = _decomp.eigh(a, lower=lower, check_finite=False)
|
| 1527 |
+
t = u.dtype.char.lower()
|
| 1528 |
+
maxS = np.max(np.abs(s))
|
| 1529 |
+
|
| 1530 |
+
atol = 0. if atol is None else atol
|
| 1531 |
+
rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
|
| 1532 |
+
|
| 1533 |
+
if (atol < 0.) or (rtol < 0.):
|
| 1534 |
+
raise ValueError("atol and rtol values must be positive.")
|
| 1535 |
+
|
| 1536 |
+
val = atol + maxS * rtol
|
| 1537 |
+
above_cutoff = (abs(s) > val)
|
| 1538 |
+
|
| 1539 |
+
psigma_diag = 1.0 / s[above_cutoff]
|
| 1540 |
+
u = u[:, above_cutoff]
|
| 1541 |
+
|
| 1542 |
+
B = (u * psigma_diag) @ u.conj().T
|
| 1543 |
+
|
| 1544 |
+
if return_rank:
|
| 1545 |
+
return B, len(psigma_diag)
|
| 1546 |
+
else:
|
| 1547 |
+
return B
|
| 1548 |
+
|
| 1549 |
+
|
| 1550 |
+
def matrix_balance(A, permute=True, scale=True, separate=False,
|
| 1551 |
+
overwrite_a=False):
|
| 1552 |
+
"""
|
| 1553 |
+
Compute a diagonal similarity transformation for row/column balancing.
|
| 1554 |
+
|
| 1555 |
+
The balancing tries to equalize the row and column 1-norms by applying
|
| 1556 |
+
a similarity transformation such that the magnitude variation of the
|
| 1557 |
+
matrix entries is reflected to the scaling matrices.
|
| 1558 |
+
|
| 1559 |
+
Moreover, if enabled, the matrix is first permuted to isolate the upper
|
| 1560 |
+
triangular parts of the matrix and, again if scaling is also enabled,
|
| 1561 |
+
only the remaining subblocks are subjected to scaling.
|
| 1562 |
+
|
| 1563 |
+
The balanced matrix satisfies the following equality
|
| 1564 |
+
|
| 1565 |
+
.. math::
|
| 1566 |
+
|
| 1567 |
+
B = T^{-1} A T
|
| 1568 |
+
|
| 1569 |
+
The scaling coefficients are approximated to the nearest power of 2
|
| 1570 |
+
to avoid round-off errors.
|
| 1571 |
+
|
| 1572 |
+
Parameters
|
| 1573 |
+
----------
|
| 1574 |
+
A : (n, n) array_like
|
| 1575 |
+
Square data matrix for the balancing.
|
| 1576 |
+
permute : bool, optional
|
| 1577 |
+
The selector to define whether permutation of A is also performed
|
| 1578 |
+
prior to scaling.
|
| 1579 |
+
scale : bool, optional
|
| 1580 |
+
The selector to turn on and off the scaling. If False, the matrix
|
| 1581 |
+
will not be scaled.
|
| 1582 |
+
separate : bool, optional
|
| 1583 |
+
This switches from returning a full matrix of the transformation
|
| 1584 |
+
to a tuple of two separate 1-D permutation and scaling arrays.
|
| 1585 |
+
overwrite_a : bool, optional
|
| 1586 |
+
This is passed to xGEBAL directly. Essentially, overwrites the result
|
| 1587 |
+
to the data. It might increase the space efficiency. See LAPACK manual
|
| 1588 |
+
for details. This is False by default.
|
| 1589 |
+
|
| 1590 |
+
Returns
|
| 1591 |
+
-------
|
| 1592 |
+
B : (n, n) ndarray
|
| 1593 |
+
Balanced matrix
|
| 1594 |
+
T : (n, n) ndarray
|
| 1595 |
+
A possibly permuted diagonal matrix whose nonzero entries are
|
| 1596 |
+
integer powers of 2 to avoid numerical truncation errors.
|
| 1597 |
+
scale, perm : (n,) ndarray
|
| 1598 |
+
If ``separate`` keyword is set to True then instead of the array
|
| 1599 |
+
``T`` above, the scaling and the permutation vectors are given
|
| 1600 |
+
separately as a tuple without allocating the full array ``T``.
|
| 1601 |
+
|
| 1602 |
+
Notes
|
| 1603 |
+
-----
|
| 1604 |
+
This algorithm is particularly useful for eigenvalue and matrix
|
| 1605 |
+
decompositions and in many cases it is already called by various
|
| 1606 |
+
LAPACK routines.
|
| 1607 |
+
|
| 1608 |
+
The algorithm is based on the well-known technique of [1]_ and has
|
| 1609 |
+
been modified to account for special cases. See [2]_ for details
|
| 1610 |
+
which have been implemented since LAPACK v3.5.0. Before this version
|
| 1611 |
+
there are corner cases where balancing can actually worsen the
|
| 1612 |
+
conditioning. See [3]_ for such examples.
|
| 1613 |
+
|
| 1614 |
+
The code is a wrapper around LAPACK's xGEBAL routine family for matrix
|
| 1615 |
+
balancing.
|
| 1616 |
+
|
| 1617 |
+
.. versionadded:: 0.19.0
|
| 1618 |
+
|
| 1619 |
+
References
|
| 1620 |
+
----------
|
| 1621 |
+
.. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for
|
| 1622 |
+
Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik,
|
| 1623 |
+
Vol.13(4), 1969, :doi:`10.1007/BF02165404`
|
| 1624 |
+
.. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and
|
| 1625 |
+
eigenvector computation", 2014, :arxiv:`1401.5766`
|
| 1626 |
+
.. [3] D.S. Watkins. A case where balancing is harmful.
|
| 1627 |
+
Electron. Trans. Numer. Anal, Vol.23, 2006.
|
| 1628 |
+
|
| 1629 |
+
Examples
|
| 1630 |
+
--------
|
| 1631 |
+
>>> import numpy as np
|
| 1632 |
+
>>> from scipy import linalg
|
| 1633 |
+
>>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]])
|
| 1634 |
+
|
| 1635 |
+
>>> y, permscale = linalg.matrix_balance(x)
|
| 1636 |
+
>>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1)
|
| 1637 |
+
array([ 3.66666667, 0.4995005 , 0.91312162])
|
| 1638 |
+
|
| 1639 |
+
>>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1)
|
| 1640 |
+
array([ 1.2 , 1.27041742, 0.92658316]) # may vary
|
| 1641 |
+
|
| 1642 |
+
>>> permscale # only powers of 2 (0.5 == 2^(-1))
|
| 1643 |
+
array([[ 0.5, 0. , 0. ], # may vary
|
| 1644 |
+
[ 0. , 1. , 0. ],
|
| 1645 |
+
[ 0. , 0. , 1. ]])
|
| 1646 |
+
|
| 1647 |
+
"""
|
| 1648 |
+
|
| 1649 |
+
A = np.atleast_2d(_asarray_validated(A, check_finite=True))
|
| 1650 |
+
|
| 1651 |
+
if not np.equal(*A.shape):
|
| 1652 |
+
raise ValueError('The data matrix for balancing should be square.')
|
| 1653 |
+
|
| 1654 |
+
gebal = get_lapack_funcs(('gebal'), (A,))
|
| 1655 |
+
B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute,
|
| 1656 |
+
overwrite_a=overwrite_a)
|
| 1657 |
+
|
| 1658 |
+
if info < 0:
|
| 1659 |
+
raise ValueError('xGEBAL exited with the internal error '
|
| 1660 |
+
f'"illegal value in argument number {-info}.". See '
|
| 1661 |
+
'LAPACK documentation for the xGEBAL error codes.')
|
| 1662 |
+
|
| 1663 |
+
# Separate the permutations from the scalings and then convert to int
|
| 1664 |
+
scaling = np.ones_like(ps, dtype=float)
|
| 1665 |
+
scaling[lo:hi+1] = ps[lo:hi+1]
|
| 1666 |
+
|
| 1667 |
+
# gebal uses 1-indexing
|
| 1668 |
+
ps = ps.astype(int, copy=False) - 1
|
| 1669 |
+
n = A.shape[0]
|
| 1670 |
+
perm = np.arange(n)
|
| 1671 |
+
|
| 1672 |
+
# LAPACK permutes with the ordering n --> hi, then 0--> lo
|
| 1673 |
+
if hi < n:
|
| 1674 |
+
for ind, x in enumerate(ps[hi+1:][::-1], 1):
|
| 1675 |
+
if n-ind == x:
|
| 1676 |
+
continue
|
| 1677 |
+
perm[[x, n-ind]] = perm[[n-ind, x]]
|
| 1678 |
+
|
| 1679 |
+
if lo > 0:
|
| 1680 |
+
for ind, x in enumerate(ps[:lo]):
|
| 1681 |
+
if ind == x:
|
| 1682 |
+
continue
|
| 1683 |
+
perm[[x, ind]] = perm[[ind, x]]
|
| 1684 |
+
|
| 1685 |
+
if separate:
|
| 1686 |
+
return B, (scaling, perm)
|
| 1687 |
+
|
| 1688 |
+
# get the inverse permutation
|
| 1689 |
+
iperm = np.empty_like(perm)
|
| 1690 |
+
iperm[perm] = np.arange(n)
|
| 1691 |
+
|
| 1692 |
+
return B, np.diag(scaling)[iperm, :]
|
| 1693 |
+
|
| 1694 |
+
|
| 1695 |
+
def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape,
|
| 1696 |
+
enforce_square=True):
|
| 1697 |
+
"""Validate arguments and format inputs for toeplitz functions
|
| 1698 |
+
|
| 1699 |
+
Parameters
|
| 1700 |
+
----------
|
| 1701 |
+
c_or_cr : array_like or tuple of (array_like, array_like)
|
| 1702 |
+
The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
|
| 1703 |
+
actual shape of ``c``, it will be converted to a 1-D array. If not
|
| 1704 |
+
supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
|
| 1705 |
+
real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
|
| 1706 |
+
of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
|
| 1707 |
+
of ``r``, it will be converted to a 1-D array.
|
| 1708 |
+
b : (M,) or (M, K) array_like
|
| 1709 |
+
Right-hand side in ``T x = b``.
|
| 1710 |
+
check_finite : bool
|
| 1711 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 1712 |
+
Disabling may give a performance gain, but may result in problems
|
| 1713 |
+
(result entirely NaNs) if the inputs do contain infinities or NaNs.
|
| 1714 |
+
keep_b_shape : bool
|
| 1715 |
+
Whether to convert a (M,) dimensional b into a (M, 1) dimensional
|
| 1716 |
+
matrix.
|
| 1717 |
+
enforce_square : bool, optional
|
| 1718 |
+
If True (default), this verifies that the Toeplitz matrix is square.
|
| 1719 |
+
|
| 1720 |
+
Returns
|
| 1721 |
+
-------
|
| 1722 |
+
r : array
|
| 1723 |
+
1d array corresponding to the first row of the Toeplitz matrix.
|
| 1724 |
+
c: array
|
| 1725 |
+
1d array corresponding to the first column of the Toeplitz matrix.
|
| 1726 |
+
b: array
|
| 1727 |
+
(M,), (M, 1) or (M, K) dimensional array, post validation,
|
| 1728 |
+
corresponding to ``b``.
|
| 1729 |
+
dtype: numpy datatype
|
| 1730 |
+
``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of
|
| 1731 |
+
``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``,
|
| 1732 |
+
otherwise, it is ``np.float``.
|
| 1733 |
+
b_shape: tuple
|
| 1734 |
+
Shape of ``b`` after passing it through ``_asarray_validated``.
|
| 1735 |
+
|
| 1736 |
+
"""
|
| 1737 |
+
|
| 1738 |
+
if isinstance(c_or_cr, tuple):
|
| 1739 |
+
c, r = c_or_cr
|
| 1740 |
+
c = _asarray_validated(c, check_finite=check_finite).ravel()
|
| 1741 |
+
r = _asarray_validated(r, check_finite=check_finite).ravel()
|
| 1742 |
+
else:
|
| 1743 |
+
c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel()
|
| 1744 |
+
r = c.conjugate()
|
| 1745 |
+
|
| 1746 |
+
if b is None:
|
| 1747 |
+
raise ValueError('`b` must be an array, not None.')
|
| 1748 |
+
|
| 1749 |
+
b = _asarray_validated(b, check_finite=check_finite)
|
| 1750 |
+
b_shape = b.shape
|
| 1751 |
+
|
| 1752 |
+
is_not_square = r.shape[0] != c.shape[0]
|
| 1753 |
+
if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]:
|
| 1754 |
+
raise ValueError('Incompatible dimensions.')
|
| 1755 |
+
|
| 1756 |
+
is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b)
|
| 1757 |
+
dtype = np.complex128 if is_cmplx else np.float64
|
| 1758 |
+
r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b))
|
| 1759 |
+
|
| 1760 |
+
if b.ndim == 1 and not keep_b_shape:
|
| 1761 |
+
b = b.reshape(-1, 1)
|
| 1762 |
+
elif b.ndim != 1:
|
| 1763 |
+
b = b.reshape(b.shape[0], -1)
|
| 1764 |
+
|
| 1765 |
+
return r, c, b, dtype, b_shape
|
| 1766 |
+
|
| 1767 |
+
|
| 1768 |
+
def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None):
|
| 1769 |
+
"""Efficient Toeplitz Matrix-Matrix Multiplication using FFT
|
| 1770 |
+
|
| 1771 |
+
This function returns the matrix multiplication between a Toeplitz
|
| 1772 |
+
matrix and a dense matrix.
|
| 1773 |
+
|
| 1774 |
+
The Toeplitz matrix has constant diagonals, with c as its first column
|
| 1775 |
+
and r as its first row. If r is not given, ``r == conjugate(c)`` is
|
| 1776 |
+
assumed.
|
| 1777 |
+
|
| 1778 |
+
Parameters
|
| 1779 |
+
----------
|
| 1780 |
+
c_or_cr : array_like or tuple of (array_like, array_like)
|
| 1781 |
+
The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
|
| 1782 |
+
actual shape of ``c``, it will be converted to a 1-D array. If not
|
| 1783 |
+
supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
|
| 1784 |
+
real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
|
| 1785 |
+
of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
|
| 1786 |
+
of ``r``, it will be converted to a 1-D array.
|
| 1787 |
+
x : (M,) or (M, K) array_like
|
| 1788 |
+
Matrix with which to multiply.
|
| 1789 |
+
check_finite : bool, optional
|
| 1790 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 1791 |
+
Disabling may give a performance gain, but may result in problems
|
| 1792 |
+
(result entirely NaNs) if the inputs do contain infinities or NaNs.
|
| 1793 |
+
workers : int, optional
|
| 1794 |
+
To pass to scipy.fft.fft and ifft. Maximum number of workers to use
|
| 1795 |
+
for parallel computation. If negative, the value wraps around from
|
| 1796 |
+
``os.cpu_count()``. See scipy.fft.fft for more details.
|
| 1797 |
+
|
| 1798 |
+
Returns
|
| 1799 |
+
-------
|
| 1800 |
+
T @ x : (M,) or (M, K) ndarray
|
| 1801 |
+
The result of the matrix multiplication ``T @ x``. Shape of return
|
| 1802 |
+
matches shape of `x`.
|
| 1803 |
+
|
| 1804 |
+
See Also
|
| 1805 |
+
--------
|
| 1806 |
+
toeplitz : Toeplitz matrix
|
| 1807 |
+
solve_toeplitz : Solve a Toeplitz system using Levinson Recursion
|
| 1808 |
+
|
| 1809 |
+
Notes
|
| 1810 |
+
-----
|
| 1811 |
+
The Toeplitz matrix is embedded in a circulant matrix and the FFT is used
|
| 1812 |
+
to efficiently calculate the matrix-matrix product.
|
| 1813 |
+
|
| 1814 |
+
Because the computation is based on the FFT, integer inputs will
|
| 1815 |
+
result in floating point outputs. This is unlike NumPy's `matmul`,
|
| 1816 |
+
which preserves the data type of the input.
|
| 1817 |
+
|
| 1818 |
+
This is partly based on the implementation that can be found in [1]_,
|
| 1819 |
+
licensed under the MIT license. More information about the method can be
|
| 1820 |
+
found in reference [2]_. References [3]_ and [4]_ have more reference
|
| 1821 |
+
implementations in Python.
|
| 1822 |
+
|
| 1823 |
+
.. versionadded:: 1.6.0
|
| 1824 |
+
|
| 1825 |
+
References
|
| 1826 |
+
----------
|
| 1827 |
+
.. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian
|
| 1828 |
+
Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix
|
| 1829 |
+
Gaussian Process Inference with GPU Acceleration" with contributions
|
| 1830 |
+
from Max Balandat and Ruihan Wu. Available online:
|
| 1831 |
+
https://github.com/cornellius-gp/gpytorch
|
| 1832 |
+
|
| 1833 |
+
.. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear
|
| 1834 |
+
Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der
|
| 1835 |
+
Vorst, editors. Templates for the Solution of Algebraic Eigenvalue
|
| 1836 |
+
Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at:
|
| 1837 |
+
http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
|
| 1838 |
+
|
| 1839 |
+
.. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python
|
| 1840 |
+
package for audio room simulations and array processing algorithms,
|
| 1841 |
+
Proc. IEEE ICASSP, Calgary, CA, 2018.
|
| 1842 |
+
https://github.com/LCAV/pyroomacoustics/blob/pypi-release/
|
| 1843 |
+
pyroomacoustics/adaptive/util.py
|
| 1844 |
+
|
| 1845 |
+
.. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting
|
| 1846 |
+
Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of
|
| 1847 |
+
the Seismological Society of America., January, 2017. Vol. 107(1),
|
| 1848 |
+
pp. 276-291.
|
| 1849 |
+
|
| 1850 |
+
Examples
|
| 1851 |
+
--------
|
| 1852 |
+
Multiply the Toeplitz matrix T with matrix x::
|
| 1853 |
+
|
| 1854 |
+
[ 1 -1 -2 -3] [1 10]
|
| 1855 |
+
T = [ 3 1 -1 -2] x = [2 11]
|
| 1856 |
+
[ 6 3 1 -1] [2 11]
|
| 1857 |
+
[10 6 3 1] [5 19]
|
| 1858 |
+
|
| 1859 |
+
To specify the Toeplitz matrix, only the first column and the first
|
| 1860 |
+
row are needed.
|
| 1861 |
+
|
| 1862 |
+
>>> import numpy as np
|
| 1863 |
+
>>> c = np.array([1, 3, 6, 10]) # First column of T
|
| 1864 |
+
>>> r = np.array([1, -1, -2, -3]) # First row of T
|
| 1865 |
+
>>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]])
|
| 1866 |
+
|
| 1867 |
+
>>> from scipy.linalg import toeplitz, matmul_toeplitz
|
| 1868 |
+
>>> matmul_toeplitz((c, r), x)
|
| 1869 |
+
array([[-20., -80.],
|
| 1870 |
+
[ -7., -8.],
|
| 1871 |
+
[ 9., 85.],
|
| 1872 |
+
[ 33., 218.]])
|
| 1873 |
+
|
| 1874 |
+
Check the result by creating the full Toeplitz matrix and
|
| 1875 |
+
multiplying it by ``x``.
|
| 1876 |
+
|
| 1877 |
+
>>> toeplitz(c, r) @ x
|
| 1878 |
+
array([[-20, -80],
|
| 1879 |
+
[ -7, -8],
|
| 1880 |
+
[ 9, 85],
|
| 1881 |
+
[ 33, 218]])
|
| 1882 |
+
|
| 1883 |
+
The full matrix is never formed explicitly, so this routine
|
| 1884 |
+
is suitable for very large Toeplitz matrices.
|
| 1885 |
+
|
| 1886 |
+
>>> n = 1000000
|
| 1887 |
+
>>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n))
|
| 1888 |
+
array([1., 1., 1., ..., 1., 1., 1.])
|
| 1889 |
+
|
| 1890 |
+
"""
|
| 1891 |
+
|
| 1892 |
+
from ..fft import fft, ifft, rfft, irfft
|
| 1893 |
+
|
| 1894 |
+
r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops(
|
| 1895 |
+
c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False)
|
| 1896 |
+
n, m = x.shape
|
| 1897 |
+
|
| 1898 |
+
T_nrows = len(c)
|
| 1899 |
+
T_ncols = len(r)
|
| 1900 |
+
p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col)
|
| 1901 |
+
|
| 1902 |
+
embedded_col = np.concatenate((c, r[-1:0:-1]))
|
| 1903 |
+
|
| 1904 |
+
if np.iscomplexobj(embedded_col) or np.iscomplexobj(x):
|
| 1905 |
+
fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
|
| 1906 |
+
fft_x = fft(x, n=p, axis=0, workers=workers)
|
| 1907 |
+
|
| 1908 |
+
mat_times_x = ifft(fft_mat*fft_x, axis=0,
|
| 1909 |
+
workers=workers)[:T_nrows, :]
|
| 1910 |
+
else:
|
| 1911 |
+
# Real inputs; using rfft is faster
|
| 1912 |
+
fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
|
| 1913 |
+
fft_x = rfft(x, n=p, axis=0, workers=workers)
|
| 1914 |
+
|
| 1915 |
+
mat_times_x = irfft(fft_mat*fft_x, axis=0,
|
| 1916 |
+
workers=workers, n=p)[:T_nrows, :]
|
| 1917 |
+
|
| 1918 |
+
return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m)
|
| 1919 |
+
return mat_times_x.reshape(*return_shape)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_blas_subroutines.h
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
This file was generated by _generate_pyx.py.
|
| 3 |
+
Do not edit this file directly.
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
#include "fortran_defs.h"
|
| 7 |
+
#include "npy_cblas.h"
|
| 8 |
+
|
| 9 |
+
#ifdef __cplusplus
|
| 10 |
+
extern "C" {
|
| 11 |
+
#endif
|
| 12 |
+
|
| 13 |
+
void BLAS_FUNC(caxpy)(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
|
| 14 |
+
void BLAS_FUNC(ccopy)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
|
| 15 |
+
void (cdotcwrp_)(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
|
| 16 |
+
void (cdotuwrp_)(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
|
| 17 |
+
void BLAS_FUNC(cgbmv)(char *trans, int *m, int *n, int *kl, int *ku, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
|
| 18 |
+
void BLAS_FUNC(cgemm)(char *transa, char *transb, int *m, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
|
| 19 |
+
void BLAS_FUNC(cgemv)(char *trans, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
|
| 20 |
+
void BLAS_FUNC(cgerc)(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
|
| 21 |
+
void BLAS_FUNC(cgeru)(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
|
| 22 |
+
void BLAS_FUNC(chbmv)(char *uplo, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
|
| 23 |
+
void BLAS_FUNC(chemm)(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
|
| 24 |
+
void BLAS_FUNC(chemv)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
|
| 25 |
+
void BLAS_FUNC(cher)(char *uplo, int *n, float *alpha, npy_complex64 *x, int *incx, npy_complex64 *a, int *lda);
|
| 26 |
+
void BLAS_FUNC(cher2)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
|
| 27 |
+
void BLAS_FUNC(cher2k)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, float *beta, npy_complex64 *c, int *ldc);
|
| 28 |
+
void BLAS_FUNC(cherk)(char *uplo, char *trans, int *n, int *k, float *alpha, npy_complex64 *a, int *lda, float *beta, npy_complex64 *c, int *ldc);
|
| 29 |
+
void BLAS_FUNC(chpmv)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *ap, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
|
| 30 |
+
void BLAS_FUNC(chpr)(char *uplo, int *n, float *alpha, npy_complex64 *x, int *incx, npy_complex64 *ap);
|
| 31 |
+
void BLAS_FUNC(chpr2)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *ap);
|
| 32 |
+
void BLAS_FUNC(crotg)(npy_complex64 *ca, npy_complex64 *cb, float *c, npy_complex64 *s);
|
| 33 |
+
void BLAS_FUNC(cscal)(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx);
|
| 34 |
+
void BLAS_FUNC(csrot)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy, float *c, float *s);
|
| 35 |
+
void BLAS_FUNC(csscal)(int *n, float *sa, npy_complex64 *cx, int *incx);
|
| 36 |
+
void BLAS_FUNC(cswap)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
|
| 37 |
+
void BLAS_FUNC(csymm)(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
|
| 38 |
+
void BLAS_FUNC(csyr2k)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
|
| 39 |
+
void BLAS_FUNC(csyrk)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *beta, npy_complex64 *c, int *ldc);
|
| 40 |
+
void BLAS_FUNC(ctbmv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
|
| 41 |
+
void BLAS_FUNC(ctbsv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
|
| 42 |
+
void BLAS_FUNC(ctpmv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx);
|
| 43 |
+
void BLAS_FUNC(ctpsv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx);
|
| 44 |
+
void BLAS_FUNC(ctrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb);
|
| 45 |
+
void BLAS_FUNC(ctrmv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
|
| 46 |
+
void BLAS_FUNC(ctrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb);
|
| 47 |
+
void BLAS_FUNC(ctrsv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
|
| 48 |
+
double BLAS_FUNC(dasum)(int *n, double *dx, int *incx);
|
| 49 |
+
void BLAS_FUNC(daxpy)(int *n, double *da, double *dx, int *incx, double *dy, int *incy);
|
| 50 |
+
double BLAS_FUNC(dcabs1)(npy_complex128 *z);
|
| 51 |
+
void BLAS_FUNC(dcopy)(int *n, double *dx, int *incx, double *dy, int *incy);
|
| 52 |
+
double BLAS_FUNC(ddot)(int *n, double *dx, int *incx, double *dy, int *incy);
|
| 53 |
+
void BLAS_FUNC(dgbmv)(char *trans, int *m, int *n, int *kl, int *ku, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
|
| 54 |
+
void BLAS_FUNC(dgemm)(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
|
| 55 |
+
void BLAS_FUNC(dgemv)(char *trans, int *m, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
|
| 56 |
+
void BLAS_FUNC(dger)(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda);
|
| 57 |
+
double BLAS_FUNC(dnrm2)(int *n, double *x, int *incx);
|
| 58 |
+
void BLAS_FUNC(drot)(int *n, double *dx, int *incx, double *dy, int *incy, double *c, double *s);
|
| 59 |
+
void BLAS_FUNC(drotg)(double *da, double *db, double *c, double *s);
|
| 60 |
+
void BLAS_FUNC(drotm)(int *n, double *dx, int *incx, double *dy, int *incy, double *dparam);
|
| 61 |
+
void BLAS_FUNC(drotmg)(double *dd1, double *dd2, double *dx1, double *dy1, double *dparam);
|
| 62 |
+
void BLAS_FUNC(dsbmv)(char *uplo, int *n, int *k, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
|
| 63 |
+
void BLAS_FUNC(dscal)(int *n, double *da, double *dx, int *incx);
|
| 64 |
+
double BLAS_FUNC(dsdot)(int *n, float *sx, int *incx, float *sy, int *incy);
|
| 65 |
+
void BLAS_FUNC(dspmv)(char *uplo, int *n, double *alpha, double *ap, double *x, int *incx, double *beta, double *y, int *incy);
|
| 66 |
+
void BLAS_FUNC(dspr)(char *uplo, int *n, double *alpha, double *x, int *incx, double *ap);
|
| 67 |
+
void BLAS_FUNC(dspr2)(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *ap);
|
| 68 |
+
void BLAS_FUNC(dswap)(int *n, double *dx, int *incx, double *dy, int *incy);
|
| 69 |
+
void BLAS_FUNC(dsymm)(char *side, char *uplo, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
|
| 70 |
+
void BLAS_FUNC(dsymv)(char *uplo, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
|
| 71 |
+
void BLAS_FUNC(dsyr)(char *uplo, int *n, double *alpha, double *x, int *incx, double *a, int *lda);
|
| 72 |
+
void BLAS_FUNC(dsyr2)(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda);
|
| 73 |
+
void BLAS_FUNC(dsyr2k)(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
|
| 74 |
+
void BLAS_FUNC(dsyrk)(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *beta, double *c, int *ldc);
|
| 75 |
+
void BLAS_FUNC(dtbmv)(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx);
|
| 76 |
+
void BLAS_FUNC(dtbsv)(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx);
|
| 77 |
+
void BLAS_FUNC(dtpmv)(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx);
|
| 78 |
+
void BLAS_FUNC(dtpsv)(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx);
|
| 79 |
+
void BLAS_FUNC(dtrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb);
|
| 80 |
+
void BLAS_FUNC(dtrmv)(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx);
|
| 81 |
+
void BLAS_FUNC(dtrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb);
|
| 82 |
+
void BLAS_FUNC(dtrsv)(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx);
|
| 83 |
+
double BLAS_FUNC(dzasum)(int *n, npy_complex128 *zx, int *incx);
|
| 84 |
+
double BLAS_FUNC(dznrm2)(int *n, npy_complex128 *x, int *incx);
|
| 85 |
+
int BLAS_FUNC(icamax)(int *n, npy_complex64 *cx, int *incx);
|
| 86 |
+
int BLAS_FUNC(idamax)(int *n, double *dx, int *incx);
|
| 87 |
+
int BLAS_FUNC(isamax)(int *n, float *sx, int *incx);
|
| 88 |
+
int BLAS_FUNC(izamax)(int *n, npy_complex128 *zx, int *incx);
|
| 89 |
+
int BLAS_FUNC(lsame)(char *ca, char *cb);
|
| 90 |
+
float BLAS_FUNC(sasum)(int *n, float *sx, int *incx);
|
| 91 |
+
void BLAS_FUNC(saxpy)(int *n, float *sa, float *sx, int *incx, float *sy, int *incy);
|
| 92 |
+
float BLAS_FUNC(scasum)(int *n, npy_complex64 *cx, int *incx);
|
| 93 |
+
float BLAS_FUNC(scnrm2)(int *n, npy_complex64 *x, int *incx);
|
| 94 |
+
void BLAS_FUNC(scopy)(int *n, float *sx, int *incx, float *sy, int *incy);
|
| 95 |
+
float BLAS_FUNC(sdot)(int *n, float *sx, int *incx, float *sy, int *incy);
|
| 96 |
+
float BLAS_FUNC(sdsdot)(int *n, float *sb, float *sx, int *incx, float *sy, int *incy);
|
| 97 |
+
void BLAS_FUNC(sgbmv)(char *trans, int *m, int *n, int *kl, int *ku, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
|
| 98 |
+
void BLAS_FUNC(sgemm)(char *transa, char *transb, int *m, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
|
| 99 |
+
void BLAS_FUNC(sgemv)(char *trans, int *m, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
|
| 100 |
+
void BLAS_FUNC(sger)(int *m, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda);
|
| 101 |
+
float BLAS_FUNC(snrm2)(int *n, float *x, int *incx);
|
| 102 |
+
void BLAS_FUNC(srot)(int *n, float *sx, int *incx, float *sy, int *incy, float *c, float *s);
|
| 103 |
+
void BLAS_FUNC(srotg)(float *sa, float *sb, float *c, float *s);
|
| 104 |
+
void BLAS_FUNC(srotm)(int *n, float *sx, int *incx, float *sy, int *incy, float *sparam);
|
| 105 |
+
void BLAS_FUNC(srotmg)(float *sd1, float *sd2, float *sx1, float *sy1, float *sparam);
|
| 106 |
+
void BLAS_FUNC(ssbmv)(char *uplo, int *n, int *k, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
|
| 107 |
+
void BLAS_FUNC(sscal)(int *n, float *sa, float *sx, int *incx);
|
| 108 |
+
void BLAS_FUNC(sspmv)(char *uplo, int *n, float *alpha, float *ap, float *x, int *incx, float *beta, float *y, int *incy);
|
| 109 |
+
void BLAS_FUNC(sspr)(char *uplo, int *n, float *alpha, float *x, int *incx, float *ap);
|
| 110 |
+
void BLAS_FUNC(sspr2)(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *ap);
|
| 111 |
+
void BLAS_FUNC(sswap)(int *n, float *sx, int *incx, float *sy, int *incy);
|
| 112 |
+
void BLAS_FUNC(ssymm)(char *side, char *uplo, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
|
| 113 |
+
void BLAS_FUNC(ssymv)(char *uplo, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
|
| 114 |
+
void BLAS_FUNC(ssyr)(char *uplo, int *n, float *alpha, float *x, int *incx, float *a, int *lda);
|
| 115 |
+
void BLAS_FUNC(ssyr2)(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda);
|
| 116 |
+
void BLAS_FUNC(ssyr2k)(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
|
| 117 |
+
void BLAS_FUNC(ssyrk)(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *beta, float *c, int *ldc);
|
| 118 |
+
void BLAS_FUNC(stbmv)(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx);
|
| 119 |
+
void BLAS_FUNC(stbsv)(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx);
|
| 120 |
+
void BLAS_FUNC(stpmv)(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx);
|
| 121 |
+
void BLAS_FUNC(stpsv)(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx);
|
| 122 |
+
void BLAS_FUNC(strmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb);
|
| 123 |
+
void BLAS_FUNC(strmv)(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx);
|
| 124 |
+
void BLAS_FUNC(strsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb);
|
| 125 |
+
void BLAS_FUNC(strsv)(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx);
|
| 126 |
+
void BLAS_FUNC(zaxpy)(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
|
| 127 |
+
void BLAS_FUNC(zcopy)(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
|
| 128 |
+
void (zdotcwrp_)(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
|
| 129 |
+
void (zdotuwrp_)(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
|
| 130 |
+
void BLAS_FUNC(zdrot)(int *n, npy_complex128 *cx, int *incx, npy_complex128 *cy, int *incy, double *c, double *s);
|
| 131 |
+
void BLAS_FUNC(zdscal)(int *n, double *da, npy_complex128 *zx, int *incx);
|
| 132 |
+
void BLAS_FUNC(zgbmv)(char *trans, int *m, int *n, int *kl, int *ku, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
|
| 133 |
+
void BLAS_FUNC(zgemm)(char *transa, char *transb, int *m, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
|
| 134 |
+
void BLAS_FUNC(zgemv)(char *trans, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
|
| 135 |
+
void BLAS_FUNC(zgerc)(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
|
| 136 |
+
void BLAS_FUNC(zgeru)(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
|
| 137 |
+
void BLAS_FUNC(zhbmv)(char *uplo, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
|
| 138 |
+
void BLAS_FUNC(zhemm)(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
|
| 139 |
+
void BLAS_FUNC(zhemv)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
|
| 140 |
+
void BLAS_FUNC(zher)(char *uplo, int *n, double *alpha, npy_complex128 *x, int *incx, npy_complex128 *a, int *lda);
|
| 141 |
+
void BLAS_FUNC(zher2)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
|
| 142 |
+
void BLAS_FUNC(zher2k)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, double *beta, npy_complex128 *c, int *ldc);
|
| 143 |
+
void BLAS_FUNC(zherk)(char *uplo, char *trans, int *n, int *k, double *alpha, npy_complex128 *a, int *lda, double *beta, npy_complex128 *c, int *ldc);
|
| 144 |
+
void BLAS_FUNC(zhpmv)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *ap, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
|
| 145 |
+
void BLAS_FUNC(zhpr)(char *uplo, int *n, double *alpha, npy_complex128 *x, int *incx, npy_complex128 *ap);
|
| 146 |
+
void BLAS_FUNC(zhpr2)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *ap);
|
| 147 |
+
void BLAS_FUNC(zrotg)(npy_complex128 *ca, npy_complex128 *cb, double *c, npy_complex128 *s);
|
| 148 |
+
void BLAS_FUNC(zscal)(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx);
|
| 149 |
+
void BLAS_FUNC(zswap)(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
|
| 150 |
+
void BLAS_FUNC(zsymm)(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
|
| 151 |
+
void BLAS_FUNC(zsyr2k)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
|
| 152 |
+
void BLAS_FUNC(zsyrk)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *beta, npy_complex128 *c, int *ldc);
|
| 153 |
+
void BLAS_FUNC(ztbmv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
|
| 154 |
+
void BLAS_FUNC(ztbsv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
|
| 155 |
+
void BLAS_FUNC(ztpmv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx);
|
| 156 |
+
void BLAS_FUNC(ztpsv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx);
|
| 157 |
+
void BLAS_FUNC(ztrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb);
|
| 158 |
+
void BLAS_FUNC(ztrmv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
|
| 159 |
+
void BLAS_FUNC(ztrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb);
|
| 160 |
+
void BLAS_FUNC(ztrsv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
|
| 161 |
+
|
| 162 |
+
#ifdef __cplusplus
|
| 163 |
+
}
|
| 164 |
+
#endif
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pxd
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport numpy as cnp
|
| 2 |
+
|
| 3 |
+
ctypedef fused lapack_t:
|
| 4 |
+
float
|
| 5 |
+
double
|
| 6 |
+
(float complex)
|
| 7 |
+
(double complex)
|
| 8 |
+
|
| 9 |
+
ctypedef fused lapack_cz_t:
|
| 10 |
+
(float complex)
|
| 11 |
+
(double complex)
|
| 12 |
+
|
| 13 |
+
ctypedef fused lapack_sd_t:
|
| 14 |
+
float
|
| 15 |
+
double
|
| 16 |
+
|
| 17 |
+
ctypedef fused np_numeric_t:
|
| 18 |
+
cnp.int8_t
|
| 19 |
+
cnp.int16_t
|
| 20 |
+
cnp.int32_t
|
| 21 |
+
cnp.int64_t
|
| 22 |
+
cnp.uint8_t
|
| 23 |
+
cnp.uint16_t
|
| 24 |
+
cnp.uint32_t
|
| 25 |
+
cnp.uint64_t
|
| 26 |
+
cnp.float32_t
|
| 27 |
+
cnp.float64_t
|
| 28 |
+
cnp.longdouble_t
|
| 29 |
+
cnp.complex64_t
|
| 30 |
+
cnp.complex128_t
|
| 31 |
+
|
| 32 |
+
ctypedef fused np_complex_numeric_t:
|
| 33 |
+
cnp.complex64_t
|
| 34 |
+
cnp.complex128_t
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
cdef void swap_c_and_f_layout(lapack_t *a, lapack_t *b, int r, int c) noexcept nogil
|
| 38 |
+
cdef (int, int) band_check_internal_c(np_numeric_t[:, ::1]A) noexcept nogil
|
| 39 |
+
cdef bint is_sym_her_real_c_internal(np_numeric_t[:, ::1]A) noexcept nogil
|
| 40 |
+
cdef bint is_sym_her_complex_c_internal(np_complex_numeric_t[:, ::1]A) noexcept nogil
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pyi
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from numpy.typing import NDArray
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
def bandwidth(a: NDArray[Any]) -> tuple[int, int]: ...
|
| 5 |
+
|
| 6 |
+
def issymmetric(
|
| 7 |
+
a: NDArray[Any],
|
| 8 |
+
atol: None | float = ...,
|
| 9 |
+
rtol: None | float = ...,
|
| 10 |
+
) -> bool: ...
|
| 11 |
+
|
| 12 |
+
def ishermitian(
|
| 13 |
+
a: NDArray[Any],
|
| 14 |
+
atol: None | float = ...,
|
| 15 |
+
rtol: None | float = ...,
|
| 16 |
+
) -> bool: ...
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp.py
ADDED
|
@@ -0,0 +1,1621 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Author: Pearu Peterson, March 2002
|
| 3 |
+
#
|
| 4 |
+
# additions by Travis Oliphant, March 2002
|
| 5 |
+
# additions by Eric Jones, June 2002
|
| 6 |
+
# additions by Johannes Loehnert, June 2006
|
| 7 |
+
# additions by Bart Vandereycken, June 2006
|
| 8 |
+
# additions by Andrew D Straw, May 2007
|
| 9 |
+
# additions by Tiziano Zito, November 2008
|
| 10 |
+
#
|
| 11 |
+
# April 2010: Functions for LU, QR, SVD, Schur, and Cholesky decompositions
|
| 12 |
+
# were moved to their own files. Still in this file are functions for
|
| 13 |
+
# eigenstuff and for the Hessenberg form.
|
| 14 |
+
|
| 15 |
+
__all__ = ['eig', 'eigvals', 'eigh', 'eigvalsh',
|
| 16 |
+
'eig_banded', 'eigvals_banded',
|
| 17 |
+
'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf']
|
| 18 |
+
|
| 19 |
+
import warnings
|
| 20 |
+
|
| 21 |
+
import numpy
|
| 22 |
+
from numpy import (array, isfinite, inexact, nonzero, iscomplexobj,
|
| 23 |
+
flatnonzero, conj, asarray, argsort, empty,
|
| 24 |
+
iscomplex, zeros, einsum, eye, inf)
|
| 25 |
+
# Local imports
|
| 26 |
+
from scipy._lib._util import _asarray_validated
|
| 27 |
+
from ._misc import LinAlgError, _datacopied, norm
|
| 28 |
+
from .lapack import get_lapack_funcs, _compute_lwork
|
| 29 |
+
from scipy._lib.deprecation import _NoValue, _deprecate_positional_args
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
_I = numpy.array(1j, dtype='F')
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def _make_complex_eigvecs(w, vin, dtype):
|
| 36 |
+
"""
|
| 37 |
+
Produce complex-valued eigenvectors from LAPACK DGGEV real-valued output
|
| 38 |
+
"""
|
| 39 |
+
# - see LAPACK man page DGGEV at ALPHAI
|
| 40 |
+
v = numpy.array(vin, dtype=dtype)
|
| 41 |
+
m = (w.imag > 0)
|
| 42 |
+
m[:-1] |= (w.imag[1:] < 0) # workaround for LAPACK bug, cf. ticket #709
|
| 43 |
+
for i in flatnonzero(m):
|
| 44 |
+
v.imag[:, i] = vin[:, i+1]
|
| 45 |
+
conj(v[:, i], v[:, i+1])
|
| 46 |
+
return v
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _make_eigvals(alpha, beta, homogeneous_eigvals):
|
| 50 |
+
if homogeneous_eigvals:
|
| 51 |
+
if beta is None:
|
| 52 |
+
return numpy.vstack((alpha, numpy.ones_like(alpha)))
|
| 53 |
+
else:
|
| 54 |
+
return numpy.vstack((alpha, beta))
|
| 55 |
+
else:
|
| 56 |
+
if beta is None:
|
| 57 |
+
return alpha
|
| 58 |
+
else:
|
| 59 |
+
w = numpy.empty_like(alpha)
|
| 60 |
+
alpha_zero = (alpha == 0)
|
| 61 |
+
beta_zero = (beta == 0)
|
| 62 |
+
beta_nonzero = ~beta_zero
|
| 63 |
+
w[beta_nonzero] = alpha[beta_nonzero]/beta[beta_nonzero]
|
| 64 |
+
# Use numpy.inf for complex values too since
|
| 65 |
+
# 1/numpy.inf = 0, i.e., it correctly behaves as projective
|
| 66 |
+
# infinity.
|
| 67 |
+
w[~alpha_zero & beta_zero] = numpy.inf
|
| 68 |
+
if numpy.all(alpha.imag == 0):
|
| 69 |
+
w[alpha_zero & beta_zero] = numpy.nan
|
| 70 |
+
else:
|
| 71 |
+
w[alpha_zero & beta_zero] = complex(numpy.nan, numpy.nan)
|
| 72 |
+
return w
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def _geneig(a1, b1, left, right, overwrite_a, overwrite_b,
|
| 76 |
+
homogeneous_eigvals):
|
| 77 |
+
ggev, = get_lapack_funcs(('ggev',), (a1, b1))
|
| 78 |
+
cvl, cvr = left, right
|
| 79 |
+
res = ggev(a1, b1, lwork=-1)
|
| 80 |
+
lwork = res[-2][0].real.astype(numpy.int_)
|
| 81 |
+
if ggev.typecode in 'cz':
|
| 82 |
+
alpha, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork,
|
| 83 |
+
overwrite_a, overwrite_b)
|
| 84 |
+
w = _make_eigvals(alpha, beta, homogeneous_eigvals)
|
| 85 |
+
else:
|
| 86 |
+
alphar, alphai, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr,
|
| 87 |
+
lwork, overwrite_a,
|
| 88 |
+
overwrite_b)
|
| 89 |
+
alpha = alphar + _I * alphai
|
| 90 |
+
w = _make_eigvals(alpha, beta, homogeneous_eigvals)
|
| 91 |
+
_check_info(info, 'generalized eig algorithm (ggev)')
|
| 92 |
+
|
| 93 |
+
only_real = numpy.all(w.imag == 0.0)
|
| 94 |
+
if not (ggev.typecode in 'cz' or only_real):
|
| 95 |
+
t = w.dtype.char
|
| 96 |
+
if left:
|
| 97 |
+
vl = _make_complex_eigvecs(w, vl, t)
|
| 98 |
+
if right:
|
| 99 |
+
vr = _make_complex_eigvecs(w, vr, t)
|
| 100 |
+
|
| 101 |
+
# the eigenvectors returned by the lapack function are NOT normalized
|
| 102 |
+
for i in range(vr.shape[0]):
|
| 103 |
+
if right:
|
| 104 |
+
vr[:, i] /= norm(vr[:, i])
|
| 105 |
+
if left:
|
| 106 |
+
vl[:, i] /= norm(vl[:, i])
|
| 107 |
+
|
| 108 |
+
if not (left or right):
|
| 109 |
+
return w
|
| 110 |
+
if left:
|
| 111 |
+
if right:
|
| 112 |
+
return w, vl, vr
|
| 113 |
+
return w, vl
|
| 114 |
+
return w, vr
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def eig(a, b=None, left=False, right=True, overwrite_a=False,
|
| 118 |
+
overwrite_b=False, check_finite=True, homogeneous_eigvals=False):
|
| 119 |
+
"""
|
| 120 |
+
Solve an ordinary or generalized eigenvalue problem of a square matrix.
|
| 121 |
+
|
| 122 |
+
Find eigenvalues w and right or left eigenvectors of a general matrix::
|
| 123 |
+
|
| 124 |
+
a vr[:,i] = w[i] b vr[:,i]
|
| 125 |
+
a.H vl[:,i] = w[i].conj() b.H vl[:,i]
|
| 126 |
+
|
| 127 |
+
where ``.H`` is the Hermitian conjugation.
|
| 128 |
+
|
| 129 |
+
Parameters
|
| 130 |
+
----------
|
| 131 |
+
a : (M, M) array_like
|
| 132 |
+
A complex or real matrix whose eigenvalues and eigenvectors
|
| 133 |
+
will be computed.
|
| 134 |
+
b : (M, M) array_like, optional
|
| 135 |
+
Right-hand side matrix in a generalized eigenvalue problem.
|
| 136 |
+
Default is None, identity matrix is assumed.
|
| 137 |
+
left : bool, optional
|
| 138 |
+
Whether to calculate and return left eigenvectors. Default is False.
|
| 139 |
+
right : bool, optional
|
| 140 |
+
Whether to calculate and return right eigenvectors. Default is True.
|
| 141 |
+
overwrite_a : bool, optional
|
| 142 |
+
Whether to overwrite `a`; may improve performance. Default is False.
|
| 143 |
+
overwrite_b : bool, optional
|
| 144 |
+
Whether to overwrite `b`; may improve performance. Default is False.
|
| 145 |
+
check_finite : bool, optional
|
| 146 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 147 |
+
Disabling may give a performance gain, but may result in problems
|
| 148 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 149 |
+
homogeneous_eigvals : bool, optional
|
| 150 |
+
If True, return the eigenvalues in homogeneous coordinates.
|
| 151 |
+
In this case ``w`` is a (2, M) array so that::
|
| 152 |
+
|
| 153 |
+
w[1,i] a vr[:,i] = w[0,i] b vr[:,i]
|
| 154 |
+
|
| 155 |
+
Default is False.
|
| 156 |
+
|
| 157 |
+
Returns
|
| 158 |
+
-------
|
| 159 |
+
w : (M,) or (2, M) double or complex ndarray
|
| 160 |
+
The eigenvalues, each repeated according to its
|
| 161 |
+
multiplicity. The shape is (M,) unless
|
| 162 |
+
``homogeneous_eigvals=True``.
|
| 163 |
+
vl : (M, M) double or complex ndarray
|
| 164 |
+
The left eigenvector corresponding to the eigenvalue
|
| 165 |
+
``w[i]`` is the column ``vl[:,i]``. Only returned if ``left=True``.
|
| 166 |
+
The left eigenvector is not normalized.
|
| 167 |
+
vr : (M, M) double or complex ndarray
|
| 168 |
+
The normalized right eigenvector corresponding to the eigenvalue
|
| 169 |
+
``w[i]`` is the column ``vr[:,i]``. Only returned if ``right=True``.
|
| 170 |
+
|
| 171 |
+
Raises
|
| 172 |
+
------
|
| 173 |
+
LinAlgError
|
| 174 |
+
If eigenvalue computation does not converge.
|
| 175 |
+
|
| 176 |
+
See Also
|
| 177 |
+
--------
|
| 178 |
+
eigvals : eigenvalues of general arrays
|
| 179 |
+
eigh : Eigenvalues and right eigenvectors for symmetric/Hermitian arrays.
|
| 180 |
+
eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
|
| 181 |
+
band matrices
|
| 182 |
+
eigh_tridiagonal : eigenvalues and right eiegenvectors for
|
| 183 |
+
symmetric/Hermitian tridiagonal matrices
|
| 184 |
+
|
| 185 |
+
Examples
|
| 186 |
+
--------
|
| 187 |
+
>>> import numpy as np
|
| 188 |
+
>>> from scipy import linalg
|
| 189 |
+
>>> a = np.array([[0., -1.], [1., 0.]])
|
| 190 |
+
>>> linalg.eigvals(a)
|
| 191 |
+
array([0.+1.j, 0.-1.j])
|
| 192 |
+
|
| 193 |
+
>>> b = np.array([[0., 1.], [1., 1.]])
|
| 194 |
+
>>> linalg.eigvals(a, b)
|
| 195 |
+
array([ 1.+0.j, -1.+0.j])
|
| 196 |
+
|
| 197 |
+
>>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]])
|
| 198 |
+
>>> linalg.eigvals(a, homogeneous_eigvals=True)
|
| 199 |
+
array([[3.+0.j, 8.+0.j, 7.+0.j],
|
| 200 |
+
[1.+0.j, 1.+0.j, 1.+0.j]])
|
| 201 |
+
|
| 202 |
+
>>> a = np.array([[0., -1.], [1., 0.]])
|
| 203 |
+
>>> linalg.eigvals(a) == linalg.eig(a)[0]
|
| 204 |
+
array([ True, True])
|
| 205 |
+
>>> linalg.eig(a, left=True, right=False)[1] # normalized left eigenvector
|
| 206 |
+
array([[-0.70710678+0.j , -0.70710678-0.j ],
|
| 207 |
+
[-0. +0.70710678j, -0. -0.70710678j]])
|
| 208 |
+
>>> linalg.eig(a, left=False, right=True)[1] # normalized right eigenvector
|
| 209 |
+
array([[0.70710678+0.j , 0.70710678-0.j ],
|
| 210 |
+
[0. -0.70710678j, 0. +0.70710678j]])
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
"""
|
| 215 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 216 |
+
if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
|
| 217 |
+
raise ValueError('expected square matrix')
|
| 218 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 219 |
+
if b is not None:
|
| 220 |
+
b1 = _asarray_validated(b, check_finite=check_finite)
|
| 221 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 222 |
+
if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]:
|
| 223 |
+
raise ValueError('expected square matrix')
|
| 224 |
+
if b1.shape != a1.shape:
|
| 225 |
+
raise ValueError('a and b must have the same shape')
|
| 226 |
+
return _geneig(a1, b1, left, right, overwrite_a, overwrite_b,
|
| 227 |
+
homogeneous_eigvals)
|
| 228 |
+
|
| 229 |
+
geev, geev_lwork = get_lapack_funcs(('geev', 'geev_lwork'), (a1,))
|
| 230 |
+
compute_vl, compute_vr = left, right
|
| 231 |
+
|
| 232 |
+
lwork = _compute_lwork(geev_lwork, a1.shape[0],
|
| 233 |
+
compute_vl=compute_vl,
|
| 234 |
+
compute_vr=compute_vr)
|
| 235 |
+
|
| 236 |
+
if geev.typecode in 'cz':
|
| 237 |
+
w, vl, vr, info = geev(a1, lwork=lwork,
|
| 238 |
+
compute_vl=compute_vl,
|
| 239 |
+
compute_vr=compute_vr,
|
| 240 |
+
overwrite_a=overwrite_a)
|
| 241 |
+
w = _make_eigvals(w, None, homogeneous_eigvals)
|
| 242 |
+
else:
|
| 243 |
+
wr, wi, vl, vr, info = geev(a1, lwork=lwork,
|
| 244 |
+
compute_vl=compute_vl,
|
| 245 |
+
compute_vr=compute_vr,
|
| 246 |
+
overwrite_a=overwrite_a)
|
| 247 |
+
t = {'f': 'F', 'd': 'D'}[wr.dtype.char]
|
| 248 |
+
w = wr + _I * wi
|
| 249 |
+
w = _make_eigvals(w, None, homogeneous_eigvals)
|
| 250 |
+
|
| 251 |
+
_check_info(info, 'eig algorithm (geev)',
|
| 252 |
+
positive='did not converge (only eigenvalues '
|
| 253 |
+
'with order >= %d have converged)')
|
| 254 |
+
|
| 255 |
+
only_real = numpy.all(w.imag == 0.0)
|
| 256 |
+
if not (geev.typecode in 'cz' or only_real):
|
| 257 |
+
t = w.dtype.char
|
| 258 |
+
if left:
|
| 259 |
+
vl = _make_complex_eigvecs(w, vl, t)
|
| 260 |
+
if right:
|
| 261 |
+
vr = _make_complex_eigvecs(w, vr, t)
|
| 262 |
+
if not (left or right):
|
| 263 |
+
return w
|
| 264 |
+
if left:
|
| 265 |
+
if right:
|
| 266 |
+
return w, vl, vr
|
| 267 |
+
return w, vl
|
| 268 |
+
return w, vr
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
@_deprecate_positional_args(version="1.14.0")
|
| 272 |
+
def eigh(a, b=None, *, lower=True, eigvals_only=False, overwrite_a=False,
|
| 273 |
+
overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1,
|
| 274 |
+
check_finite=True, subset_by_index=None, subset_by_value=None,
|
| 275 |
+
driver=None):
|
| 276 |
+
"""
|
| 277 |
+
Solve a standard or generalized eigenvalue problem for a complex
|
| 278 |
+
Hermitian or real symmetric matrix.
|
| 279 |
+
|
| 280 |
+
Find eigenvalues array ``w`` and optionally eigenvectors array ``v`` of
|
| 281 |
+
array ``a``, where ``b`` is positive definite such that for every
|
| 282 |
+
eigenvalue λ (i-th entry of w) and its eigenvector ``vi`` (i-th column of
|
| 283 |
+
``v``) satisfies::
|
| 284 |
+
|
| 285 |
+
a @ vi = λ * b @ vi
|
| 286 |
+
vi.conj().T @ a @ vi = λ
|
| 287 |
+
vi.conj().T @ b @ vi = 1
|
| 288 |
+
|
| 289 |
+
In the standard problem, ``b`` is assumed to be the identity matrix.
|
| 290 |
+
|
| 291 |
+
Parameters
|
| 292 |
+
----------
|
| 293 |
+
a : (M, M) array_like
|
| 294 |
+
A complex Hermitian or real symmetric matrix whose eigenvalues and
|
| 295 |
+
eigenvectors will be computed.
|
| 296 |
+
b : (M, M) array_like, optional
|
| 297 |
+
A complex Hermitian or real symmetric definite positive matrix in.
|
| 298 |
+
If omitted, identity matrix is assumed.
|
| 299 |
+
lower : bool, optional
|
| 300 |
+
Whether the pertinent array data is taken from the lower or upper
|
| 301 |
+
triangle of ``a`` and, if applicable, ``b``. (Default: lower)
|
| 302 |
+
eigvals_only : bool, optional
|
| 303 |
+
Whether to calculate only eigenvalues and no eigenvectors.
|
| 304 |
+
(Default: both are calculated)
|
| 305 |
+
subset_by_index : iterable, optional
|
| 306 |
+
If provided, this two-element iterable defines the start and the end
|
| 307 |
+
indices of the desired eigenvalues (ascending order and 0-indexed).
|
| 308 |
+
To return only the second smallest to fifth smallest eigenvalues,
|
| 309 |
+
``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only
|
| 310 |
+
available with "evr", "evx", and "gvx" drivers. The entries are
|
| 311 |
+
directly converted to integers via ``int()``.
|
| 312 |
+
subset_by_value : iterable, optional
|
| 313 |
+
If provided, this two-element iterable defines the half-open interval
|
| 314 |
+
``(a, b]`` that, if any, only the eigenvalues between these values
|
| 315 |
+
are returned. Only available with "evr", "evx", and "gvx" drivers. Use
|
| 316 |
+
``np.inf`` for the unconstrained ends.
|
| 317 |
+
driver : str, optional
|
| 318 |
+
Defines which LAPACK driver should be used. Valid options are "ev",
|
| 319 |
+
"evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for
|
| 320 |
+
generalized (where b is not None) problems. See the Notes section.
|
| 321 |
+
The default for standard problems is "evr". For generalized problems,
|
| 322 |
+
"gvd" is used for full set, and "gvx" for subset requested cases.
|
| 323 |
+
type : int, optional
|
| 324 |
+
For the generalized problems, this keyword specifies the problem type
|
| 325 |
+
to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible
|
| 326 |
+
inputs)::
|
| 327 |
+
|
| 328 |
+
1 => a @ v = w @ b @ v
|
| 329 |
+
2 => a @ b @ v = w @ v
|
| 330 |
+
3 => b @ a @ v = w @ v
|
| 331 |
+
|
| 332 |
+
This keyword is ignored for standard problems.
|
| 333 |
+
overwrite_a : bool, optional
|
| 334 |
+
Whether to overwrite data in ``a`` (may improve performance). Default
|
| 335 |
+
is False.
|
| 336 |
+
overwrite_b : bool, optional
|
| 337 |
+
Whether to overwrite data in ``b`` (may improve performance). Default
|
| 338 |
+
is False.
|
| 339 |
+
check_finite : bool, optional
|
| 340 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 341 |
+
Disabling may give a performance gain, but may result in problems
|
| 342 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 343 |
+
turbo : bool, optional, deprecated
|
| 344 |
+
.. deprecated:: 1.5.0
|
| 345 |
+
`eigh` keyword argument `turbo` is deprecated in favour of
|
| 346 |
+
``driver=gvd`` keyword instead and will be removed in SciPy
|
| 347 |
+
1.14.0.
|
| 348 |
+
eigvals : tuple (lo, hi), optional, deprecated
|
| 349 |
+
.. deprecated:: 1.5.0
|
| 350 |
+
`eigh` keyword argument `eigvals` is deprecated in favour of
|
| 351 |
+
`subset_by_index` keyword instead and will be removed in SciPy
|
| 352 |
+
1.14.0.
|
| 353 |
+
|
| 354 |
+
Returns
|
| 355 |
+
-------
|
| 356 |
+
w : (N,) ndarray
|
| 357 |
+
The N (N<=M) selected eigenvalues, in ascending order, each
|
| 358 |
+
repeated according to its multiplicity.
|
| 359 |
+
v : (M, N) ndarray
|
| 360 |
+
The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is
|
| 361 |
+
the column ``v[:,i]``. Only returned if ``eigvals_only=False``.
|
| 362 |
+
|
| 363 |
+
Raises
|
| 364 |
+
------
|
| 365 |
+
LinAlgError
|
| 366 |
+
If eigenvalue computation does not converge, an error occurred, or
|
| 367 |
+
b matrix is not definite positive. Note that if input matrices are
|
| 368 |
+
not symmetric or Hermitian, no error will be reported but results will
|
| 369 |
+
be wrong.
|
| 370 |
+
|
| 371 |
+
See Also
|
| 372 |
+
--------
|
| 373 |
+
eigvalsh : eigenvalues of symmetric or Hermitian arrays
|
| 374 |
+
eig : eigenvalues and right eigenvectors for non-symmetric arrays
|
| 375 |
+
eigh_tridiagonal : eigenvalues and right eiegenvectors for
|
| 376 |
+
symmetric/Hermitian tridiagonal matrices
|
| 377 |
+
|
| 378 |
+
Notes
|
| 379 |
+
-----
|
| 380 |
+
This function does not check the input array for being Hermitian/symmetric
|
| 381 |
+
in order to allow for representing arrays with only their upper/lower
|
| 382 |
+
triangular parts. Also, note that even though not taken into account,
|
| 383 |
+
finiteness check applies to the whole array and unaffected by "lower"
|
| 384 |
+
keyword.
|
| 385 |
+
|
| 386 |
+
This function uses LAPACK drivers for computations in all possible keyword
|
| 387 |
+
combinations, prefixed with ``sy`` if arrays are real and ``he`` if
|
| 388 |
+
complex, e.g., a float array with "evr" driver is solved via
|
| 389 |
+
"syevr", complex arrays with "gvx" driver problem is solved via "hegvx"
|
| 390 |
+
etc.
|
| 391 |
+
|
| 392 |
+
As a brief summary, the slowest and the most robust driver is the
|
| 393 |
+
classical ``<sy/he>ev`` which uses symmetric QR. ``<sy/he>evr`` is seen as
|
| 394 |
+
the optimal choice for the most general cases. However, there are certain
|
| 395 |
+
occasions that ``<sy/he>evd`` computes faster at the expense of more
|
| 396 |
+
memory usage. ``<sy/he>evx``, while still being faster than ``<sy/he>ev``,
|
| 397 |
+
often performs worse than the rest except when very few eigenvalues are
|
| 398 |
+
requested for large arrays though there is still no performance guarantee.
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
For the generalized problem, normalization with respect to the given
|
| 402 |
+
type argument::
|
| 403 |
+
|
| 404 |
+
type 1 and 3 : v.conj().T @ a @ v = w
|
| 405 |
+
type 2 : inv(v).conj().T @ a @ inv(v) = w
|
| 406 |
+
|
| 407 |
+
type 1 or 2 : v.conj().T @ b @ v = I
|
| 408 |
+
type 3 : v.conj().T @ inv(b) @ v = I
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
Examples
|
| 412 |
+
--------
|
| 413 |
+
>>> import numpy as np
|
| 414 |
+
>>> from scipy.linalg import eigh
|
| 415 |
+
>>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]])
|
| 416 |
+
>>> w, v = eigh(A)
|
| 417 |
+
>>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
|
| 418 |
+
True
|
| 419 |
+
|
| 420 |
+
Request only the eigenvalues
|
| 421 |
+
|
| 422 |
+
>>> w = eigh(A, eigvals_only=True)
|
| 423 |
+
|
| 424 |
+
Request eigenvalues that are less than 10.
|
| 425 |
+
|
| 426 |
+
>>> A = np.array([[34, -4, -10, -7, 2],
|
| 427 |
+
... [-4, 7, 2, 12, 0],
|
| 428 |
+
... [-10, 2, 44, 2, -19],
|
| 429 |
+
... [-7, 12, 2, 79, -34],
|
| 430 |
+
... [2, 0, -19, -34, 29]])
|
| 431 |
+
>>> eigh(A, eigvals_only=True, subset_by_value=[-np.inf, 10])
|
| 432 |
+
array([6.69199443e-07, 9.11938152e+00])
|
| 433 |
+
|
| 434 |
+
Request the second smallest eigenvalue and its eigenvector
|
| 435 |
+
|
| 436 |
+
>>> w, v = eigh(A, subset_by_index=[1, 1])
|
| 437 |
+
>>> w
|
| 438 |
+
array([9.11938152])
|
| 439 |
+
>>> v.shape # only a single column is returned
|
| 440 |
+
(5, 1)
|
| 441 |
+
|
| 442 |
+
"""
|
| 443 |
+
if turbo is not _NoValue:
|
| 444 |
+
warnings.warn("Keyword argument 'turbo' is deprecated in favour of '"
|
| 445 |
+
"driver=gvd' keyword instead and will be removed in "
|
| 446 |
+
"SciPy 1.14.0.",
|
| 447 |
+
DeprecationWarning, stacklevel=2)
|
| 448 |
+
if eigvals is not _NoValue:
|
| 449 |
+
warnings.warn("Keyword argument 'eigvals' is deprecated in favour of "
|
| 450 |
+
"'subset_by_index' keyword instead and will be removed "
|
| 451 |
+
"in SciPy 1.14.0.",
|
| 452 |
+
DeprecationWarning, stacklevel=2)
|
| 453 |
+
|
| 454 |
+
# set lower
|
| 455 |
+
uplo = 'L' if lower else 'U'
|
| 456 |
+
# Set job for Fortran routines
|
| 457 |
+
_job = 'N' if eigvals_only else 'V'
|
| 458 |
+
|
| 459 |
+
drv_str = [None, "ev", "evd", "evr", "evx", "gv", "gvd", "gvx"]
|
| 460 |
+
if driver not in drv_str:
|
| 461 |
+
raise ValueError('"{}" is unknown. Possible values are "None", "{}".'
|
| 462 |
+
''.format(driver, '", "'.join(drv_str[1:])))
|
| 463 |
+
|
| 464 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 465 |
+
if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
|
| 466 |
+
raise ValueError('expected square "a" matrix')
|
| 467 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 468 |
+
cplx = True if iscomplexobj(a1) else False
|
| 469 |
+
n = a1.shape[0]
|
| 470 |
+
drv_args = {'overwrite_a': overwrite_a}
|
| 471 |
+
|
| 472 |
+
if b is not None:
|
| 473 |
+
b1 = _asarray_validated(b, check_finite=check_finite)
|
| 474 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 475 |
+
if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]:
|
| 476 |
+
raise ValueError('expected square "b" matrix')
|
| 477 |
+
|
| 478 |
+
if b1.shape != a1.shape:
|
| 479 |
+
raise ValueError(f"wrong b dimensions {b1.shape}, should be {a1.shape}")
|
| 480 |
+
|
| 481 |
+
if type not in [1, 2, 3]:
|
| 482 |
+
raise ValueError('"type" keyword only accepts 1, 2, and 3.')
|
| 483 |
+
|
| 484 |
+
cplx = True if iscomplexobj(b1) else (cplx or False)
|
| 485 |
+
drv_args.update({'overwrite_b': overwrite_b, 'itype': type})
|
| 486 |
+
|
| 487 |
+
# backwards-compatibility handling
|
| 488 |
+
subset_by_index = subset_by_index if (eigvals in (None, _NoValue)) else eigvals
|
| 489 |
+
|
| 490 |
+
subset = (subset_by_index is not None) or (subset_by_value is not None)
|
| 491 |
+
|
| 492 |
+
# Both subsets can't be given
|
| 493 |
+
if subset_by_index and subset_by_value:
|
| 494 |
+
raise ValueError('Either index or value subset can be requested.')
|
| 495 |
+
|
| 496 |
+
# Take turbo into account if all conditions are met otherwise ignore
|
| 497 |
+
if turbo not in (None, _NoValue) and b is not None:
|
| 498 |
+
driver = 'gvx' if subset else 'gvd'
|
| 499 |
+
|
| 500 |
+
# Check indices if given
|
| 501 |
+
if subset_by_index:
|
| 502 |
+
lo, hi = (int(x) for x in subset_by_index)
|
| 503 |
+
if not (0 <= lo <= hi < n):
|
| 504 |
+
raise ValueError('Requested eigenvalue indices are not valid. '
|
| 505 |
+
f'Valid range is [0, {n-1}] and start <= end, but '
|
| 506 |
+
f'start={lo}, end={hi} is given')
|
| 507 |
+
# fortran is 1-indexed
|
| 508 |
+
drv_args.update({'range': 'I', 'il': lo + 1, 'iu': hi + 1})
|
| 509 |
+
|
| 510 |
+
if subset_by_value:
|
| 511 |
+
lo, hi = subset_by_value
|
| 512 |
+
if not (-inf <= lo < hi <= inf):
|
| 513 |
+
raise ValueError('Requested eigenvalue bounds are not valid. '
|
| 514 |
+
'Valid range is (-inf, inf) and low < high, but '
|
| 515 |
+
f'low={lo}, high={hi} is given')
|
| 516 |
+
|
| 517 |
+
drv_args.update({'range': 'V', 'vl': lo, 'vu': hi})
|
| 518 |
+
|
| 519 |
+
# fix prefix for lapack routines
|
| 520 |
+
pfx = 'he' if cplx else 'sy'
|
| 521 |
+
|
| 522 |
+
# decide on the driver if not given
|
| 523 |
+
# first early exit on incompatible choice
|
| 524 |
+
if driver:
|
| 525 |
+
if b is None and (driver in ["gv", "gvd", "gvx"]):
|
| 526 |
+
raise ValueError(f'{driver} requires input b array to be supplied '
|
| 527 |
+
'for generalized eigenvalue problems.')
|
| 528 |
+
if (b is not None) and (driver in ['ev', 'evd', 'evr', 'evx']):
|
| 529 |
+
raise ValueError(f'"{driver}" does not accept input b array '
|
| 530 |
+
'for standard eigenvalue problems.')
|
| 531 |
+
if subset and (driver in ["ev", "evd", "gv", "gvd"]):
|
| 532 |
+
raise ValueError(f'"{driver}" cannot compute subsets of eigenvalues')
|
| 533 |
+
|
| 534 |
+
# Default driver is evr and gvd
|
| 535 |
+
else:
|
| 536 |
+
driver = "evr" if b is None else ("gvx" if subset else "gvd")
|
| 537 |
+
|
| 538 |
+
lwork_spec = {
|
| 539 |
+
'syevd': ['lwork', 'liwork'],
|
| 540 |
+
'syevr': ['lwork', 'liwork'],
|
| 541 |
+
'heevd': ['lwork', 'liwork', 'lrwork'],
|
| 542 |
+
'heevr': ['lwork', 'lrwork', 'liwork'],
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
if b is None: # Standard problem
|
| 546 |
+
drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'),
|
| 547 |
+
[a1])
|
| 548 |
+
clw_args = {'n': n, 'lower': lower}
|
| 549 |
+
if driver == 'evd':
|
| 550 |
+
clw_args.update({'compute_v': 0 if _job == "N" else 1})
|
| 551 |
+
|
| 552 |
+
lw = _compute_lwork(drvlw, **clw_args)
|
| 553 |
+
# Multiple lwork vars
|
| 554 |
+
if isinstance(lw, tuple):
|
| 555 |
+
lwork_args = dict(zip(lwork_spec[pfx+driver], lw))
|
| 556 |
+
else:
|
| 557 |
+
lwork_args = {'lwork': lw}
|
| 558 |
+
|
| 559 |
+
drv_args.update({'lower': lower, 'compute_v': 0 if _job == "N" else 1})
|
| 560 |
+
w, v, *other_args, info = drv(a=a1, **drv_args, **lwork_args)
|
| 561 |
+
|
| 562 |
+
else: # Generalized problem
|
| 563 |
+
# 'gvd' doesn't have lwork query
|
| 564 |
+
if driver == "gvd":
|
| 565 |
+
drv = get_lapack_funcs(pfx + "gvd", [a1, b1])
|
| 566 |
+
lwork_args = {}
|
| 567 |
+
else:
|
| 568 |
+
drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'),
|
| 569 |
+
[a1, b1])
|
| 570 |
+
# generalized drivers use uplo instead of lower
|
| 571 |
+
lw = _compute_lwork(drvlw, n, uplo=uplo)
|
| 572 |
+
lwork_args = {'lwork': lw}
|
| 573 |
+
|
| 574 |
+
drv_args.update({'uplo': uplo, 'jobz': _job})
|
| 575 |
+
|
| 576 |
+
w, v, *other_args, info = drv(a=a1, b=b1, **drv_args, **lwork_args)
|
| 577 |
+
|
| 578 |
+
# m is always the first extra argument
|
| 579 |
+
w = w[:other_args[0]] if subset else w
|
| 580 |
+
v = v[:, :other_args[0]] if (subset and not eigvals_only) else v
|
| 581 |
+
|
| 582 |
+
# Check if we had a successful exit
|
| 583 |
+
if info == 0:
|
| 584 |
+
if eigvals_only:
|
| 585 |
+
return w
|
| 586 |
+
else:
|
| 587 |
+
return w, v
|
| 588 |
+
else:
|
| 589 |
+
if info < -1:
|
| 590 |
+
raise LinAlgError('Illegal value in argument {} of internal {}'
|
| 591 |
+
''.format(-info, drv.typecode + pfx + driver))
|
| 592 |
+
elif info > n:
|
| 593 |
+
raise LinAlgError(f'The leading minor of order {info-n} of B is not '
|
| 594 |
+
'positive definite. The factorization of B '
|
| 595 |
+
'could not be completed and no eigenvalues '
|
| 596 |
+
'or eigenvectors were computed.')
|
| 597 |
+
else:
|
| 598 |
+
drv_err = {'ev': 'The algorithm failed to converge; {} '
|
| 599 |
+
'off-diagonal elements of an intermediate '
|
| 600 |
+
'tridiagonal form did not converge to zero.',
|
| 601 |
+
'evx': '{} eigenvectors failed to converge.',
|
| 602 |
+
'evd': 'The algorithm failed to compute an eigenvalue '
|
| 603 |
+
'while working on the submatrix lying in rows '
|
| 604 |
+
'and columns {0}/{1} through mod({0},{1}).',
|
| 605 |
+
'evr': 'Internal Error.'
|
| 606 |
+
}
|
| 607 |
+
if driver in ['ev', 'gv']:
|
| 608 |
+
msg = drv_err['ev'].format(info)
|
| 609 |
+
elif driver in ['evx', 'gvx']:
|
| 610 |
+
msg = drv_err['evx'].format(info)
|
| 611 |
+
elif driver in ['evd', 'gvd']:
|
| 612 |
+
if eigvals_only:
|
| 613 |
+
msg = drv_err['ev'].format(info)
|
| 614 |
+
else:
|
| 615 |
+
msg = drv_err['evd'].format(info, n+1)
|
| 616 |
+
else:
|
| 617 |
+
msg = drv_err['evr']
|
| 618 |
+
|
| 619 |
+
raise LinAlgError(msg)
|
| 620 |
+
|
| 621 |
+
|
| 622 |
+
_conv_dict = {0: 0, 1: 1, 2: 2,
|
| 623 |
+
'all': 0, 'value': 1, 'index': 2,
|
| 624 |
+
'a': 0, 'v': 1, 'i': 2}
|
| 625 |
+
|
| 626 |
+
|
| 627 |
+
def _check_select(select, select_range, max_ev, max_len):
|
| 628 |
+
"""Check that select is valid, convert to Fortran style."""
|
| 629 |
+
if isinstance(select, str):
|
| 630 |
+
select = select.lower()
|
| 631 |
+
try:
|
| 632 |
+
select = _conv_dict[select]
|
| 633 |
+
except KeyError as e:
|
| 634 |
+
raise ValueError('invalid argument for select') from e
|
| 635 |
+
vl, vu = 0., 1.
|
| 636 |
+
il = iu = 1
|
| 637 |
+
if select != 0: # (non-all)
|
| 638 |
+
sr = asarray(select_range)
|
| 639 |
+
if sr.ndim != 1 or sr.size != 2 or sr[1] < sr[0]:
|
| 640 |
+
raise ValueError('select_range must be a 2-element array-like '
|
| 641 |
+
'in nondecreasing order')
|
| 642 |
+
if select == 1: # (value)
|
| 643 |
+
vl, vu = sr
|
| 644 |
+
if max_ev == 0:
|
| 645 |
+
max_ev = max_len
|
| 646 |
+
else: # 2 (index)
|
| 647 |
+
if sr.dtype.char.lower() not in 'hilqp':
|
| 648 |
+
raise ValueError(
|
| 649 |
+
f'when using select="i", select_range must '
|
| 650 |
+
f'contain integers, got dtype {sr.dtype} ({sr.dtype.char})'
|
| 651 |
+
)
|
| 652 |
+
# translate Python (0 ... N-1) into Fortran (1 ... N) with + 1
|
| 653 |
+
il, iu = sr + 1
|
| 654 |
+
if min(il, iu) < 1 or max(il, iu) > max_len:
|
| 655 |
+
raise ValueError('select_range out of bounds')
|
| 656 |
+
max_ev = iu - il + 1
|
| 657 |
+
return select, vl, vu, il, iu, max_ev
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
def eig_banded(a_band, lower=False, eigvals_only=False, overwrite_a_band=False,
|
| 661 |
+
select='a', select_range=None, max_ev=0, check_finite=True):
|
| 662 |
+
"""
|
| 663 |
+
Solve real symmetric or complex Hermitian band matrix eigenvalue problem.
|
| 664 |
+
|
| 665 |
+
Find eigenvalues w and optionally right eigenvectors v of a::
|
| 666 |
+
|
| 667 |
+
a v[:,i] = w[i] v[:,i]
|
| 668 |
+
v.H v = identity
|
| 669 |
+
|
| 670 |
+
The matrix a is stored in a_band either in lower diagonal or upper
|
| 671 |
+
diagonal ordered form:
|
| 672 |
+
|
| 673 |
+
a_band[u + i - j, j] == a[i,j] (if upper form; i <= j)
|
| 674 |
+
a_band[ i - j, j] == a[i,j] (if lower form; i >= j)
|
| 675 |
+
|
| 676 |
+
where u is the number of bands above the diagonal.
|
| 677 |
+
|
| 678 |
+
Example of a_band (shape of a is (6,6), u=2)::
|
| 679 |
+
|
| 680 |
+
upper form:
|
| 681 |
+
* * a02 a13 a24 a35
|
| 682 |
+
* a01 a12 a23 a34 a45
|
| 683 |
+
a00 a11 a22 a33 a44 a55
|
| 684 |
+
|
| 685 |
+
lower form:
|
| 686 |
+
a00 a11 a22 a33 a44 a55
|
| 687 |
+
a10 a21 a32 a43 a54 *
|
| 688 |
+
a20 a31 a42 a53 * *
|
| 689 |
+
|
| 690 |
+
Cells marked with * are not used.
|
| 691 |
+
|
| 692 |
+
Parameters
|
| 693 |
+
----------
|
| 694 |
+
a_band : (u+1, M) array_like
|
| 695 |
+
The bands of the M by M matrix a.
|
| 696 |
+
lower : bool, optional
|
| 697 |
+
Is the matrix in the lower form. (Default is upper form)
|
| 698 |
+
eigvals_only : bool, optional
|
| 699 |
+
Compute only the eigenvalues and no eigenvectors.
|
| 700 |
+
(Default: calculate also eigenvectors)
|
| 701 |
+
overwrite_a_band : bool, optional
|
| 702 |
+
Discard data in a_band (may enhance performance)
|
| 703 |
+
select : {'a', 'v', 'i'}, optional
|
| 704 |
+
Which eigenvalues to calculate
|
| 705 |
+
|
| 706 |
+
====== ========================================
|
| 707 |
+
select calculated
|
| 708 |
+
====== ========================================
|
| 709 |
+
'a' All eigenvalues
|
| 710 |
+
'v' Eigenvalues in the interval (min, max]
|
| 711 |
+
'i' Eigenvalues with indices min <= i <= max
|
| 712 |
+
====== ========================================
|
| 713 |
+
select_range : (min, max), optional
|
| 714 |
+
Range of selected eigenvalues
|
| 715 |
+
max_ev : int, optional
|
| 716 |
+
For select=='v', maximum number of eigenvalues expected.
|
| 717 |
+
For other values of select, has no meaning.
|
| 718 |
+
|
| 719 |
+
In doubt, leave this parameter untouched.
|
| 720 |
+
|
| 721 |
+
check_finite : bool, optional
|
| 722 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 723 |
+
Disabling may give a performance gain, but may result in problems
|
| 724 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 725 |
+
|
| 726 |
+
Returns
|
| 727 |
+
-------
|
| 728 |
+
w : (M,) ndarray
|
| 729 |
+
The eigenvalues, in ascending order, each repeated according to its
|
| 730 |
+
multiplicity.
|
| 731 |
+
v : (M, M) float or complex ndarray
|
| 732 |
+
The normalized eigenvector corresponding to the eigenvalue w[i] is
|
| 733 |
+
the column v[:,i]. Only returned if ``eigvals_only=False``.
|
| 734 |
+
|
| 735 |
+
Raises
|
| 736 |
+
------
|
| 737 |
+
LinAlgError
|
| 738 |
+
If eigenvalue computation does not converge.
|
| 739 |
+
|
| 740 |
+
See Also
|
| 741 |
+
--------
|
| 742 |
+
eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
|
| 743 |
+
eig : eigenvalues and right eigenvectors of general arrays.
|
| 744 |
+
eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
|
| 745 |
+
eigh_tridiagonal : eigenvalues and right eigenvectors for
|
| 746 |
+
symmetric/Hermitian tridiagonal matrices
|
| 747 |
+
|
| 748 |
+
Examples
|
| 749 |
+
--------
|
| 750 |
+
>>> import numpy as np
|
| 751 |
+
>>> from scipy.linalg import eig_banded
|
| 752 |
+
>>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]])
|
| 753 |
+
>>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]])
|
| 754 |
+
>>> w, v = eig_banded(Ab, lower=True)
|
| 755 |
+
>>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
|
| 756 |
+
True
|
| 757 |
+
>>> w = eig_banded(Ab, lower=True, eigvals_only=True)
|
| 758 |
+
>>> w
|
| 759 |
+
array([-4.26200532, -2.22987175, 3.95222349, 12.53965359])
|
| 760 |
+
|
| 761 |
+
Request only the eigenvalues between ``[-3, 4]``
|
| 762 |
+
|
| 763 |
+
>>> w, v = eig_banded(Ab, lower=True, select='v', select_range=[-3, 4])
|
| 764 |
+
>>> w
|
| 765 |
+
array([-2.22987175, 3.95222349])
|
| 766 |
+
|
| 767 |
+
"""
|
| 768 |
+
if eigvals_only or overwrite_a_band:
|
| 769 |
+
a1 = _asarray_validated(a_band, check_finite=check_finite)
|
| 770 |
+
overwrite_a_band = overwrite_a_band or (_datacopied(a1, a_band))
|
| 771 |
+
else:
|
| 772 |
+
a1 = array(a_band)
|
| 773 |
+
if issubclass(a1.dtype.type, inexact) and not isfinite(a1).all():
|
| 774 |
+
raise ValueError("array must not contain infs or NaNs")
|
| 775 |
+
overwrite_a_band = 1
|
| 776 |
+
|
| 777 |
+
if len(a1.shape) != 2:
|
| 778 |
+
raise ValueError('expected a 2-D array')
|
| 779 |
+
select, vl, vu, il, iu, max_ev = _check_select(
|
| 780 |
+
select, select_range, max_ev, a1.shape[1])
|
| 781 |
+
del select_range
|
| 782 |
+
if select == 0:
|
| 783 |
+
if a1.dtype.char in 'GFD':
|
| 784 |
+
# FIXME: implement this somewhen, for now go with builtin values
|
| 785 |
+
# FIXME: calc optimal lwork by calling ?hbevd(lwork=-1)
|
| 786 |
+
# or by using calc_lwork.f ???
|
| 787 |
+
# lwork = calc_lwork.hbevd(bevd.typecode, a1.shape[0], lower)
|
| 788 |
+
internal_name = 'hbevd'
|
| 789 |
+
else: # a1.dtype.char in 'fd':
|
| 790 |
+
# FIXME: implement this somewhen, for now go with builtin values
|
| 791 |
+
# see above
|
| 792 |
+
# lwork = calc_lwork.sbevd(bevd.typecode, a1.shape[0], lower)
|
| 793 |
+
internal_name = 'sbevd'
|
| 794 |
+
bevd, = get_lapack_funcs((internal_name,), (a1,))
|
| 795 |
+
w, v, info = bevd(a1, compute_v=not eigvals_only,
|
| 796 |
+
lower=lower, overwrite_ab=overwrite_a_band)
|
| 797 |
+
else: # select in [1, 2]
|
| 798 |
+
if eigvals_only:
|
| 799 |
+
max_ev = 1
|
| 800 |
+
# calculate optimal abstol for dsbevx (see manpage)
|
| 801 |
+
if a1.dtype.char in 'fF': # single precision
|
| 802 |
+
lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='f'),))
|
| 803 |
+
else:
|
| 804 |
+
lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='d'),))
|
| 805 |
+
abstol = 2 * lamch('s')
|
| 806 |
+
if a1.dtype.char in 'GFD':
|
| 807 |
+
internal_name = 'hbevx'
|
| 808 |
+
else: # a1.dtype.char in 'gfd'
|
| 809 |
+
internal_name = 'sbevx'
|
| 810 |
+
bevx, = get_lapack_funcs((internal_name,), (a1,))
|
| 811 |
+
w, v, m, ifail, info = bevx(
|
| 812 |
+
a1, vl, vu, il, iu, compute_v=not eigvals_only, mmax=max_ev,
|
| 813 |
+
range=select, lower=lower, overwrite_ab=overwrite_a_band,
|
| 814 |
+
abstol=abstol)
|
| 815 |
+
# crop off w and v
|
| 816 |
+
w = w[:m]
|
| 817 |
+
if not eigvals_only:
|
| 818 |
+
v = v[:, :m]
|
| 819 |
+
_check_info(info, internal_name)
|
| 820 |
+
|
| 821 |
+
if eigvals_only:
|
| 822 |
+
return w
|
| 823 |
+
return w, v
|
| 824 |
+
|
| 825 |
+
|
| 826 |
+
def eigvals(a, b=None, overwrite_a=False, check_finite=True,
|
| 827 |
+
homogeneous_eigvals=False):
|
| 828 |
+
"""
|
| 829 |
+
Compute eigenvalues from an ordinary or generalized eigenvalue problem.
|
| 830 |
+
|
| 831 |
+
Find eigenvalues of a general matrix::
|
| 832 |
+
|
| 833 |
+
a vr[:,i] = w[i] b vr[:,i]
|
| 834 |
+
|
| 835 |
+
Parameters
|
| 836 |
+
----------
|
| 837 |
+
a : (M, M) array_like
|
| 838 |
+
A complex or real matrix whose eigenvalues and eigenvectors
|
| 839 |
+
will be computed.
|
| 840 |
+
b : (M, M) array_like, optional
|
| 841 |
+
Right-hand side matrix in a generalized eigenvalue problem.
|
| 842 |
+
If omitted, identity matrix is assumed.
|
| 843 |
+
overwrite_a : bool, optional
|
| 844 |
+
Whether to overwrite data in a (may improve performance)
|
| 845 |
+
check_finite : bool, optional
|
| 846 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 847 |
+
Disabling may give a performance gain, but may result in problems
|
| 848 |
+
(crashes, non-termination) if the inputs do contain infinities
|
| 849 |
+
or NaNs.
|
| 850 |
+
homogeneous_eigvals : bool, optional
|
| 851 |
+
If True, return the eigenvalues in homogeneous coordinates.
|
| 852 |
+
In this case ``w`` is a (2, M) array so that::
|
| 853 |
+
|
| 854 |
+
w[1,i] a vr[:,i] = w[0,i] b vr[:,i]
|
| 855 |
+
|
| 856 |
+
Default is False.
|
| 857 |
+
|
| 858 |
+
Returns
|
| 859 |
+
-------
|
| 860 |
+
w : (M,) or (2, M) double or complex ndarray
|
| 861 |
+
The eigenvalues, each repeated according to its multiplicity
|
| 862 |
+
but not in any specific order. The shape is (M,) unless
|
| 863 |
+
``homogeneous_eigvals=True``.
|
| 864 |
+
|
| 865 |
+
Raises
|
| 866 |
+
------
|
| 867 |
+
LinAlgError
|
| 868 |
+
If eigenvalue computation does not converge
|
| 869 |
+
|
| 870 |
+
See Also
|
| 871 |
+
--------
|
| 872 |
+
eig : eigenvalues and right eigenvectors of general arrays.
|
| 873 |
+
eigvalsh : eigenvalues of symmetric or Hermitian arrays
|
| 874 |
+
eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
|
| 875 |
+
eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
|
| 876 |
+
matrices
|
| 877 |
+
|
| 878 |
+
Examples
|
| 879 |
+
--------
|
| 880 |
+
>>> import numpy as np
|
| 881 |
+
>>> from scipy import linalg
|
| 882 |
+
>>> a = np.array([[0., -1.], [1., 0.]])
|
| 883 |
+
>>> linalg.eigvals(a)
|
| 884 |
+
array([0.+1.j, 0.-1.j])
|
| 885 |
+
|
| 886 |
+
>>> b = np.array([[0., 1.], [1., 1.]])
|
| 887 |
+
>>> linalg.eigvals(a, b)
|
| 888 |
+
array([ 1.+0.j, -1.+0.j])
|
| 889 |
+
|
| 890 |
+
>>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]])
|
| 891 |
+
>>> linalg.eigvals(a, homogeneous_eigvals=True)
|
| 892 |
+
array([[3.+0.j, 8.+0.j, 7.+0.j],
|
| 893 |
+
[1.+0.j, 1.+0.j, 1.+0.j]])
|
| 894 |
+
|
| 895 |
+
"""
|
| 896 |
+
return eig(a, b=b, left=0, right=0, overwrite_a=overwrite_a,
|
| 897 |
+
check_finite=check_finite,
|
| 898 |
+
homogeneous_eigvals=homogeneous_eigvals)
|
| 899 |
+
|
| 900 |
+
|
| 901 |
+
@_deprecate_positional_args(version="1.14.0")
|
| 902 |
+
def eigvalsh(a, b=None, *, lower=True, overwrite_a=False,
|
| 903 |
+
overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1,
|
| 904 |
+
check_finite=True, subset_by_index=None, subset_by_value=None,
|
| 905 |
+
driver=None):
|
| 906 |
+
"""
|
| 907 |
+
Solves a standard or generalized eigenvalue problem for a complex
|
| 908 |
+
Hermitian or real symmetric matrix.
|
| 909 |
+
|
| 910 |
+
Find eigenvalues array ``w`` of array ``a``, where ``b`` is positive
|
| 911 |
+
definite such that for every eigenvalue λ (i-th entry of w) and its
|
| 912 |
+
eigenvector vi (i-th column of v) satisfies::
|
| 913 |
+
|
| 914 |
+
a @ vi = λ * b @ vi
|
| 915 |
+
vi.conj().T @ a @ vi = λ
|
| 916 |
+
vi.conj().T @ b @ vi = 1
|
| 917 |
+
|
| 918 |
+
In the standard problem, b is assumed to be the identity matrix.
|
| 919 |
+
|
| 920 |
+
Parameters
|
| 921 |
+
----------
|
| 922 |
+
a : (M, M) array_like
|
| 923 |
+
A complex Hermitian or real symmetric matrix whose eigenvalues will
|
| 924 |
+
be computed.
|
| 925 |
+
b : (M, M) array_like, optional
|
| 926 |
+
A complex Hermitian or real symmetric definite positive matrix in.
|
| 927 |
+
If omitted, identity matrix is assumed.
|
| 928 |
+
lower : bool, optional
|
| 929 |
+
Whether the pertinent array data is taken from the lower or upper
|
| 930 |
+
triangle of ``a`` and, if applicable, ``b``. (Default: lower)
|
| 931 |
+
overwrite_a : bool, optional
|
| 932 |
+
Whether to overwrite data in ``a`` (may improve performance). Default
|
| 933 |
+
is False.
|
| 934 |
+
overwrite_b : bool, optional
|
| 935 |
+
Whether to overwrite data in ``b`` (may improve performance). Default
|
| 936 |
+
is False.
|
| 937 |
+
type : int, optional
|
| 938 |
+
For the generalized problems, this keyword specifies the problem type
|
| 939 |
+
to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible
|
| 940 |
+
inputs)::
|
| 941 |
+
|
| 942 |
+
1 => a @ v = w @ b @ v
|
| 943 |
+
2 => a @ b @ v = w @ v
|
| 944 |
+
3 => b @ a @ v = w @ v
|
| 945 |
+
|
| 946 |
+
This keyword is ignored for standard problems.
|
| 947 |
+
check_finite : bool, optional
|
| 948 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 949 |
+
Disabling may give a performance gain, but may result in problems
|
| 950 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 951 |
+
subset_by_index : iterable, optional
|
| 952 |
+
If provided, this two-element iterable defines the start and the end
|
| 953 |
+
indices of the desired eigenvalues (ascending order and 0-indexed).
|
| 954 |
+
To return only the second smallest to fifth smallest eigenvalues,
|
| 955 |
+
``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only
|
| 956 |
+
available with "evr", "evx", and "gvx" drivers. The entries are
|
| 957 |
+
directly converted to integers via ``int()``.
|
| 958 |
+
subset_by_value : iterable, optional
|
| 959 |
+
If provided, this two-element iterable defines the half-open interval
|
| 960 |
+
``(a, b]`` that, if any, only the eigenvalues between these values
|
| 961 |
+
are returned. Only available with "evr", "evx", and "gvx" drivers. Use
|
| 962 |
+
``np.inf`` for the unconstrained ends.
|
| 963 |
+
driver : str, optional
|
| 964 |
+
Defines which LAPACK driver should be used. Valid options are "ev",
|
| 965 |
+
"evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for
|
| 966 |
+
generalized (where b is not None) problems. See the Notes section of
|
| 967 |
+
`scipy.linalg.eigh`.
|
| 968 |
+
turbo : bool, optional, deprecated
|
| 969 |
+
.. deprecated:: 1.5.0
|
| 970 |
+
'eigvalsh' keyword argument `turbo` is deprecated in favor of
|
| 971 |
+
``driver=gvd`` option and will be removed in SciPy 1.14.0.
|
| 972 |
+
|
| 973 |
+
eigvals : tuple (lo, hi), optional
|
| 974 |
+
.. deprecated:: 1.5.0
|
| 975 |
+
'eigvalsh' keyword argument `eigvals` is deprecated in favor of
|
| 976 |
+
`subset_by_index` option and will be removed in SciPy 1.14.0.
|
| 977 |
+
|
| 978 |
+
Returns
|
| 979 |
+
-------
|
| 980 |
+
w : (N,) ndarray
|
| 981 |
+
The N (N<=M) selected eigenvalues, in ascending order, each
|
| 982 |
+
repeated according to its multiplicity.
|
| 983 |
+
|
| 984 |
+
Raises
|
| 985 |
+
------
|
| 986 |
+
LinAlgError
|
| 987 |
+
If eigenvalue computation does not converge, an error occurred, or
|
| 988 |
+
b matrix is not definite positive. Note that if input matrices are
|
| 989 |
+
not symmetric or Hermitian, no error will be reported but results will
|
| 990 |
+
be wrong.
|
| 991 |
+
|
| 992 |
+
See Also
|
| 993 |
+
--------
|
| 994 |
+
eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
|
| 995 |
+
eigvals : eigenvalues of general arrays
|
| 996 |
+
eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
|
| 997 |
+
eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
|
| 998 |
+
matrices
|
| 999 |
+
|
| 1000 |
+
Notes
|
| 1001 |
+
-----
|
| 1002 |
+
This function does not check the input array for being Hermitian/symmetric
|
| 1003 |
+
in order to allow for representing arrays with only their upper/lower
|
| 1004 |
+
triangular parts.
|
| 1005 |
+
|
| 1006 |
+
This function serves as a one-liner shorthand for `scipy.linalg.eigh` with
|
| 1007 |
+
the option ``eigvals_only=True`` to get the eigenvalues and not the
|
| 1008 |
+
eigenvectors. Here it is kept as a legacy convenience. It might be
|
| 1009 |
+
beneficial to use the main function to have full control and to be a bit
|
| 1010 |
+
more pythonic.
|
| 1011 |
+
|
| 1012 |
+
Examples
|
| 1013 |
+
--------
|
| 1014 |
+
For more examples see `scipy.linalg.eigh`.
|
| 1015 |
+
|
| 1016 |
+
>>> import numpy as np
|
| 1017 |
+
>>> from scipy.linalg import eigvalsh
|
| 1018 |
+
>>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]])
|
| 1019 |
+
>>> w = eigvalsh(A)
|
| 1020 |
+
>>> w
|
| 1021 |
+
array([-3.74637491, -0.76263923, 6.08502336, 12.42399079])
|
| 1022 |
+
|
| 1023 |
+
"""
|
| 1024 |
+
return eigh(a, b=b, lower=lower, eigvals_only=True,
|
| 1025 |
+
overwrite_a=overwrite_a, overwrite_b=overwrite_b,
|
| 1026 |
+
turbo=turbo, eigvals=eigvals, type=type,
|
| 1027 |
+
check_finite=check_finite, subset_by_index=subset_by_index,
|
| 1028 |
+
subset_by_value=subset_by_value, driver=driver)
|
| 1029 |
+
|
| 1030 |
+
|
| 1031 |
+
def eigvals_banded(a_band, lower=False, overwrite_a_band=False,
|
| 1032 |
+
select='a', select_range=None, check_finite=True):
|
| 1033 |
+
"""
|
| 1034 |
+
Solve real symmetric or complex Hermitian band matrix eigenvalue problem.
|
| 1035 |
+
|
| 1036 |
+
Find eigenvalues w of a::
|
| 1037 |
+
|
| 1038 |
+
a v[:,i] = w[i] v[:,i]
|
| 1039 |
+
v.H v = identity
|
| 1040 |
+
|
| 1041 |
+
The matrix a is stored in a_band either in lower diagonal or upper
|
| 1042 |
+
diagonal ordered form:
|
| 1043 |
+
|
| 1044 |
+
a_band[u + i - j, j] == a[i,j] (if upper form; i <= j)
|
| 1045 |
+
a_band[ i - j, j] == a[i,j] (if lower form; i >= j)
|
| 1046 |
+
|
| 1047 |
+
where u is the number of bands above the diagonal.
|
| 1048 |
+
|
| 1049 |
+
Example of a_band (shape of a is (6,6), u=2)::
|
| 1050 |
+
|
| 1051 |
+
upper form:
|
| 1052 |
+
* * a02 a13 a24 a35
|
| 1053 |
+
* a01 a12 a23 a34 a45
|
| 1054 |
+
a00 a11 a22 a33 a44 a55
|
| 1055 |
+
|
| 1056 |
+
lower form:
|
| 1057 |
+
a00 a11 a22 a33 a44 a55
|
| 1058 |
+
a10 a21 a32 a43 a54 *
|
| 1059 |
+
a20 a31 a42 a53 * *
|
| 1060 |
+
|
| 1061 |
+
Cells marked with * are not used.
|
| 1062 |
+
|
| 1063 |
+
Parameters
|
| 1064 |
+
----------
|
| 1065 |
+
a_band : (u+1, M) array_like
|
| 1066 |
+
The bands of the M by M matrix a.
|
| 1067 |
+
lower : bool, optional
|
| 1068 |
+
Is the matrix in the lower form. (Default is upper form)
|
| 1069 |
+
overwrite_a_band : bool, optional
|
| 1070 |
+
Discard data in a_band (may enhance performance)
|
| 1071 |
+
select : {'a', 'v', 'i'}, optional
|
| 1072 |
+
Which eigenvalues to calculate
|
| 1073 |
+
|
| 1074 |
+
====== ========================================
|
| 1075 |
+
select calculated
|
| 1076 |
+
====== ========================================
|
| 1077 |
+
'a' All eigenvalues
|
| 1078 |
+
'v' Eigenvalues in the interval (min, max]
|
| 1079 |
+
'i' Eigenvalues with indices min <= i <= max
|
| 1080 |
+
====== ========================================
|
| 1081 |
+
select_range : (min, max), optional
|
| 1082 |
+
Range of selected eigenvalues
|
| 1083 |
+
check_finite : bool, optional
|
| 1084 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1085 |
+
Disabling may give a performance gain, but may result in problems
|
| 1086 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1087 |
+
|
| 1088 |
+
Returns
|
| 1089 |
+
-------
|
| 1090 |
+
w : (M,) ndarray
|
| 1091 |
+
The eigenvalues, in ascending order, each repeated according to its
|
| 1092 |
+
multiplicity.
|
| 1093 |
+
|
| 1094 |
+
Raises
|
| 1095 |
+
------
|
| 1096 |
+
LinAlgError
|
| 1097 |
+
If eigenvalue computation does not converge.
|
| 1098 |
+
|
| 1099 |
+
See Also
|
| 1100 |
+
--------
|
| 1101 |
+
eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
|
| 1102 |
+
band matrices
|
| 1103 |
+
eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
|
| 1104 |
+
matrices
|
| 1105 |
+
eigvals : eigenvalues of general arrays
|
| 1106 |
+
eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
|
| 1107 |
+
eig : eigenvalues and right eigenvectors for non-symmetric arrays
|
| 1108 |
+
|
| 1109 |
+
Examples
|
| 1110 |
+
--------
|
| 1111 |
+
>>> import numpy as np
|
| 1112 |
+
>>> from scipy.linalg import eigvals_banded
|
| 1113 |
+
>>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]])
|
| 1114 |
+
>>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]])
|
| 1115 |
+
>>> w = eigvals_banded(Ab, lower=True)
|
| 1116 |
+
>>> w
|
| 1117 |
+
array([-4.26200532, -2.22987175, 3.95222349, 12.53965359])
|
| 1118 |
+
"""
|
| 1119 |
+
return eig_banded(a_band, lower=lower, eigvals_only=1,
|
| 1120 |
+
overwrite_a_band=overwrite_a_band, select=select,
|
| 1121 |
+
select_range=select_range, check_finite=check_finite)
|
| 1122 |
+
|
| 1123 |
+
|
| 1124 |
+
def eigvalsh_tridiagonal(d, e, select='a', select_range=None,
|
| 1125 |
+
check_finite=True, tol=0., lapack_driver='auto'):
|
| 1126 |
+
"""
|
| 1127 |
+
Solve eigenvalue problem for a real symmetric tridiagonal matrix.
|
| 1128 |
+
|
| 1129 |
+
Find eigenvalues `w` of ``a``::
|
| 1130 |
+
|
| 1131 |
+
a v[:,i] = w[i] v[:,i]
|
| 1132 |
+
v.H v = identity
|
| 1133 |
+
|
| 1134 |
+
For a real symmetric matrix ``a`` with diagonal elements `d` and
|
| 1135 |
+
off-diagonal elements `e`.
|
| 1136 |
+
|
| 1137 |
+
Parameters
|
| 1138 |
+
----------
|
| 1139 |
+
d : ndarray, shape (ndim,)
|
| 1140 |
+
The diagonal elements of the array.
|
| 1141 |
+
e : ndarray, shape (ndim-1,)
|
| 1142 |
+
The off-diagonal elements of the array.
|
| 1143 |
+
select : {'a', 'v', 'i'}, optional
|
| 1144 |
+
Which eigenvalues to calculate
|
| 1145 |
+
|
| 1146 |
+
====== ========================================
|
| 1147 |
+
select calculated
|
| 1148 |
+
====== ========================================
|
| 1149 |
+
'a' All eigenvalues
|
| 1150 |
+
'v' Eigenvalues in the interval (min, max]
|
| 1151 |
+
'i' Eigenvalues with indices min <= i <= max
|
| 1152 |
+
====== ========================================
|
| 1153 |
+
select_range : (min, max), optional
|
| 1154 |
+
Range of selected eigenvalues
|
| 1155 |
+
check_finite : bool, optional
|
| 1156 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1157 |
+
Disabling may give a performance gain, but may result in problems
|
| 1158 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1159 |
+
tol : float
|
| 1160 |
+
The absolute tolerance to which each eigenvalue is required
|
| 1161 |
+
(only used when ``lapack_driver='stebz'``).
|
| 1162 |
+
An eigenvalue (or cluster) is considered to have converged if it
|
| 1163 |
+
lies in an interval of this width. If <= 0. (default),
|
| 1164 |
+
the value ``eps*|a|`` is used where eps is the machine precision,
|
| 1165 |
+
and ``|a|`` is the 1-norm of the matrix ``a``.
|
| 1166 |
+
lapack_driver : str
|
| 1167 |
+
LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf',
|
| 1168 |
+
or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'``
|
| 1169 |
+
and 'stebz' otherwise. 'sterf' and 'stev' can only be used when
|
| 1170 |
+
``select='a'``.
|
| 1171 |
+
|
| 1172 |
+
Returns
|
| 1173 |
+
-------
|
| 1174 |
+
w : (M,) ndarray
|
| 1175 |
+
The eigenvalues, in ascending order, each repeated according to its
|
| 1176 |
+
multiplicity.
|
| 1177 |
+
|
| 1178 |
+
Raises
|
| 1179 |
+
------
|
| 1180 |
+
LinAlgError
|
| 1181 |
+
If eigenvalue computation does not converge.
|
| 1182 |
+
|
| 1183 |
+
See Also
|
| 1184 |
+
--------
|
| 1185 |
+
eigh_tridiagonal : eigenvalues and right eiegenvectors for
|
| 1186 |
+
symmetric/Hermitian tridiagonal matrices
|
| 1187 |
+
|
| 1188 |
+
Examples
|
| 1189 |
+
--------
|
| 1190 |
+
>>> import numpy as np
|
| 1191 |
+
>>> from scipy.linalg import eigvalsh_tridiagonal, eigvalsh
|
| 1192 |
+
>>> d = 3*np.ones(4)
|
| 1193 |
+
>>> e = -1*np.ones(3)
|
| 1194 |
+
>>> w = eigvalsh_tridiagonal(d, e)
|
| 1195 |
+
>>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1)
|
| 1196 |
+
>>> w2 = eigvalsh(A) # Verify with other eigenvalue routines
|
| 1197 |
+
>>> np.allclose(w - w2, np.zeros(4))
|
| 1198 |
+
True
|
| 1199 |
+
"""
|
| 1200 |
+
return eigh_tridiagonal(
|
| 1201 |
+
d, e, eigvals_only=True, select=select, select_range=select_range,
|
| 1202 |
+
check_finite=check_finite, tol=tol, lapack_driver=lapack_driver)
|
| 1203 |
+
|
| 1204 |
+
|
| 1205 |
+
def eigh_tridiagonal(d, e, eigvals_only=False, select='a', select_range=None,
|
| 1206 |
+
check_finite=True, tol=0., lapack_driver='auto'):
|
| 1207 |
+
"""
|
| 1208 |
+
Solve eigenvalue problem for a real symmetric tridiagonal matrix.
|
| 1209 |
+
|
| 1210 |
+
Find eigenvalues `w` and optionally right eigenvectors `v` of ``a``::
|
| 1211 |
+
|
| 1212 |
+
a v[:,i] = w[i] v[:,i]
|
| 1213 |
+
v.H v = identity
|
| 1214 |
+
|
| 1215 |
+
For a real symmetric matrix ``a`` with diagonal elements `d` and
|
| 1216 |
+
off-diagonal elements `e`.
|
| 1217 |
+
|
| 1218 |
+
Parameters
|
| 1219 |
+
----------
|
| 1220 |
+
d : ndarray, shape (ndim,)
|
| 1221 |
+
The diagonal elements of the array.
|
| 1222 |
+
e : ndarray, shape (ndim-1,)
|
| 1223 |
+
The off-diagonal elements of the array.
|
| 1224 |
+
eigvals_only : bool, optional
|
| 1225 |
+
Compute only the eigenvalues and no eigenvectors.
|
| 1226 |
+
(Default: calculate also eigenvectors)
|
| 1227 |
+
select : {'a', 'v', 'i'}, optional
|
| 1228 |
+
Which eigenvalues to calculate
|
| 1229 |
+
|
| 1230 |
+
====== ========================================
|
| 1231 |
+
select calculated
|
| 1232 |
+
====== ========================================
|
| 1233 |
+
'a' All eigenvalues
|
| 1234 |
+
'v' Eigenvalues in the interval (min, max]
|
| 1235 |
+
'i' Eigenvalues with indices min <= i <= max
|
| 1236 |
+
====== ========================================
|
| 1237 |
+
select_range : (min, max), optional
|
| 1238 |
+
Range of selected eigenvalues
|
| 1239 |
+
check_finite : bool, optional
|
| 1240 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1241 |
+
Disabling may give a performance gain, but may result in problems
|
| 1242 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1243 |
+
tol : float
|
| 1244 |
+
The absolute tolerance to which each eigenvalue is required
|
| 1245 |
+
(only used when 'stebz' is the `lapack_driver`).
|
| 1246 |
+
An eigenvalue (or cluster) is considered to have converged if it
|
| 1247 |
+
lies in an interval of this width. If <= 0. (default),
|
| 1248 |
+
the value ``eps*|a|`` is used where eps is the machine precision,
|
| 1249 |
+
and ``|a|`` is the 1-norm of the matrix ``a``.
|
| 1250 |
+
lapack_driver : str
|
| 1251 |
+
LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf',
|
| 1252 |
+
or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'``
|
| 1253 |
+
and 'stebz' otherwise. When 'stebz' is used to find the eigenvalues and
|
| 1254 |
+
``eigvals_only=False``, then a second LAPACK call (to ``?STEIN``) is
|
| 1255 |
+
used to find the corresponding eigenvectors. 'sterf' can only be
|
| 1256 |
+
used when ``eigvals_only=True`` and ``select='a'``. 'stev' can only
|
| 1257 |
+
be used when ``select='a'``.
|
| 1258 |
+
|
| 1259 |
+
Returns
|
| 1260 |
+
-------
|
| 1261 |
+
w : (M,) ndarray
|
| 1262 |
+
The eigenvalues, in ascending order, each repeated according to its
|
| 1263 |
+
multiplicity.
|
| 1264 |
+
v : (M, M) ndarray
|
| 1265 |
+
The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is
|
| 1266 |
+
the column ``v[:,i]``. Only returned if ``eigvals_only=False``.
|
| 1267 |
+
|
| 1268 |
+
Raises
|
| 1269 |
+
------
|
| 1270 |
+
LinAlgError
|
| 1271 |
+
If eigenvalue computation does not converge.
|
| 1272 |
+
|
| 1273 |
+
See Also
|
| 1274 |
+
--------
|
| 1275 |
+
eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
|
| 1276 |
+
matrices
|
| 1277 |
+
eig : eigenvalues and right eigenvectors for non-symmetric arrays
|
| 1278 |
+
eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
|
| 1279 |
+
eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
|
| 1280 |
+
band matrices
|
| 1281 |
+
|
| 1282 |
+
Notes
|
| 1283 |
+
-----
|
| 1284 |
+
This function makes use of LAPACK ``S/DSTEMR`` routines.
|
| 1285 |
+
|
| 1286 |
+
Examples
|
| 1287 |
+
--------
|
| 1288 |
+
>>> import numpy as np
|
| 1289 |
+
>>> from scipy.linalg import eigh_tridiagonal
|
| 1290 |
+
>>> d = 3*np.ones(4)
|
| 1291 |
+
>>> e = -1*np.ones(3)
|
| 1292 |
+
>>> w, v = eigh_tridiagonal(d, e)
|
| 1293 |
+
>>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1)
|
| 1294 |
+
>>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
|
| 1295 |
+
True
|
| 1296 |
+
"""
|
| 1297 |
+
d = _asarray_validated(d, check_finite=check_finite)
|
| 1298 |
+
e = _asarray_validated(e, check_finite=check_finite)
|
| 1299 |
+
for check in (d, e):
|
| 1300 |
+
if check.ndim != 1:
|
| 1301 |
+
raise ValueError('expected a 1-D array')
|
| 1302 |
+
if check.dtype.char in 'GFD': # complex
|
| 1303 |
+
raise TypeError('Only real arrays currently supported')
|
| 1304 |
+
if d.size != e.size + 1:
|
| 1305 |
+
raise ValueError(f'd ({d.size}) must have one more element than e ({e.size})')
|
| 1306 |
+
select, vl, vu, il, iu, _ = _check_select(
|
| 1307 |
+
select, select_range, 0, d.size)
|
| 1308 |
+
if not isinstance(lapack_driver, str):
|
| 1309 |
+
raise TypeError('lapack_driver must be str')
|
| 1310 |
+
drivers = ('auto', 'stemr', 'sterf', 'stebz', 'stev')
|
| 1311 |
+
if lapack_driver not in drivers:
|
| 1312 |
+
raise ValueError(f'lapack_driver must be one of {drivers}, '
|
| 1313 |
+
f'got {lapack_driver}')
|
| 1314 |
+
if lapack_driver == 'auto':
|
| 1315 |
+
lapack_driver = 'stemr' if select == 0 else 'stebz'
|
| 1316 |
+
|
| 1317 |
+
# Quick exit for 1x1 case
|
| 1318 |
+
if len(d) == 1:
|
| 1319 |
+
if select == 1 and (not (vl < d[0] <= vu)): # request by value
|
| 1320 |
+
w = array([])
|
| 1321 |
+
v = empty([1, 0], dtype=d.dtype)
|
| 1322 |
+
else: # all and request by index
|
| 1323 |
+
w = array([d[0]], dtype=d.dtype)
|
| 1324 |
+
v = array([[1.]], dtype=d.dtype)
|
| 1325 |
+
|
| 1326 |
+
if eigvals_only:
|
| 1327 |
+
return w
|
| 1328 |
+
else:
|
| 1329 |
+
return w, v
|
| 1330 |
+
|
| 1331 |
+
func, = get_lapack_funcs((lapack_driver,), (d, e))
|
| 1332 |
+
compute_v = not eigvals_only
|
| 1333 |
+
if lapack_driver == 'sterf':
|
| 1334 |
+
if select != 0:
|
| 1335 |
+
raise ValueError('sterf can only be used when select == "a"')
|
| 1336 |
+
if not eigvals_only:
|
| 1337 |
+
raise ValueError('sterf can only be used when eigvals_only is '
|
| 1338 |
+
'True')
|
| 1339 |
+
w, info = func(d, e)
|
| 1340 |
+
m = len(w)
|
| 1341 |
+
elif lapack_driver == 'stev':
|
| 1342 |
+
if select != 0:
|
| 1343 |
+
raise ValueError('stev can only be used when select == "a"')
|
| 1344 |
+
w, v, info = func(d, e, compute_v=compute_v)
|
| 1345 |
+
m = len(w)
|
| 1346 |
+
elif lapack_driver == 'stebz':
|
| 1347 |
+
tol = float(tol)
|
| 1348 |
+
internal_name = 'stebz'
|
| 1349 |
+
stebz, = get_lapack_funcs((internal_name,), (d, e))
|
| 1350 |
+
# If getting eigenvectors, needs to be block-ordered (B) instead of
|
| 1351 |
+
# matrix-ordered (E), and we will reorder later
|
| 1352 |
+
order = 'E' if eigvals_only else 'B'
|
| 1353 |
+
m, w, iblock, isplit, info = stebz(d, e, select, vl, vu, il, iu, tol,
|
| 1354 |
+
order)
|
| 1355 |
+
else: # 'stemr'
|
| 1356 |
+
# ?STEMR annoyingly requires size N instead of N-1
|
| 1357 |
+
e_ = empty(e.size+1, e.dtype)
|
| 1358 |
+
e_[:-1] = e
|
| 1359 |
+
stemr_lwork, = get_lapack_funcs(('stemr_lwork',), (d, e))
|
| 1360 |
+
lwork, liwork, info = stemr_lwork(d, e_, select, vl, vu, il, iu,
|
| 1361 |
+
compute_v=compute_v)
|
| 1362 |
+
_check_info(info, 'stemr_lwork')
|
| 1363 |
+
m, w, v, info = func(d, e_, select, vl, vu, il, iu,
|
| 1364 |
+
compute_v=compute_v, lwork=lwork, liwork=liwork)
|
| 1365 |
+
_check_info(info, lapack_driver + ' (eigh_tridiagonal)')
|
| 1366 |
+
w = w[:m]
|
| 1367 |
+
if eigvals_only:
|
| 1368 |
+
return w
|
| 1369 |
+
else:
|
| 1370 |
+
# Do we still need to compute the eigenvalues?
|
| 1371 |
+
if lapack_driver == 'stebz':
|
| 1372 |
+
func, = get_lapack_funcs(('stein',), (d, e))
|
| 1373 |
+
v, info = func(d, e, w, iblock, isplit)
|
| 1374 |
+
_check_info(info, 'stein (eigh_tridiagonal)',
|
| 1375 |
+
positive='%d eigenvectors failed to converge')
|
| 1376 |
+
# Convert block-order to matrix-order
|
| 1377 |
+
order = argsort(w)
|
| 1378 |
+
w, v = w[order], v[:, order]
|
| 1379 |
+
else:
|
| 1380 |
+
v = v[:, :m]
|
| 1381 |
+
return w, v
|
| 1382 |
+
|
| 1383 |
+
|
| 1384 |
+
def _check_info(info, driver, positive='did not converge (LAPACK info=%d)'):
|
| 1385 |
+
"""Check info return value."""
|
| 1386 |
+
if info < 0:
|
| 1387 |
+
raise ValueError('illegal value in argument %d of internal %s'
|
| 1388 |
+
% (-info, driver))
|
| 1389 |
+
if info > 0 and positive:
|
| 1390 |
+
raise LinAlgError(("%s " + positive) % (driver, info,))
|
| 1391 |
+
|
| 1392 |
+
|
| 1393 |
+
def hessenberg(a, calc_q=False, overwrite_a=False, check_finite=True):
|
| 1394 |
+
"""
|
| 1395 |
+
Compute Hessenberg form of a matrix.
|
| 1396 |
+
|
| 1397 |
+
The Hessenberg decomposition is::
|
| 1398 |
+
|
| 1399 |
+
A = Q H Q^H
|
| 1400 |
+
|
| 1401 |
+
where `Q` is unitary/orthogonal and `H` has only zero elements below
|
| 1402 |
+
the first sub-diagonal.
|
| 1403 |
+
|
| 1404 |
+
Parameters
|
| 1405 |
+
----------
|
| 1406 |
+
a : (M, M) array_like
|
| 1407 |
+
Matrix to bring into Hessenberg form.
|
| 1408 |
+
calc_q : bool, optional
|
| 1409 |
+
Whether to compute the transformation matrix. Default is False.
|
| 1410 |
+
overwrite_a : bool, optional
|
| 1411 |
+
Whether to overwrite `a`; may improve performance.
|
| 1412 |
+
Default is False.
|
| 1413 |
+
check_finite : bool, optional
|
| 1414 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 1415 |
+
Disabling may give a performance gain, but may result in problems
|
| 1416 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 1417 |
+
|
| 1418 |
+
Returns
|
| 1419 |
+
-------
|
| 1420 |
+
H : (M, M) ndarray
|
| 1421 |
+
Hessenberg form of `a`.
|
| 1422 |
+
Q : (M, M) ndarray
|
| 1423 |
+
Unitary/orthogonal similarity transformation matrix ``A = Q H Q^H``.
|
| 1424 |
+
Only returned if ``calc_q=True``.
|
| 1425 |
+
|
| 1426 |
+
Examples
|
| 1427 |
+
--------
|
| 1428 |
+
>>> import numpy as np
|
| 1429 |
+
>>> from scipy.linalg import hessenberg
|
| 1430 |
+
>>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
|
| 1431 |
+
>>> H, Q = hessenberg(A, calc_q=True)
|
| 1432 |
+
>>> H
|
| 1433 |
+
array([[ 2. , -11.65843866, 1.42005301, 0.25349066],
|
| 1434 |
+
[ -9.94987437, 14.53535354, -5.31022304, 2.43081618],
|
| 1435 |
+
[ 0. , -1.83299243, 0.38969961, -0.51527034],
|
| 1436 |
+
[ 0. , 0. , -3.83189513, 1.07494686]])
|
| 1437 |
+
>>> np.allclose(Q @ H @ Q.conj().T - A, np.zeros((4, 4)))
|
| 1438 |
+
True
|
| 1439 |
+
"""
|
| 1440 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 1441 |
+
if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]):
|
| 1442 |
+
raise ValueError('expected square matrix')
|
| 1443 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 1444 |
+
|
| 1445 |
+
# if 2x2 or smaller: already in Hessenberg
|
| 1446 |
+
if a1.shape[0] <= 2:
|
| 1447 |
+
if calc_q:
|
| 1448 |
+
return a1, eye(a1.shape[0])
|
| 1449 |
+
return a1
|
| 1450 |
+
|
| 1451 |
+
gehrd, gebal, gehrd_lwork = get_lapack_funcs(('gehrd', 'gebal',
|
| 1452 |
+
'gehrd_lwork'), (a1,))
|
| 1453 |
+
ba, lo, hi, pivscale, info = gebal(a1, permute=0, overwrite_a=overwrite_a)
|
| 1454 |
+
_check_info(info, 'gebal (hessenberg)', positive=False)
|
| 1455 |
+
n = len(a1)
|
| 1456 |
+
|
| 1457 |
+
lwork = _compute_lwork(gehrd_lwork, ba.shape[0], lo=lo, hi=hi)
|
| 1458 |
+
|
| 1459 |
+
hq, tau, info = gehrd(ba, lo=lo, hi=hi, lwork=lwork, overwrite_a=1)
|
| 1460 |
+
_check_info(info, 'gehrd (hessenberg)', positive=False)
|
| 1461 |
+
h = numpy.triu(hq, -1)
|
| 1462 |
+
if not calc_q:
|
| 1463 |
+
return h
|
| 1464 |
+
|
| 1465 |
+
# use orghr/unghr to compute q
|
| 1466 |
+
orghr, orghr_lwork = get_lapack_funcs(('orghr', 'orghr_lwork'), (a1,))
|
| 1467 |
+
lwork = _compute_lwork(orghr_lwork, n, lo=lo, hi=hi)
|
| 1468 |
+
|
| 1469 |
+
q, info = orghr(a=hq, tau=tau, lo=lo, hi=hi, lwork=lwork, overwrite_a=1)
|
| 1470 |
+
_check_info(info, 'orghr (hessenberg)', positive=False)
|
| 1471 |
+
return h, q
|
| 1472 |
+
|
| 1473 |
+
|
| 1474 |
+
def cdf2rdf(w, v):
|
| 1475 |
+
"""
|
| 1476 |
+
Converts complex eigenvalues ``w`` and eigenvectors ``v`` to real
|
| 1477 |
+
eigenvalues in a block diagonal form ``wr`` and the associated real
|
| 1478 |
+
eigenvectors ``vr``, such that::
|
| 1479 |
+
|
| 1480 |
+
vr @ wr = X @ vr
|
| 1481 |
+
|
| 1482 |
+
continues to hold, where ``X`` is the original array for which ``w`` and
|
| 1483 |
+
``v`` are the eigenvalues and eigenvectors.
|
| 1484 |
+
|
| 1485 |
+
.. versionadded:: 1.1.0
|
| 1486 |
+
|
| 1487 |
+
Parameters
|
| 1488 |
+
----------
|
| 1489 |
+
w : (..., M) array_like
|
| 1490 |
+
Complex or real eigenvalues, an array or stack of arrays
|
| 1491 |
+
|
| 1492 |
+
Conjugate pairs must not be interleaved, else the wrong result
|
| 1493 |
+
will be produced. So ``[1+1j, 1, 1-1j]`` will give a correct result,
|
| 1494 |
+
but ``[1+1j, 2+1j, 1-1j, 2-1j]`` will not.
|
| 1495 |
+
|
| 1496 |
+
v : (..., M, M) array_like
|
| 1497 |
+
Complex or real eigenvectors, a square array or stack of square arrays.
|
| 1498 |
+
|
| 1499 |
+
Returns
|
| 1500 |
+
-------
|
| 1501 |
+
wr : (..., M, M) ndarray
|
| 1502 |
+
Real diagonal block form of eigenvalues
|
| 1503 |
+
vr : (..., M, M) ndarray
|
| 1504 |
+
Real eigenvectors associated with ``wr``
|
| 1505 |
+
|
| 1506 |
+
See Also
|
| 1507 |
+
--------
|
| 1508 |
+
eig : Eigenvalues and right eigenvectors for non-symmetric arrays
|
| 1509 |
+
rsf2csf : Convert real Schur form to complex Schur form
|
| 1510 |
+
|
| 1511 |
+
Notes
|
| 1512 |
+
-----
|
| 1513 |
+
``w``, ``v`` must be the eigenstructure for some *real* matrix ``X``.
|
| 1514 |
+
For example, obtained by ``w, v = scipy.linalg.eig(X)`` or
|
| 1515 |
+
``w, v = numpy.linalg.eig(X)`` in which case ``X`` can also represent
|
| 1516 |
+
stacked arrays.
|
| 1517 |
+
|
| 1518 |
+
.. versionadded:: 1.1.0
|
| 1519 |
+
|
| 1520 |
+
Examples
|
| 1521 |
+
--------
|
| 1522 |
+
>>> import numpy as np
|
| 1523 |
+
>>> X = np.array([[1, 2, 3], [0, 4, 5], [0, -5, 4]])
|
| 1524 |
+
>>> X
|
| 1525 |
+
array([[ 1, 2, 3],
|
| 1526 |
+
[ 0, 4, 5],
|
| 1527 |
+
[ 0, -5, 4]])
|
| 1528 |
+
|
| 1529 |
+
>>> from scipy import linalg
|
| 1530 |
+
>>> w, v = linalg.eig(X)
|
| 1531 |
+
>>> w
|
| 1532 |
+
array([ 1.+0.j, 4.+5.j, 4.-5.j])
|
| 1533 |
+
>>> v
|
| 1534 |
+
array([[ 1.00000+0.j , -0.01906-0.40016j, -0.01906+0.40016j],
|
| 1535 |
+
[ 0.00000+0.j , 0.00000-0.64788j, 0.00000+0.64788j],
|
| 1536 |
+
[ 0.00000+0.j , 0.64788+0.j , 0.64788-0.j ]])
|
| 1537 |
+
|
| 1538 |
+
>>> wr, vr = linalg.cdf2rdf(w, v)
|
| 1539 |
+
>>> wr
|
| 1540 |
+
array([[ 1., 0., 0.],
|
| 1541 |
+
[ 0., 4., 5.],
|
| 1542 |
+
[ 0., -5., 4.]])
|
| 1543 |
+
>>> vr
|
| 1544 |
+
array([[ 1. , 0.40016, -0.01906],
|
| 1545 |
+
[ 0. , 0.64788, 0. ],
|
| 1546 |
+
[ 0. , 0. , 0.64788]])
|
| 1547 |
+
|
| 1548 |
+
>>> vr @ wr
|
| 1549 |
+
array([[ 1. , 1.69593, 1.9246 ],
|
| 1550 |
+
[ 0. , 2.59153, 3.23942],
|
| 1551 |
+
[ 0. , -3.23942, 2.59153]])
|
| 1552 |
+
>>> X @ vr
|
| 1553 |
+
array([[ 1. , 1.69593, 1.9246 ],
|
| 1554 |
+
[ 0. , 2.59153, 3.23942],
|
| 1555 |
+
[ 0. , -3.23942, 2.59153]])
|
| 1556 |
+
"""
|
| 1557 |
+
w, v = _asarray_validated(w), _asarray_validated(v)
|
| 1558 |
+
|
| 1559 |
+
# check dimensions
|
| 1560 |
+
if w.ndim < 1:
|
| 1561 |
+
raise ValueError('expected w to be at least 1D')
|
| 1562 |
+
if v.ndim < 2:
|
| 1563 |
+
raise ValueError('expected v to be at least 2D')
|
| 1564 |
+
if v.ndim != w.ndim + 1:
|
| 1565 |
+
raise ValueError('expected eigenvectors array to have exactly one '
|
| 1566 |
+
'dimension more than eigenvalues array')
|
| 1567 |
+
|
| 1568 |
+
# check shapes
|
| 1569 |
+
n = w.shape[-1]
|
| 1570 |
+
M = w.shape[:-1]
|
| 1571 |
+
if v.shape[-2] != v.shape[-1]:
|
| 1572 |
+
raise ValueError('expected v to be a square matrix or stacked square '
|
| 1573 |
+
'matrices: v.shape[-2] = v.shape[-1]')
|
| 1574 |
+
if v.shape[-1] != n:
|
| 1575 |
+
raise ValueError('expected the same number of eigenvalues as '
|
| 1576 |
+
'eigenvectors')
|
| 1577 |
+
|
| 1578 |
+
# get indices for each first pair of complex eigenvalues
|
| 1579 |
+
complex_mask = iscomplex(w)
|
| 1580 |
+
n_complex = complex_mask.sum(axis=-1)
|
| 1581 |
+
|
| 1582 |
+
# check if all complex eigenvalues have conjugate pairs
|
| 1583 |
+
if not (n_complex % 2 == 0).all():
|
| 1584 |
+
raise ValueError('expected complex-conjugate pairs of eigenvalues')
|
| 1585 |
+
|
| 1586 |
+
# find complex indices
|
| 1587 |
+
idx = nonzero(complex_mask)
|
| 1588 |
+
idx_stack = idx[:-1]
|
| 1589 |
+
idx_elem = idx[-1]
|
| 1590 |
+
|
| 1591 |
+
# filter them to conjugate indices, assuming pairs are not interleaved
|
| 1592 |
+
j = idx_elem[0::2]
|
| 1593 |
+
k = idx_elem[1::2]
|
| 1594 |
+
stack_ind = ()
|
| 1595 |
+
for i in idx_stack:
|
| 1596 |
+
# should never happen, assuming nonzero orders by the last axis
|
| 1597 |
+
assert (i[0::2] == i[1::2]).all(), \
|
| 1598 |
+
"Conjugate pair spanned different arrays!"
|
| 1599 |
+
stack_ind += (i[0::2],)
|
| 1600 |
+
|
| 1601 |
+
# all eigenvalues to diagonal form
|
| 1602 |
+
wr = zeros(M + (n, n), dtype=w.real.dtype)
|
| 1603 |
+
di = range(n)
|
| 1604 |
+
wr[..., di, di] = w.real
|
| 1605 |
+
|
| 1606 |
+
# complex eigenvalues to real block diagonal form
|
| 1607 |
+
wr[stack_ind + (j, k)] = w[stack_ind + (j,)].imag
|
| 1608 |
+
wr[stack_ind + (k, j)] = w[stack_ind + (k,)].imag
|
| 1609 |
+
|
| 1610 |
+
# compute real eigenvectors associated with real block diagonal eigenvalues
|
| 1611 |
+
u = zeros(M + (n, n), dtype=numpy.cdouble)
|
| 1612 |
+
u[..., di, di] = 1.0
|
| 1613 |
+
u[stack_ind + (j, j)] = 0.5j
|
| 1614 |
+
u[stack_ind + (j, k)] = 0.5
|
| 1615 |
+
u[stack_ind + (k, j)] = -0.5j
|
| 1616 |
+
u[stack_ind + (k, k)] = 0.5
|
| 1617 |
+
|
| 1618 |
+
# multiply matrices v and u (equivalent to v @ u)
|
| 1619 |
+
vr = einsum('...ij,...jk->...ik', v, u).real
|
| 1620 |
+
|
| 1621 |
+
return wr, vr
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cholesky.py
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Cholesky decomposition functions."""
|
| 2 |
+
|
| 3 |
+
from numpy import asarray_chkfinite, asarray, atleast_2d
|
| 4 |
+
|
| 5 |
+
# Local imports
|
| 6 |
+
from ._misc import LinAlgError, _datacopied
|
| 7 |
+
from .lapack import get_lapack_funcs
|
| 8 |
+
|
| 9 |
+
__all__ = ['cholesky', 'cho_factor', 'cho_solve', 'cholesky_banded',
|
| 10 |
+
'cho_solve_banded']
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _cholesky(a, lower=False, overwrite_a=False, clean=True,
|
| 14 |
+
check_finite=True):
|
| 15 |
+
"""Common code for cholesky() and cho_factor()."""
|
| 16 |
+
|
| 17 |
+
a1 = asarray_chkfinite(a) if check_finite else asarray(a)
|
| 18 |
+
a1 = atleast_2d(a1)
|
| 19 |
+
|
| 20 |
+
# Dimension check
|
| 21 |
+
if a1.ndim != 2:
|
| 22 |
+
raise ValueError(f'Input array needs to be 2D but received a {a1.ndim}d-array.')
|
| 23 |
+
# Squareness check
|
| 24 |
+
if a1.shape[0] != a1.shape[1]:
|
| 25 |
+
raise ValueError('Input array is expected to be square but has '
|
| 26 |
+
f'the shape: {a1.shape}.')
|
| 27 |
+
|
| 28 |
+
# Quick return for square empty array
|
| 29 |
+
if a1.size == 0:
|
| 30 |
+
return a1.copy(), lower
|
| 31 |
+
|
| 32 |
+
overwrite_a = overwrite_a or _datacopied(a1, a)
|
| 33 |
+
potrf, = get_lapack_funcs(('potrf',), (a1,))
|
| 34 |
+
c, info = potrf(a1, lower=lower, overwrite_a=overwrite_a, clean=clean)
|
| 35 |
+
if info > 0:
|
| 36 |
+
raise LinAlgError("%d-th leading minor of the array is not positive "
|
| 37 |
+
"definite" % info)
|
| 38 |
+
if info < 0:
|
| 39 |
+
raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument'
|
| 40 |
+
'on entry to "POTRF".')
|
| 41 |
+
return c, lower
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def cholesky(a, lower=False, overwrite_a=False, check_finite=True):
|
| 45 |
+
"""
|
| 46 |
+
Compute the Cholesky decomposition of a matrix.
|
| 47 |
+
|
| 48 |
+
Returns the Cholesky decomposition, :math:`A = L L^*` or
|
| 49 |
+
:math:`A = U^* U` of a Hermitian positive-definite matrix A.
|
| 50 |
+
|
| 51 |
+
Parameters
|
| 52 |
+
----------
|
| 53 |
+
a : (M, M) array_like
|
| 54 |
+
Matrix to be decomposed
|
| 55 |
+
lower : bool, optional
|
| 56 |
+
Whether to compute the upper- or lower-triangular Cholesky
|
| 57 |
+
factorization. Default is upper-triangular.
|
| 58 |
+
overwrite_a : bool, optional
|
| 59 |
+
Whether to overwrite data in `a` (may improve performance).
|
| 60 |
+
check_finite : bool, optional
|
| 61 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 62 |
+
Disabling may give a performance gain, but may result in problems
|
| 63 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 64 |
+
|
| 65 |
+
Returns
|
| 66 |
+
-------
|
| 67 |
+
c : (M, M) ndarray
|
| 68 |
+
Upper- or lower-triangular Cholesky factor of `a`.
|
| 69 |
+
|
| 70 |
+
Raises
|
| 71 |
+
------
|
| 72 |
+
LinAlgError : if decomposition fails.
|
| 73 |
+
|
| 74 |
+
Examples
|
| 75 |
+
--------
|
| 76 |
+
>>> import numpy as np
|
| 77 |
+
>>> from scipy.linalg import cholesky
|
| 78 |
+
>>> a = np.array([[1,-2j],[2j,5]])
|
| 79 |
+
>>> L = cholesky(a, lower=True)
|
| 80 |
+
>>> L
|
| 81 |
+
array([[ 1.+0.j, 0.+0.j],
|
| 82 |
+
[ 0.+2.j, 1.+0.j]])
|
| 83 |
+
>>> L @ L.T.conj()
|
| 84 |
+
array([[ 1.+0.j, 0.-2.j],
|
| 85 |
+
[ 0.+2.j, 5.+0.j]])
|
| 86 |
+
|
| 87 |
+
"""
|
| 88 |
+
c, lower = _cholesky(a, lower=lower, overwrite_a=overwrite_a, clean=True,
|
| 89 |
+
check_finite=check_finite)
|
| 90 |
+
return c
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def cho_factor(a, lower=False, overwrite_a=False, check_finite=True):
|
| 94 |
+
"""
|
| 95 |
+
Compute the Cholesky decomposition of a matrix, to use in cho_solve
|
| 96 |
+
|
| 97 |
+
Returns a matrix containing the Cholesky decomposition,
|
| 98 |
+
``A = L L*`` or ``A = U* U`` of a Hermitian positive-definite matrix `a`.
|
| 99 |
+
The return value can be directly used as the first parameter to cho_solve.
|
| 100 |
+
|
| 101 |
+
.. warning::
|
| 102 |
+
The returned matrix also contains random data in the entries not
|
| 103 |
+
used by the Cholesky decomposition. If you need to zero these
|
| 104 |
+
entries, use the function `cholesky` instead.
|
| 105 |
+
|
| 106 |
+
Parameters
|
| 107 |
+
----------
|
| 108 |
+
a : (M, M) array_like
|
| 109 |
+
Matrix to be decomposed
|
| 110 |
+
lower : bool, optional
|
| 111 |
+
Whether to compute the upper or lower triangular Cholesky factorization
|
| 112 |
+
(Default: upper-triangular)
|
| 113 |
+
overwrite_a : bool, optional
|
| 114 |
+
Whether to overwrite data in a (may improve performance)
|
| 115 |
+
check_finite : bool, optional
|
| 116 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 117 |
+
Disabling may give a performance gain, but may result in problems
|
| 118 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 119 |
+
|
| 120 |
+
Returns
|
| 121 |
+
-------
|
| 122 |
+
c : (M, M) ndarray
|
| 123 |
+
Matrix whose upper or lower triangle contains the Cholesky factor
|
| 124 |
+
of `a`. Other parts of the matrix contain random data.
|
| 125 |
+
lower : bool
|
| 126 |
+
Flag indicating whether the factor is in the lower or upper triangle
|
| 127 |
+
|
| 128 |
+
Raises
|
| 129 |
+
------
|
| 130 |
+
LinAlgError
|
| 131 |
+
Raised if decomposition fails.
|
| 132 |
+
|
| 133 |
+
See Also
|
| 134 |
+
--------
|
| 135 |
+
cho_solve : Solve a linear set equations using the Cholesky factorization
|
| 136 |
+
of a matrix.
|
| 137 |
+
|
| 138 |
+
Examples
|
| 139 |
+
--------
|
| 140 |
+
>>> import numpy as np
|
| 141 |
+
>>> from scipy.linalg import cho_factor
|
| 142 |
+
>>> A = np.array([[9, 3, 1, 5], [3, 7, 5, 1], [1, 5, 9, 2], [5, 1, 2, 6]])
|
| 143 |
+
>>> c, low = cho_factor(A)
|
| 144 |
+
>>> c
|
| 145 |
+
array([[3. , 1. , 0.33333333, 1.66666667],
|
| 146 |
+
[3. , 2.44948974, 1.90515869, -0.27216553],
|
| 147 |
+
[1. , 5. , 2.29330749, 0.8559528 ],
|
| 148 |
+
[5. , 1. , 2. , 1.55418563]])
|
| 149 |
+
>>> np.allclose(np.triu(c).T @ np. triu(c) - A, np.zeros((4, 4)))
|
| 150 |
+
True
|
| 151 |
+
|
| 152 |
+
"""
|
| 153 |
+
c, lower = _cholesky(a, lower=lower, overwrite_a=overwrite_a, clean=False,
|
| 154 |
+
check_finite=check_finite)
|
| 155 |
+
return c, lower
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def cho_solve(c_and_lower, b, overwrite_b=False, check_finite=True):
|
| 159 |
+
"""Solve the linear equations A x = b, given the Cholesky factorization of A.
|
| 160 |
+
|
| 161 |
+
Parameters
|
| 162 |
+
----------
|
| 163 |
+
(c, lower) : tuple, (array, bool)
|
| 164 |
+
Cholesky factorization of a, as given by cho_factor
|
| 165 |
+
b : array
|
| 166 |
+
Right-hand side
|
| 167 |
+
overwrite_b : bool, optional
|
| 168 |
+
Whether to overwrite data in b (may improve performance)
|
| 169 |
+
check_finite : bool, optional
|
| 170 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 171 |
+
Disabling may give a performance gain, but may result in problems
|
| 172 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 173 |
+
|
| 174 |
+
Returns
|
| 175 |
+
-------
|
| 176 |
+
x : array
|
| 177 |
+
The solution to the system A x = b
|
| 178 |
+
|
| 179 |
+
See Also
|
| 180 |
+
--------
|
| 181 |
+
cho_factor : Cholesky factorization of a matrix
|
| 182 |
+
|
| 183 |
+
Examples
|
| 184 |
+
--------
|
| 185 |
+
>>> import numpy as np
|
| 186 |
+
>>> from scipy.linalg import cho_factor, cho_solve
|
| 187 |
+
>>> A = np.array([[9, 3, 1, 5], [3, 7, 5, 1], [1, 5, 9, 2], [5, 1, 2, 6]])
|
| 188 |
+
>>> c, low = cho_factor(A)
|
| 189 |
+
>>> x = cho_solve((c, low), [1, 1, 1, 1])
|
| 190 |
+
>>> np.allclose(A @ x - [1, 1, 1, 1], np.zeros(4))
|
| 191 |
+
True
|
| 192 |
+
|
| 193 |
+
"""
|
| 194 |
+
(c, lower) = c_and_lower
|
| 195 |
+
if check_finite:
|
| 196 |
+
b1 = asarray_chkfinite(b)
|
| 197 |
+
c = asarray_chkfinite(c)
|
| 198 |
+
else:
|
| 199 |
+
b1 = asarray(b)
|
| 200 |
+
c = asarray(c)
|
| 201 |
+
if c.ndim != 2 or c.shape[0] != c.shape[1]:
|
| 202 |
+
raise ValueError("The factored matrix c is not square.")
|
| 203 |
+
if c.shape[1] != b1.shape[0]:
|
| 204 |
+
raise ValueError(f"incompatible dimensions ({c.shape} and {b1.shape})")
|
| 205 |
+
|
| 206 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 207 |
+
|
| 208 |
+
potrs, = get_lapack_funcs(('potrs',), (c, b1))
|
| 209 |
+
x, info = potrs(c, b1, lower=lower, overwrite_b=overwrite_b)
|
| 210 |
+
if info != 0:
|
| 211 |
+
raise ValueError('illegal value in %dth argument of internal potrs'
|
| 212 |
+
% -info)
|
| 213 |
+
return x
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def cholesky_banded(ab, overwrite_ab=False, lower=False, check_finite=True):
|
| 217 |
+
"""
|
| 218 |
+
Cholesky decompose a banded Hermitian positive-definite matrix
|
| 219 |
+
|
| 220 |
+
The matrix a is stored in ab either in lower-diagonal or upper-
|
| 221 |
+
diagonal ordered form::
|
| 222 |
+
|
| 223 |
+
ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
|
| 224 |
+
ab[ i - j, j] == a[i,j] (if lower form; i >= j)
|
| 225 |
+
|
| 226 |
+
Example of ab (shape of a is (6,6), u=2)::
|
| 227 |
+
|
| 228 |
+
upper form:
|
| 229 |
+
* * a02 a13 a24 a35
|
| 230 |
+
* a01 a12 a23 a34 a45
|
| 231 |
+
a00 a11 a22 a33 a44 a55
|
| 232 |
+
|
| 233 |
+
lower form:
|
| 234 |
+
a00 a11 a22 a33 a44 a55
|
| 235 |
+
a10 a21 a32 a43 a54 *
|
| 236 |
+
a20 a31 a42 a53 * *
|
| 237 |
+
|
| 238 |
+
Parameters
|
| 239 |
+
----------
|
| 240 |
+
ab : (u + 1, M) array_like
|
| 241 |
+
Banded matrix
|
| 242 |
+
overwrite_ab : bool, optional
|
| 243 |
+
Discard data in ab (may enhance performance)
|
| 244 |
+
lower : bool, optional
|
| 245 |
+
Is the matrix in the lower form. (Default is upper form)
|
| 246 |
+
check_finite : bool, optional
|
| 247 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 248 |
+
Disabling may give a performance gain, but may result in problems
|
| 249 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 250 |
+
|
| 251 |
+
Returns
|
| 252 |
+
-------
|
| 253 |
+
c : (u + 1, M) ndarray
|
| 254 |
+
Cholesky factorization of a, in the same banded format as ab
|
| 255 |
+
|
| 256 |
+
See Also
|
| 257 |
+
--------
|
| 258 |
+
cho_solve_banded :
|
| 259 |
+
Solve a linear set equations, given the Cholesky factorization
|
| 260 |
+
of a banded Hermitian.
|
| 261 |
+
|
| 262 |
+
Examples
|
| 263 |
+
--------
|
| 264 |
+
>>> import numpy as np
|
| 265 |
+
>>> from scipy.linalg import cholesky_banded
|
| 266 |
+
>>> from numpy import allclose, zeros, diag
|
| 267 |
+
>>> Ab = np.array([[0, 0, 1j, 2, 3j], [0, -1, -2, 3, 4], [9, 8, 7, 6, 9]])
|
| 268 |
+
>>> A = np.diag(Ab[0,2:], k=2) + np.diag(Ab[1,1:], k=1)
|
| 269 |
+
>>> A = A + A.conj().T + np.diag(Ab[2, :])
|
| 270 |
+
>>> c = cholesky_banded(Ab)
|
| 271 |
+
>>> C = np.diag(c[0, 2:], k=2) + np.diag(c[1, 1:], k=1) + np.diag(c[2, :])
|
| 272 |
+
>>> np.allclose(C.conj().T @ C - A, np.zeros((5, 5)))
|
| 273 |
+
True
|
| 274 |
+
|
| 275 |
+
"""
|
| 276 |
+
if check_finite:
|
| 277 |
+
ab = asarray_chkfinite(ab)
|
| 278 |
+
else:
|
| 279 |
+
ab = asarray(ab)
|
| 280 |
+
|
| 281 |
+
pbtrf, = get_lapack_funcs(('pbtrf',), (ab,))
|
| 282 |
+
c, info = pbtrf(ab, lower=lower, overwrite_ab=overwrite_ab)
|
| 283 |
+
if info > 0:
|
| 284 |
+
raise LinAlgError("%d-th leading minor not positive definite" % info)
|
| 285 |
+
if info < 0:
|
| 286 |
+
raise ValueError('illegal value in %d-th argument of internal pbtrf'
|
| 287 |
+
% -info)
|
| 288 |
+
return c
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
def cho_solve_banded(cb_and_lower, b, overwrite_b=False, check_finite=True):
|
| 292 |
+
"""
|
| 293 |
+
Solve the linear equations ``A x = b``, given the Cholesky factorization of
|
| 294 |
+
the banded Hermitian ``A``.
|
| 295 |
+
|
| 296 |
+
Parameters
|
| 297 |
+
----------
|
| 298 |
+
(cb, lower) : tuple, (ndarray, bool)
|
| 299 |
+
`cb` is the Cholesky factorization of A, as given by cholesky_banded.
|
| 300 |
+
`lower` must be the same value that was given to cholesky_banded.
|
| 301 |
+
b : array_like
|
| 302 |
+
Right-hand side
|
| 303 |
+
overwrite_b : bool, optional
|
| 304 |
+
If True, the function will overwrite the values in `b`.
|
| 305 |
+
check_finite : bool, optional
|
| 306 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 307 |
+
Disabling may give a performance gain, but may result in problems
|
| 308 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 309 |
+
|
| 310 |
+
Returns
|
| 311 |
+
-------
|
| 312 |
+
x : array
|
| 313 |
+
The solution to the system A x = b
|
| 314 |
+
|
| 315 |
+
See Also
|
| 316 |
+
--------
|
| 317 |
+
cholesky_banded : Cholesky factorization of a banded matrix
|
| 318 |
+
|
| 319 |
+
Notes
|
| 320 |
+
-----
|
| 321 |
+
|
| 322 |
+
.. versionadded:: 0.8.0
|
| 323 |
+
|
| 324 |
+
Examples
|
| 325 |
+
--------
|
| 326 |
+
>>> import numpy as np
|
| 327 |
+
>>> from scipy.linalg import cholesky_banded, cho_solve_banded
|
| 328 |
+
>>> Ab = np.array([[0, 0, 1j, 2, 3j], [0, -1, -2, 3, 4], [9, 8, 7, 6, 9]])
|
| 329 |
+
>>> A = np.diag(Ab[0,2:], k=2) + np.diag(Ab[1,1:], k=1)
|
| 330 |
+
>>> A = A + A.conj().T + np.diag(Ab[2, :])
|
| 331 |
+
>>> c = cholesky_banded(Ab)
|
| 332 |
+
>>> x = cho_solve_banded((c, False), np.ones(5))
|
| 333 |
+
>>> np.allclose(A @ x - np.ones(5), np.zeros(5))
|
| 334 |
+
True
|
| 335 |
+
|
| 336 |
+
"""
|
| 337 |
+
(cb, lower) = cb_and_lower
|
| 338 |
+
if check_finite:
|
| 339 |
+
cb = asarray_chkfinite(cb)
|
| 340 |
+
b = asarray_chkfinite(b)
|
| 341 |
+
else:
|
| 342 |
+
cb = asarray(cb)
|
| 343 |
+
b = asarray(b)
|
| 344 |
+
|
| 345 |
+
# Validate shapes.
|
| 346 |
+
if cb.shape[-1] != b.shape[0]:
|
| 347 |
+
raise ValueError("shapes of cb and b are not compatible.")
|
| 348 |
+
|
| 349 |
+
pbtrs, = get_lapack_funcs(('pbtrs',), (cb, b))
|
| 350 |
+
x, info = pbtrs(cb, b, lower=lower, overwrite_b=overwrite_b)
|
| 351 |
+
if info > 0:
|
| 352 |
+
raise LinAlgError("%dth leading minor not positive definite" % info)
|
| 353 |
+
if info < 0:
|
| 354 |
+
raise ValueError('illegal value in %dth argument of internal pbtrs'
|
| 355 |
+
% -info)
|
| 356 |
+
return x
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cossin.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections.abc import Iterable
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
from scipy._lib._util import _asarray_validated
|
| 5 |
+
from scipy.linalg import block_diag, LinAlgError
|
| 6 |
+
from .lapack import _compute_lwork, get_lapack_funcs
|
| 7 |
+
|
| 8 |
+
__all__ = ['cossin']
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def cossin(X, p=None, q=None, separate=False,
|
| 12 |
+
swap_sign=False, compute_u=True, compute_vh=True):
|
| 13 |
+
"""
|
| 14 |
+
Compute the cosine-sine (CS) decomposition of an orthogonal/unitary matrix.
|
| 15 |
+
|
| 16 |
+
X is an ``(m, m)`` orthogonal/unitary matrix, partitioned as the following
|
| 17 |
+
where upper left block has the shape of ``(p, q)``::
|
| 18 |
+
|
| 19 |
+
┌ ┐
|
| 20 |
+
│ I 0 0 │ 0 0 0 │
|
| 21 |
+
┌ ┐ ┌ ┐│ 0 C 0 │ 0 -S 0 │┌ ┐*
|
| 22 |
+
│ X11 │ X12 │ │ U1 │ ││ 0 0 0 │ 0 0 -I ││ V1 │ │
|
| 23 |
+
│ ────┼──── │ = │────┼────││─────────┼─────────││────┼────│
|
| 24 |
+
│ X21 │ X22 │ │ │ U2 ││ 0 0 0 │ I 0 0 ││ │ V2 │
|
| 25 |
+
└ ┘ └ ┘│ 0 S 0 │ 0 C 0 │└ ┘
|
| 26 |
+
│ 0 0 I │ 0 0 0 │
|
| 27 |
+
└ ┘
|
| 28 |
+
|
| 29 |
+
``U1``, ``U2``, ``V1``, ``V2`` are square orthogonal/unitary matrices of
|
| 30 |
+
dimensions ``(p,p)``, ``(m-p,m-p)``, ``(q,q)``, and ``(m-q,m-q)``
|
| 31 |
+
respectively, and ``C`` and ``S`` are ``(r, r)`` nonnegative diagonal
|
| 32 |
+
matrices satisfying ``C^2 + S^2 = I`` where ``r = min(p, m-p, q, m-q)``.
|
| 33 |
+
|
| 34 |
+
Moreover, the rank of the identity matrices are ``min(p, q) - r``,
|
| 35 |
+
``min(p, m - q) - r``, ``min(m - p, q) - r``, and ``min(m - p, m - q) - r``
|
| 36 |
+
respectively.
|
| 37 |
+
|
| 38 |
+
X can be supplied either by itself and block specifications p, q or its
|
| 39 |
+
subblocks in an iterable from which the shapes would be derived. See the
|
| 40 |
+
examples below.
|
| 41 |
+
|
| 42 |
+
Parameters
|
| 43 |
+
----------
|
| 44 |
+
X : array_like, iterable
|
| 45 |
+
complex unitary or real orthogonal matrix to be decomposed, or iterable
|
| 46 |
+
of subblocks ``X11``, ``X12``, ``X21``, ``X22``, when ``p``, ``q`` are
|
| 47 |
+
omitted.
|
| 48 |
+
p : int, optional
|
| 49 |
+
Number of rows of the upper left block ``X11``, used only when X is
|
| 50 |
+
given as an array.
|
| 51 |
+
q : int, optional
|
| 52 |
+
Number of columns of the upper left block ``X11``, used only when X is
|
| 53 |
+
given as an array.
|
| 54 |
+
separate : bool, optional
|
| 55 |
+
if ``True``, the low level components are returned instead of the
|
| 56 |
+
matrix factors, i.e. ``(u1,u2)``, ``theta``, ``(v1h,v2h)`` instead of
|
| 57 |
+
``u``, ``cs``, ``vh``.
|
| 58 |
+
swap_sign : bool, optional
|
| 59 |
+
if ``True``, the ``-S``, ``-I`` block will be the bottom left,
|
| 60 |
+
otherwise (by default) they will be in the upper right block.
|
| 61 |
+
compute_u : bool, optional
|
| 62 |
+
if ``False``, ``u`` won't be computed and an empty array is returned.
|
| 63 |
+
compute_vh : bool, optional
|
| 64 |
+
if ``False``, ``vh`` won't be computed and an empty array is returned.
|
| 65 |
+
|
| 66 |
+
Returns
|
| 67 |
+
-------
|
| 68 |
+
u : ndarray
|
| 69 |
+
When ``compute_u=True``, contains the block diagonal orthogonal/unitary
|
| 70 |
+
matrix consisting of the blocks ``U1`` (``p`` x ``p``) and ``U2``
|
| 71 |
+
(``m-p`` x ``m-p``) orthogonal/unitary matrices. If ``separate=True``,
|
| 72 |
+
this contains the tuple of ``(U1, U2)``.
|
| 73 |
+
cs : ndarray
|
| 74 |
+
The cosine-sine factor with the structure described above.
|
| 75 |
+
If ``separate=True``, this contains the ``theta`` array containing the
|
| 76 |
+
angles in radians.
|
| 77 |
+
vh : ndarray
|
| 78 |
+
When ``compute_vh=True`, contains the block diagonal orthogonal/unitary
|
| 79 |
+
matrix consisting of the blocks ``V1H`` (``q`` x ``q``) and ``V2H``
|
| 80 |
+
(``m-q`` x ``m-q``) orthogonal/unitary matrices. If ``separate=True``,
|
| 81 |
+
this contains the tuple of ``(V1H, V2H)``.
|
| 82 |
+
|
| 83 |
+
References
|
| 84 |
+
----------
|
| 85 |
+
.. [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
|
| 86 |
+
Algorithms, 50(1):33-65, 2009.
|
| 87 |
+
|
| 88 |
+
Examples
|
| 89 |
+
--------
|
| 90 |
+
>>> import numpy as np
|
| 91 |
+
>>> from scipy.linalg import cossin
|
| 92 |
+
>>> from scipy.stats import unitary_group
|
| 93 |
+
>>> x = unitary_group.rvs(4)
|
| 94 |
+
>>> u, cs, vdh = cossin(x, p=2, q=2)
|
| 95 |
+
>>> np.allclose(x, u @ cs @ vdh)
|
| 96 |
+
True
|
| 97 |
+
|
| 98 |
+
Same can be entered via subblocks without the need of ``p`` and ``q``. Also
|
| 99 |
+
let's skip the computation of ``u``
|
| 100 |
+
|
| 101 |
+
>>> ue, cs, vdh = cossin((x[:2, :2], x[:2, 2:], x[2:, :2], x[2:, 2:]),
|
| 102 |
+
... compute_u=False)
|
| 103 |
+
>>> print(ue)
|
| 104 |
+
[]
|
| 105 |
+
>>> np.allclose(x, u @ cs @ vdh)
|
| 106 |
+
True
|
| 107 |
+
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
if p or q:
|
| 111 |
+
p = 1 if p is None else int(p)
|
| 112 |
+
q = 1 if q is None else int(q)
|
| 113 |
+
X = _asarray_validated(X, check_finite=True)
|
| 114 |
+
if not np.equal(*X.shape):
|
| 115 |
+
raise ValueError("Cosine Sine decomposition only supports square"
|
| 116 |
+
f" matrices, got {X.shape}")
|
| 117 |
+
m = X.shape[0]
|
| 118 |
+
if p >= m or p <= 0:
|
| 119 |
+
raise ValueError(f"invalid p={p}, 0<p<{X.shape[0]} must hold")
|
| 120 |
+
if q >= m or q <= 0:
|
| 121 |
+
raise ValueError(f"invalid q={q}, 0<q<{X.shape[0]} must hold")
|
| 122 |
+
|
| 123 |
+
x11, x12, x21, x22 = X[:p, :q], X[:p, q:], X[p:, :q], X[p:, q:]
|
| 124 |
+
elif not isinstance(X, Iterable):
|
| 125 |
+
raise ValueError("When p and q are None, X must be an Iterable"
|
| 126 |
+
" containing the subblocks of X")
|
| 127 |
+
else:
|
| 128 |
+
if len(X) != 4:
|
| 129 |
+
raise ValueError("When p and q are None, exactly four arrays"
|
| 130 |
+
f" should be in X, got {len(X)}")
|
| 131 |
+
|
| 132 |
+
x11, x12, x21, x22 = (np.atleast_2d(x) for x in X)
|
| 133 |
+
for name, block in zip(["x11", "x12", "x21", "x22"],
|
| 134 |
+
[x11, x12, x21, x22]):
|
| 135 |
+
if block.shape[1] == 0:
|
| 136 |
+
raise ValueError(f"{name} can't be empty")
|
| 137 |
+
p, q = x11.shape
|
| 138 |
+
mmp, mmq = x22.shape
|
| 139 |
+
|
| 140 |
+
if x12.shape != (p, mmq):
|
| 141 |
+
raise ValueError(f"Invalid x12 dimensions: desired {(p, mmq)}, "
|
| 142 |
+
f"got {x12.shape}")
|
| 143 |
+
|
| 144 |
+
if x21.shape != (mmp, q):
|
| 145 |
+
raise ValueError(f"Invalid x21 dimensions: desired {(mmp, q)}, "
|
| 146 |
+
f"got {x21.shape}")
|
| 147 |
+
|
| 148 |
+
if p + mmp != q + mmq:
|
| 149 |
+
raise ValueError("The subblocks have compatible sizes but "
|
| 150 |
+
"don't form a square array (instead they form a"
|
| 151 |
+
" {}x{} array). This might be due to missing "
|
| 152 |
+
"p, q arguments.".format(p + mmp, q + mmq))
|
| 153 |
+
|
| 154 |
+
m = p + mmp
|
| 155 |
+
|
| 156 |
+
cplx = any([np.iscomplexobj(x) for x in [x11, x12, x21, x22]])
|
| 157 |
+
driver = "uncsd" if cplx else "orcsd"
|
| 158 |
+
csd, csd_lwork = get_lapack_funcs([driver, driver + "_lwork"],
|
| 159 |
+
[x11, x12, x21, x22])
|
| 160 |
+
lwork = _compute_lwork(csd_lwork, m=m, p=p, q=q)
|
| 161 |
+
lwork_args = ({'lwork': lwork[0], 'lrwork': lwork[1]} if cplx else
|
| 162 |
+
{'lwork': lwork})
|
| 163 |
+
*_, theta, u1, u2, v1h, v2h, info = csd(x11=x11, x12=x12, x21=x21, x22=x22,
|
| 164 |
+
compute_u1=compute_u,
|
| 165 |
+
compute_u2=compute_u,
|
| 166 |
+
compute_v1t=compute_vh,
|
| 167 |
+
compute_v2t=compute_vh,
|
| 168 |
+
trans=False, signs=swap_sign,
|
| 169 |
+
**lwork_args)
|
| 170 |
+
|
| 171 |
+
method_name = csd.typecode + driver
|
| 172 |
+
if info < 0:
|
| 173 |
+
raise ValueError(f'illegal value in argument {-info} '
|
| 174 |
+
f'of internal {method_name}')
|
| 175 |
+
if info > 0:
|
| 176 |
+
raise LinAlgError(f"{method_name} did not converge: {info}")
|
| 177 |
+
|
| 178 |
+
if separate:
|
| 179 |
+
return (u1, u2), theta, (v1h, v2h)
|
| 180 |
+
|
| 181 |
+
U = block_diag(u1, u2)
|
| 182 |
+
VDH = block_diag(v1h, v2h)
|
| 183 |
+
|
| 184 |
+
# Construct the middle factor CS
|
| 185 |
+
c = np.diag(np.cos(theta))
|
| 186 |
+
s = np.diag(np.sin(theta))
|
| 187 |
+
r = min(p, q, m - p, m - q)
|
| 188 |
+
n11 = min(p, q) - r
|
| 189 |
+
n12 = min(p, m - q) - r
|
| 190 |
+
n21 = min(m - p, q) - r
|
| 191 |
+
n22 = min(m - p, m - q) - r
|
| 192 |
+
Id = np.eye(np.max([n11, n12, n21, n22, r]), dtype=theta.dtype)
|
| 193 |
+
CS = np.zeros((m, m), dtype=theta.dtype)
|
| 194 |
+
|
| 195 |
+
CS[:n11, :n11] = Id[:n11, :n11]
|
| 196 |
+
|
| 197 |
+
xs = n11 + r
|
| 198 |
+
xe = n11 + r + n12
|
| 199 |
+
ys = n11 + n21 + n22 + 2 * r
|
| 200 |
+
ye = n11 + n21 + n22 + 2 * r + n12
|
| 201 |
+
CS[xs: xe, ys:ye] = Id[:n12, :n12] if swap_sign else -Id[:n12, :n12]
|
| 202 |
+
|
| 203 |
+
xs = p + n22 + r
|
| 204 |
+
xe = p + n22 + r + + n21
|
| 205 |
+
ys = n11 + r
|
| 206 |
+
ye = n11 + r + n21
|
| 207 |
+
CS[xs:xe, ys:ye] = -Id[:n21, :n21] if swap_sign else Id[:n21, :n21]
|
| 208 |
+
|
| 209 |
+
CS[p:p + n22, q:q + n22] = Id[:n22, :n22]
|
| 210 |
+
CS[n11:n11 + r, n11:n11 + r] = c
|
| 211 |
+
CS[p + n22:p + n22 + r, r + n21 + n22:2 * r + n21 + n22] = c
|
| 212 |
+
|
| 213 |
+
xs = n11
|
| 214 |
+
xe = n11 + r
|
| 215 |
+
ys = n11 + n21 + n22 + r
|
| 216 |
+
ye = n11 + n21 + n22 + 2 * r
|
| 217 |
+
CS[xs:xe, ys:ye] = s if swap_sign else -s
|
| 218 |
+
|
| 219 |
+
CS[p + n22:p + n22 + r, n11:n11 + r] = -s if swap_sign else s
|
| 220 |
+
|
| 221 |
+
return U, CS, VDH
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_ldl.py
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from warnings import warn
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
from numpy import (atleast_2d, arange, zeros_like, imag, diag,
|
| 5 |
+
iscomplexobj, tril, triu, argsort, empty_like)
|
| 6 |
+
from scipy._lib._util import ComplexWarning
|
| 7 |
+
from ._decomp import _asarray_validated
|
| 8 |
+
from .lapack import get_lapack_funcs, _compute_lwork
|
| 9 |
+
|
| 10 |
+
__all__ = ['ldl']
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def ldl(A, lower=True, hermitian=True, overwrite_a=False, check_finite=True):
|
| 14 |
+
""" Computes the LDLt or Bunch-Kaufman factorization of a symmetric/
|
| 15 |
+
hermitian matrix.
|
| 16 |
+
|
| 17 |
+
This function returns a block diagonal matrix D consisting blocks of size
|
| 18 |
+
at most 2x2 and also a possibly permuted unit lower triangular matrix
|
| 19 |
+
``L`` such that the factorization ``A = L D L^H`` or ``A = L D L^T``
|
| 20 |
+
holds. If `lower` is False then (again possibly permuted) upper
|
| 21 |
+
triangular matrices are returned as outer factors.
|
| 22 |
+
|
| 23 |
+
The permutation array can be used to triangularize the outer factors
|
| 24 |
+
simply by a row shuffle, i.e., ``lu[perm, :]`` is an upper/lower
|
| 25 |
+
triangular matrix. This is also equivalent to multiplication with a
|
| 26 |
+
permutation matrix ``P.dot(lu)``, where ``P`` is a column-permuted
|
| 27 |
+
identity matrix ``I[:, perm]``.
|
| 28 |
+
|
| 29 |
+
Depending on the value of the boolean `lower`, only upper or lower
|
| 30 |
+
triangular part of the input array is referenced. Hence, a triangular
|
| 31 |
+
matrix on entry would give the same result as if the full matrix is
|
| 32 |
+
supplied.
|
| 33 |
+
|
| 34 |
+
Parameters
|
| 35 |
+
----------
|
| 36 |
+
A : array_like
|
| 37 |
+
Square input array
|
| 38 |
+
lower : bool, optional
|
| 39 |
+
This switches between the lower and upper triangular outer factors of
|
| 40 |
+
the factorization. Lower triangular (``lower=True``) is the default.
|
| 41 |
+
hermitian : bool, optional
|
| 42 |
+
For complex-valued arrays, this defines whether ``A = A.conj().T`` or
|
| 43 |
+
``A = A.T`` is assumed. For real-valued arrays, this switch has no
|
| 44 |
+
effect.
|
| 45 |
+
overwrite_a : bool, optional
|
| 46 |
+
Allow overwriting data in `A` (may enhance performance). The default
|
| 47 |
+
is False.
|
| 48 |
+
check_finite : bool, optional
|
| 49 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 50 |
+
Disabling may give a performance gain, but may result in problems
|
| 51 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 52 |
+
|
| 53 |
+
Returns
|
| 54 |
+
-------
|
| 55 |
+
lu : ndarray
|
| 56 |
+
The (possibly) permuted upper/lower triangular outer factor of the
|
| 57 |
+
factorization.
|
| 58 |
+
d : ndarray
|
| 59 |
+
The block diagonal multiplier of the factorization.
|
| 60 |
+
perm : ndarray
|
| 61 |
+
The row-permutation index array that brings lu into triangular form.
|
| 62 |
+
|
| 63 |
+
Raises
|
| 64 |
+
------
|
| 65 |
+
ValueError
|
| 66 |
+
If input array is not square.
|
| 67 |
+
ComplexWarning
|
| 68 |
+
If a complex-valued array with nonzero imaginary parts on the
|
| 69 |
+
diagonal is given and hermitian is set to True.
|
| 70 |
+
|
| 71 |
+
See Also
|
| 72 |
+
--------
|
| 73 |
+
cholesky, lu
|
| 74 |
+
|
| 75 |
+
Notes
|
| 76 |
+
-----
|
| 77 |
+
This function uses ``?SYTRF`` routines for symmetric matrices and
|
| 78 |
+
``?HETRF`` routines for Hermitian matrices from LAPACK. See [1]_ for
|
| 79 |
+
the algorithm details.
|
| 80 |
+
|
| 81 |
+
Depending on the `lower` keyword value, only lower or upper triangular
|
| 82 |
+
part of the input array is referenced. Moreover, this keyword also defines
|
| 83 |
+
the structure of the outer factors of the factorization.
|
| 84 |
+
|
| 85 |
+
.. versionadded:: 1.1.0
|
| 86 |
+
|
| 87 |
+
References
|
| 88 |
+
----------
|
| 89 |
+
.. [1] J.R. Bunch, L. Kaufman, Some stable methods for calculating
|
| 90 |
+
inertia and solving symmetric linear systems, Math. Comput. Vol.31,
|
| 91 |
+
1977. :doi:`10.2307/2005787`
|
| 92 |
+
|
| 93 |
+
Examples
|
| 94 |
+
--------
|
| 95 |
+
Given an upper triangular array ``a`` that represents the full symmetric
|
| 96 |
+
array with its entries, obtain ``l``, 'd' and the permutation vector `perm`:
|
| 97 |
+
|
| 98 |
+
>>> import numpy as np
|
| 99 |
+
>>> from scipy.linalg import ldl
|
| 100 |
+
>>> a = np.array([[2, -1, 3], [0, 2, 0], [0, 0, 1]])
|
| 101 |
+
>>> lu, d, perm = ldl(a, lower=0) # Use the upper part
|
| 102 |
+
>>> lu
|
| 103 |
+
array([[ 0. , 0. , 1. ],
|
| 104 |
+
[ 0. , 1. , -0.5],
|
| 105 |
+
[ 1. , 1. , 1.5]])
|
| 106 |
+
>>> d
|
| 107 |
+
array([[-5. , 0. , 0. ],
|
| 108 |
+
[ 0. , 1.5, 0. ],
|
| 109 |
+
[ 0. , 0. , 2. ]])
|
| 110 |
+
>>> perm
|
| 111 |
+
array([2, 1, 0])
|
| 112 |
+
>>> lu[perm, :]
|
| 113 |
+
array([[ 1. , 1. , 1.5],
|
| 114 |
+
[ 0. , 1. , -0.5],
|
| 115 |
+
[ 0. , 0. , 1. ]])
|
| 116 |
+
>>> lu.dot(d).dot(lu.T)
|
| 117 |
+
array([[ 2., -1., 3.],
|
| 118 |
+
[-1., 2., 0.],
|
| 119 |
+
[ 3., 0., 1.]])
|
| 120 |
+
|
| 121 |
+
"""
|
| 122 |
+
a = atleast_2d(_asarray_validated(A, check_finite=check_finite))
|
| 123 |
+
if a.shape[0] != a.shape[1]:
|
| 124 |
+
raise ValueError('The input array "a" should be square.')
|
| 125 |
+
# Return empty arrays for empty square input
|
| 126 |
+
if a.size == 0:
|
| 127 |
+
return empty_like(a), empty_like(a), np.array([], dtype=int)
|
| 128 |
+
|
| 129 |
+
n = a.shape[0]
|
| 130 |
+
r_or_c = complex if iscomplexobj(a) else float
|
| 131 |
+
|
| 132 |
+
# Get the LAPACK routine
|
| 133 |
+
if r_or_c is complex and hermitian:
|
| 134 |
+
s, sl = 'hetrf', 'hetrf_lwork'
|
| 135 |
+
if np.any(imag(diag(a))):
|
| 136 |
+
warn('scipy.linalg.ldl():\nThe imaginary parts of the diagonal'
|
| 137 |
+
'are ignored. Use "hermitian=False" for factorization of'
|
| 138 |
+
'complex symmetric arrays.', ComplexWarning, stacklevel=2)
|
| 139 |
+
else:
|
| 140 |
+
s, sl = 'sytrf', 'sytrf_lwork'
|
| 141 |
+
|
| 142 |
+
solver, solver_lwork = get_lapack_funcs((s, sl), (a,))
|
| 143 |
+
lwork = _compute_lwork(solver_lwork, n, lower=lower)
|
| 144 |
+
ldu, piv, info = solver(a, lwork=lwork, lower=lower,
|
| 145 |
+
overwrite_a=overwrite_a)
|
| 146 |
+
if info < 0:
|
| 147 |
+
raise ValueError(f'{s.upper()} exited with the internal error "illegal value '
|
| 148 |
+
f'in argument number {-info}". See LAPACK documentation '
|
| 149 |
+
'for the error codes.')
|
| 150 |
+
|
| 151 |
+
swap_arr, pivot_arr = _ldl_sanitize_ipiv(piv, lower=lower)
|
| 152 |
+
d, lu = _ldl_get_d_and_l(ldu, pivot_arr, lower=lower, hermitian=hermitian)
|
| 153 |
+
lu, perm = _ldl_construct_tri_factor(lu, swap_arr, pivot_arr, lower=lower)
|
| 154 |
+
|
| 155 |
+
return lu, d, perm
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def _ldl_sanitize_ipiv(a, lower=True):
|
| 159 |
+
"""
|
| 160 |
+
This helper function takes the rather strangely encoded permutation array
|
| 161 |
+
returned by the LAPACK routines ?(HE/SY)TRF and converts it into
|
| 162 |
+
regularized permutation and diagonal pivot size format.
|
| 163 |
+
|
| 164 |
+
Since FORTRAN uses 1-indexing and LAPACK uses different start points for
|
| 165 |
+
upper and lower formats there are certain offsets in the indices used
|
| 166 |
+
below.
|
| 167 |
+
|
| 168 |
+
Let's assume a result where the matrix is 6x6 and there are two 2x2
|
| 169 |
+
and two 1x1 blocks reported by the routine. To ease the coding efforts,
|
| 170 |
+
we still populate a 6-sized array and fill zeros as the following ::
|
| 171 |
+
|
| 172 |
+
pivots = [2, 0, 2, 0, 1, 1]
|
| 173 |
+
|
| 174 |
+
This denotes a diagonal matrix of the form ::
|
| 175 |
+
|
| 176 |
+
[x x ]
|
| 177 |
+
[x x ]
|
| 178 |
+
[ x x ]
|
| 179 |
+
[ x x ]
|
| 180 |
+
[ x ]
|
| 181 |
+
[ x]
|
| 182 |
+
|
| 183 |
+
In other words, we write 2 when the 2x2 block is first encountered and
|
| 184 |
+
automatically write 0 to the next entry and skip the next spin of the
|
| 185 |
+
loop. Thus, a separate counter or array appends to keep track of block
|
| 186 |
+
sizes are avoided. If needed, zeros can be filtered out later without
|
| 187 |
+
losing the block structure.
|
| 188 |
+
|
| 189 |
+
Parameters
|
| 190 |
+
----------
|
| 191 |
+
a : ndarray
|
| 192 |
+
The permutation array ipiv returned by LAPACK
|
| 193 |
+
lower : bool, optional
|
| 194 |
+
The switch to select whether upper or lower triangle is chosen in
|
| 195 |
+
the LAPACK call.
|
| 196 |
+
|
| 197 |
+
Returns
|
| 198 |
+
-------
|
| 199 |
+
swap_ : ndarray
|
| 200 |
+
The array that defines the row/column swap operations. For example,
|
| 201 |
+
if row two is swapped with row four, the result is [0, 3, 2, 3].
|
| 202 |
+
pivots : ndarray
|
| 203 |
+
The array that defines the block diagonal structure as given above.
|
| 204 |
+
|
| 205 |
+
"""
|
| 206 |
+
n = a.size
|
| 207 |
+
swap_ = arange(n)
|
| 208 |
+
pivots = zeros_like(swap_, dtype=int)
|
| 209 |
+
skip_2x2 = False
|
| 210 |
+
|
| 211 |
+
# Some upper/lower dependent offset values
|
| 212 |
+
# range (s)tart, r(e)nd, r(i)ncrement
|
| 213 |
+
x, y, rs, re, ri = (1, 0, 0, n, 1) if lower else (-1, -1, n-1, -1, -1)
|
| 214 |
+
|
| 215 |
+
for ind in range(rs, re, ri):
|
| 216 |
+
# If previous spin belonged already to a 2x2 block
|
| 217 |
+
if skip_2x2:
|
| 218 |
+
skip_2x2 = False
|
| 219 |
+
continue
|
| 220 |
+
|
| 221 |
+
cur_val = a[ind]
|
| 222 |
+
# do we have a 1x1 block or not?
|
| 223 |
+
if cur_val > 0:
|
| 224 |
+
if cur_val != ind+1:
|
| 225 |
+
# Index value != array value --> permutation required
|
| 226 |
+
swap_[ind] = swap_[cur_val-1]
|
| 227 |
+
pivots[ind] = 1
|
| 228 |
+
# Not.
|
| 229 |
+
elif cur_val < 0 and cur_val == a[ind+x]:
|
| 230 |
+
# first neg entry of 2x2 block identifier
|
| 231 |
+
if -cur_val != ind+2:
|
| 232 |
+
# Index value != array value --> permutation required
|
| 233 |
+
swap_[ind+x] = swap_[-cur_val-1]
|
| 234 |
+
pivots[ind+y] = 2
|
| 235 |
+
skip_2x2 = True
|
| 236 |
+
else: # Doesn't make sense, give up
|
| 237 |
+
raise ValueError('While parsing the permutation array '
|
| 238 |
+
'in "scipy.linalg.ldl", invalid entries '
|
| 239 |
+
'found. The array syntax is invalid.')
|
| 240 |
+
return swap_, pivots
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
def _ldl_get_d_and_l(ldu, pivs, lower=True, hermitian=True):
|
| 244 |
+
"""
|
| 245 |
+
Helper function to extract the diagonal and triangular matrices for
|
| 246 |
+
LDL.T factorization.
|
| 247 |
+
|
| 248 |
+
Parameters
|
| 249 |
+
----------
|
| 250 |
+
ldu : ndarray
|
| 251 |
+
The compact output returned by the LAPACK routing
|
| 252 |
+
pivs : ndarray
|
| 253 |
+
The sanitized array of {0, 1, 2} denoting the sizes of the pivots. For
|
| 254 |
+
every 2 there is a succeeding 0.
|
| 255 |
+
lower : bool, optional
|
| 256 |
+
If set to False, upper triangular part is considered.
|
| 257 |
+
hermitian : bool, optional
|
| 258 |
+
If set to False a symmetric complex array is assumed.
|
| 259 |
+
|
| 260 |
+
Returns
|
| 261 |
+
-------
|
| 262 |
+
d : ndarray
|
| 263 |
+
The block diagonal matrix.
|
| 264 |
+
lu : ndarray
|
| 265 |
+
The upper/lower triangular matrix
|
| 266 |
+
"""
|
| 267 |
+
is_c = iscomplexobj(ldu)
|
| 268 |
+
d = diag(diag(ldu))
|
| 269 |
+
n = d.shape[0]
|
| 270 |
+
blk_i = 0 # block index
|
| 271 |
+
|
| 272 |
+
# row/column offsets for selecting sub-, super-diagonal
|
| 273 |
+
x, y = (1, 0) if lower else (0, 1)
|
| 274 |
+
|
| 275 |
+
lu = tril(ldu, -1) if lower else triu(ldu, 1)
|
| 276 |
+
diag_inds = arange(n)
|
| 277 |
+
lu[diag_inds, diag_inds] = 1
|
| 278 |
+
|
| 279 |
+
for blk in pivs[pivs != 0]:
|
| 280 |
+
# increment the block index and check for 2s
|
| 281 |
+
# if 2 then copy the off diagonals depending on uplo
|
| 282 |
+
inc = blk_i + blk
|
| 283 |
+
|
| 284 |
+
if blk == 2:
|
| 285 |
+
d[blk_i+x, blk_i+y] = ldu[blk_i+x, blk_i+y]
|
| 286 |
+
# If Hermitian matrix is factorized, the cross-offdiagonal element
|
| 287 |
+
# should be conjugated.
|
| 288 |
+
if is_c and hermitian:
|
| 289 |
+
d[blk_i+y, blk_i+x] = ldu[blk_i+x, blk_i+y].conj()
|
| 290 |
+
else:
|
| 291 |
+
d[blk_i+y, blk_i+x] = ldu[blk_i+x, blk_i+y]
|
| 292 |
+
|
| 293 |
+
lu[blk_i+x, blk_i+y] = 0.
|
| 294 |
+
blk_i = inc
|
| 295 |
+
|
| 296 |
+
return d, lu
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def _ldl_construct_tri_factor(lu, swap_vec, pivs, lower=True):
|
| 300 |
+
"""
|
| 301 |
+
Helper function to construct explicit outer factors of LDL factorization.
|
| 302 |
+
|
| 303 |
+
If lower is True the permuted factors are multiplied as L(1)*L(2)*...*L(k).
|
| 304 |
+
Otherwise, the permuted factors are multiplied as L(k)*...*L(2)*L(1). See
|
| 305 |
+
LAPACK documentation for more details.
|
| 306 |
+
|
| 307 |
+
Parameters
|
| 308 |
+
----------
|
| 309 |
+
lu : ndarray
|
| 310 |
+
The triangular array that is extracted from LAPACK routine call with
|
| 311 |
+
ones on the diagonals.
|
| 312 |
+
swap_vec : ndarray
|
| 313 |
+
The array that defines the row swapping indices. If the kth entry is m
|
| 314 |
+
then rows k,m are swapped. Notice that the mth entry is not necessarily
|
| 315 |
+
k to avoid undoing the swapping.
|
| 316 |
+
pivs : ndarray
|
| 317 |
+
The array that defines the block diagonal structure returned by
|
| 318 |
+
_ldl_sanitize_ipiv().
|
| 319 |
+
lower : bool, optional
|
| 320 |
+
The boolean to switch between lower and upper triangular structure.
|
| 321 |
+
|
| 322 |
+
Returns
|
| 323 |
+
-------
|
| 324 |
+
lu : ndarray
|
| 325 |
+
The square outer factor which satisfies the L * D * L.T = A
|
| 326 |
+
perm : ndarray
|
| 327 |
+
The permutation vector that brings the lu to the triangular form
|
| 328 |
+
|
| 329 |
+
Notes
|
| 330 |
+
-----
|
| 331 |
+
Note that the original argument "lu" is overwritten.
|
| 332 |
+
|
| 333 |
+
"""
|
| 334 |
+
n = lu.shape[0]
|
| 335 |
+
perm = arange(n)
|
| 336 |
+
# Setup the reading order of the permutation matrix for upper/lower
|
| 337 |
+
rs, re, ri = (n-1, -1, -1) if lower else (0, n, 1)
|
| 338 |
+
|
| 339 |
+
for ind in range(rs, re, ri):
|
| 340 |
+
s_ind = swap_vec[ind]
|
| 341 |
+
if s_ind != ind:
|
| 342 |
+
# Column start and end positions
|
| 343 |
+
col_s = ind if lower else 0
|
| 344 |
+
col_e = n if lower else ind+1
|
| 345 |
+
|
| 346 |
+
# If we stumble upon a 2x2 block include both cols in the perm.
|
| 347 |
+
if pivs[ind] == (0 if lower else 2):
|
| 348 |
+
col_s += -1 if lower else 0
|
| 349 |
+
col_e += 0 if lower else 1
|
| 350 |
+
lu[[s_ind, ind], col_s:col_e] = lu[[ind, s_ind], col_s:col_e]
|
| 351 |
+
perm[[s_ind, ind]] = perm[[ind, s_ind]]
|
| 352 |
+
|
| 353 |
+
return lu, argsort(perm)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu.py
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""LU decomposition functions."""
|
| 2 |
+
|
| 3 |
+
from warnings import warn
|
| 4 |
+
|
| 5 |
+
from numpy import asarray, asarray_chkfinite
|
| 6 |
+
import numpy as np
|
| 7 |
+
from itertools import product
|
| 8 |
+
|
| 9 |
+
# Local imports
|
| 10 |
+
from ._misc import _datacopied, LinAlgWarning
|
| 11 |
+
from .lapack import get_lapack_funcs
|
| 12 |
+
from ._decomp_lu_cython import lu_dispatcher
|
| 13 |
+
|
| 14 |
+
lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
|
| 15 |
+
for x in np.typecodes['All']}
|
| 16 |
+
|
| 17 |
+
__all__ = ['lu', 'lu_solve', 'lu_factor']
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def lu_factor(a, overwrite_a=False, check_finite=True):
|
| 21 |
+
"""
|
| 22 |
+
Compute pivoted LU decomposition of a matrix.
|
| 23 |
+
|
| 24 |
+
The decomposition is::
|
| 25 |
+
|
| 26 |
+
A = P L U
|
| 27 |
+
|
| 28 |
+
where P is a permutation matrix, L lower triangular with unit
|
| 29 |
+
diagonal elements, and U upper triangular.
|
| 30 |
+
|
| 31 |
+
Parameters
|
| 32 |
+
----------
|
| 33 |
+
a : (M, N) array_like
|
| 34 |
+
Matrix to decompose
|
| 35 |
+
overwrite_a : bool, optional
|
| 36 |
+
Whether to overwrite data in A (may increase performance)
|
| 37 |
+
check_finite : bool, optional
|
| 38 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 39 |
+
Disabling may give a performance gain, but may result in problems
|
| 40 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 41 |
+
|
| 42 |
+
Returns
|
| 43 |
+
-------
|
| 44 |
+
lu : (M, N) ndarray
|
| 45 |
+
Matrix containing U in its upper triangle, and L in its lower triangle.
|
| 46 |
+
The unit diagonal elements of L are not stored.
|
| 47 |
+
piv : (K,) ndarray
|
| 48 |
+
Pivot indices representing the permutation matrix P:
|
| 49 |
+
row i of matrix was interchanged with row piv[i].
|
| 50 |
+
Of shape ``(K,)``, with ``K = min(M, N)``.
|
| 51 |
+
|
| 52 |
+
See Also
|
| 53 |
+
--------
|
| 54 |
+
lu : gives lu factorization in more user-friendly format
|
| 55 |
+
lu_solve : solve an equation system using the LU factorization of a matrix
|
| 56 |
+
|
| 57 |
+
Notes
|
| 58 |
+
-----
|
| 59 |
+
This is a wrapper to the ``*GETRF`` routines from LAPACK. Unlike
|
| 60 |
+
:func:`lu`, it outputs the L and U factors into a single array
|
| 61 |
+
and returns pivot indices instead of a permutation matrix.
|
| 62 |
+
|
| 63 |
+
While the underlying ``*GETRF`` routines return 1-based pivot indices, the
|
| 64 |
+
``piv`` array returned by ``lu_factor`` contains 0-based indices.
|
| 65 |
+
|
| 66 |
+
Examples
|
| 67 |
+
--------
|
| 68 |
+
>>> import numpy as np
|
| 69 |
+
>>> from scipy.linalg import lu_factor
|
| 70 |
+
>>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
|
| 71 |
+
>>> lu, piv = lu_factor(A)
|
| 72 |
+
>>> piv
|
| 73 |
+
array([2, 2, 3, 3], dtype=int32)
|
| 74 |
+
|
| 75 |
+
Convert LAPACK's ``piv`` array to NumPy index and test the permutation
|
| 76 |
+
|
| 77 |
+
>>> def pivot_to_permutation(piv):
|
| 78 |
+
... perm = np.arange(len(piv))
|
| 79 |
+
... for i in range(len(piv)):
|
| 80 |
+
... perm[i], perm[piv[i]] = perm[piv[i]], perm[i]
|
| 81 |
+
... return perm
|
| 82 |
+
...
|
| 83 |
+
>>> p_inv = pivot_to_permutation(piv)
|
| 84 |
+
>>> p_inv
|
| 85 |
+
array([2, 0, 3, 1])
|
| 86 |
+
>>> L, U = np.tril(lu, k=-1) + np.eye(4), np.triu(lu)
|
| 87 |
+
>>> np.allclose(A[p_inv] - L @ U, np.zeros((4, 4)))
|
| 88 |
+
True
|
| 89 |
+
|
| 90 |
+
The P matrix in P L U is defined by the inverse permutation and
|
| 91 |
+
can be recovered using argsort:
|
| 92 |
+
|
| 93 |
+
>>> p = np.argsort(p_inv)
|
| 94 |
+
>>> p
|
| 95 |
+
array([1, 3, 0, 2])
|
| 96 |
+
>>> np.allclose(A - L[p] @ U, np.zeros((4, 4)))
|
| 97 |
+
True
|
| 98 |
+
|
| 99 |
+
or alternatively:
|
| 100 |
+
|
| 101 |
+
>>> P = np.eye(4)[p]
|
| 102 |
+
>>> np.allclose(A - P @ L @ U, np.zeros((4, 4)))
|
| 103 |
+
True
|
| 104 |
+
"""
|
| 105 |
+
if check_finite:
|
| 106 |
+
a1 = asarray_chkfinite(a)
|
| 107 |
+
else:
|
| 108 |
+
a1 = asarray(a)
|
| 109 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 110 |
+
getrf, = get_lapack_funcs(('getrf',), (a1,))
|
| 111 |
+
lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
|
| 112 |
+
if info < 0:
|
| 113 |
+
raise ValueError('illegal value in %dth argument of '
|
| 114 |
+
'internal getrf (lu_factor)' % -info)
|
| 115 |
+
if info > 0:
|
| 116 |
+
warn("Diagonal number %d is exactly zero. Singular matrix." % info,
|
| 117 |
+
LinAlgWarning, stacklevel=2)
|
| 118 |
+
return lu, piv
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def lu_solve(lu_and_piv, b, trans=0, overwrite_b=False, check_finite=True):
|
| 122 |
+
"""Solve an equation system, a x = b, given the LU factorization of a
|
| 123 |
+
|
| 124 |
+
Parameters
|
| 125 |
+
----------
|
| 126 |
+
(lu, piv)
|
| 127 |
+
Factorization of the coefficient matrix a, as given by lu_factor.
|
| 128 |
+
In particular piv are 0-indexed pivot indices.
|
| 129 |
+
b : array
|
| 130 |
+
Right-hand side
|
| 131 |
+
trans : {0, 1, 2}, optional
|
| 132 |
+
Type of system to solve:
|
| 133 |
+
|
| 134 |
+
===== =========
|
| 135 |
+
trans system
|
| 136 |
+
===== =========
|
| 137 |
+
0 a x = b
|
| 138 |
+
1 a^T x = b
|
| 139 |
+
2 a^H x = b
|
| 140 |
+
===== =========
|
| 141 |
+
overwrite_b : bool, optional
|
| 142 |
+
Whether to overwrite data in b (may increase performance)
|
| 143 |
+
check_finite : bool, optional
|
| 144 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 145 |
+
Disabling may give a performance gain, but may result in problems
|
| 146 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 147 |
+
|
| 148 |
+
Returns
|
| 149 |
+
-------
|
| 150 |
+
x : array
|
| 151 |
+
Solution to the system
|
| 152 |
+
|
| 153 |
+
See Also
|
| 154 |
+
--------
|
| 155 |
+
lu_factor : LU factorize a matrix
|
| 156 |
+
|
| 157 |
+
Examples
|
| 158 |
+
--------
|
| 159 |
+
>>> import numpy as np
|
| 160 |
+
>>> from scipy.linalg import lu_factor, lu_solve
|
| 161 |
+
>>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
|
| 162 |
+
>>> b = np.array([1, 1, 1, 1])
|
| 163 |
+
>>> lu, piv = lu_factor(A)
|
| 164 |
+
>>> x = lu_solve((lu, piv), b)
|
| 165 |
+
>>> np.allclose(A @ x - b, np.zeros((4,)))
|
| 166 |
+
True
|
| 167 |
+
|
| 168 |
+
"""
|
| 169 |
+
(lu, piv) = lu_and_piv
|
| 170 |
+
if check_finite:
|
| 171 |
+
b1 = asarray_chkfinite(b)
|
| 172 |
+
else:
|
| 173 |
+
b1 = asarray(b)
|
| 174 |
+
overwrite_b = overwrite_b or _datacopied(b1, b)
|
| 175 |
+
if lu.shape[0] != b1.shape[0]:
|
| 176 |
+
raise ValueError(f"Shapes of lu {lu.shape} and b {b1.shape} are incompatible")
|
| 177 |
+
|
| 178 |
+
getrs, = get_lapack_funcs(('getrs',), (lu, b1))
|
| 179 |
+
x, info = getrs(lu, piv, b1, trans=trans, overwrite_b=overwrite_b)
|
| 180 |
+
if info == 0:
|
| 181 |
+
return x
|
| 182 |
+
raise ValueError('illegal value in %dth argument of internal gesv|posv'
|
| 183 |
+
% -info)
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def lu(a, permute_l=False, overwrite_a=False, check_finite=True,
|
| 187 |
+
p_indices=False):
|
| 188 |
+
"""
|
| 189 |
+
Compute LU decomposition of a matrix with partial pivoting.
|
| 190 |
+
|
| 191 |
+
The decomposition satisfies::
|
| 192 |
+
|
| 193 |
+
A = P @ L @ U
|
| 194 |
+
|
| 195 |
+
where ``P`` is a permutation matrix, ``L`` lower triangular with unit
|
| 196 |
+
diagonal elements, and ``U`` upper triangular. If `permute_l` is set to
|
| 197 |
+
``True`` then ``L`` is returned already permuted and hence satisfying
|
| 198 |
+
``A = L @ U``.
|
| 199 |
+
|
| 200 |
+
Parameters
|
| 201 |
+
----------
|
| 202 |
+
a : (M, N) array_like
|
| 203 |
+
Array to decompose
|
| 204 |
+
permute_l : bool, optional
|
| 205 |
+
Perform the multiplication P*L (Default: do not permute)
|
| 206 |
+
overwrite_a : bool, optional
|
| 207 |
+
Whether to overwrite data in a (may improve performance)
|
| 208 |
+
check_finite : bool, optional
|
| 209 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 210 |
+
Disabling may give a performance gain, but may result in problems
|
| 211 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 212 |
+
p_indices : bool, optional
|
| 213 |
+
If ``True`` the permutation information is returned as row indices.
|
| 214 |
+
The default is ``False`` for backwards-compatibility reasons.
|
| 215 |
+
|
| 216 |
+
Returns
|
| 217 |
+
-------
|
| 218 |
+
**(If `permute_l` is ``False``)**
|
| 219 |
+
|
| 220 |
+
p : (..., M, M) ndarray
|
| 221 |
+
Permutation arrays or vectors depending on `p_indices`
|
| 222 |
+
l : (..., M, K) ndarray
|
| 223 |
+
Lower triangular or trapezoidal array with unit diagonal.
|
| 224 |
+
``K = min(M, N)``
|
| 225 |
+
u : (..., K, N) ndarray
|
| 226 |
+
Upper triangular or trapezoidal array
|
| 227 |
+
|
| 228 |
+
**(If `permute_l` is ``True``)**
|
| 229 |
+
|
| 230 |
+
pl : (..., M, K) ndarray
|
| 231 |
+
Permuted L matrix.
|
| 232 |
+
``K = min(M, N)``
|
| 233 |
+
u : (..., K, N) ndarray
|
| 234 |
+
Upper triangular or trapezoidal array
|
| 235 |
+
|
| 236 |
+
Notes
|
| 237 |
+
-----
|
| 238 |
+
Permutation matrices are costly since they are nothing but row reorder of
|
| 239 |
+
``L`` and hence indices are strongly recommended to be used instead if the
|
| 240 |
+
permutation is required. The relation in the 2D case then becomes simply
|
| 241 |
+
``A = L[P, :] @ U``. In higher dimensions, it is better to use `permute_l`
|
| 242 |
+
to avoid complicated indexing tricks.
|
| 243 |
+
|
| 244 |
+
In 2D case, if one has the indices however, for some reason, the
|
| 245 |
+
permutation matrix is still needed then it can be constructed by
|
| 246 |
+
``np.eye(M)[P, :]``.
|
| 247 |
+
|
| 248 |
+
Examples
|
| 249 |
+
--------
|
| 250 |
+
|
| 251 |
+
>>> import numpy as np
|
| 252 |
+
>>> from scipy.linalg import lu
|
| 253 |
+
>>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
|
| 254 |
+
>>> p, l, u = lu(A)
|
| 255 |
+
>>> np.allclose(A, p @ l @ u)
|
| 256 |
+
True
|
| 257 |
+
>>> p # Permutation matrix
|
| 258 |
+
array([[0., 1., 0., 0.], # Row index 1
|
| 259 |
+
[0., 0., 0., 1.], # Row index 3
|
| 260 |
+
[1., 0., 0., 0.], # Row index 0
|
| 261 |
+
[0., 0., 1., 0.]]) # Row index 2
|
| 262 |
+
>>> p, _, _ = lu(A, p_indices=True)
|
| 263 |
+
>>> p
|
| 264 |
+
array([1, 3, 0, 2]) # as given by row indices above
|
| 265 |
+
>>> np.allclose(A, l[p, :] @ u)
|
| 266 |
+
True
|
| 267 |
+
|
| 268 |
+
We can also use nd-arrays, for example, a demonstration with 4D array:
|
| 269 |
+
|
| 270 |
+
>>> rng = np.random.default_rng()
|
| 271 |
+
>>> A = rng.uniform(low=-4, high=4, size=[3, 2, 4, 8])
|
| 272 |
+
>>> p, l, u = lu(A)
|
| 273 |
+
>>> p.shape, l.shape, u.shape
|
| 274 |
+
((3, 2, 4, 4), (3, 2, 4, 4), (3, 2, 4, 8))
|
| 275 |
+
>>> np.allclose(A, p @ l @ u)
|
| 276 |
+
True
|
| 277 |
+
>>> PL, U = lu(A, permute_l=True)
|
| 278 |
+
>>> np.allclose(A, PL @ U)
|
| 279 |
+
True
|
| 280 |
+
|
| 281 |
+
"""
|
| 282 |
+
a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
|
| 283 |
+
if a1.ndim < 2:
|
| 284 |
+
raise ValueError('The input array must be at least two-dimensional.')
|
| 285 |
+
|
| 286 |
+
# Also check if dtype is LAPACK compatible
|
| 287 |
+
if a1.dtype.char not in 'fdFD':
|
| 288 |
+
dtype_char = lapack_cast_dict[a1.dtype.char]
|
| 289 |
+
if not dtype_char: # No casting possible
|
| 290 |
+
raise TypeError(f'The dtype {a1.dtype} cannot be cast '
|
| 291 |
+
'to float(32, 64) or complex(64, 128).')
|
| 292 |
+
|
| 293 |
+
a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
|
| 294 |
+
overwrite_a = True
|
| 295 |
+
|
| 296 |
+
*nd, m, n = a1.shape
|
| 297 |
+
k = min(m, n)
|
| 298 |
+
real_dchar = 'f' if a1.dtype.char in 'fF' else 'd'
|
| 299 |
+
|
| 300 |
+
# Empty input
|
| 301 |
+
if min(*a1.shape) == 0:
|
| 302 |
+
if permute_l:
|
| 303 |
+
PL = np.empty(shape=[*nd, m, k], dtype=a1.dtype)
|
| 304 |
+
U = np.empty(shape=[*nd, k, n], dtype=a1.dtype)
|
| 305 |
+
return PL, U
|
| 306 |
+
else:
|
| 307 |
+
P = (np.empty([*nd, 0], dtype=np.int32) if p_indices else
|
| 308 |
+
np.empty([*nd, 0, 0], dtype=real_dchar))
|
| 309 |
+
L = np.empty(shape=[*nd, m, k], dtype=a1.dtype)
|
| 310 |
+
U = np.empty(shape=[*nd, k, n], dtype=a1.dtype)
|
| 311 |
+
return P, L, U
|
| 312 |
+
|
| 313 |
+
# Scalar case
|
| 314 |
+
if a1.shape[-2:] == (1, 1):
|
| 315 |
+
if permute_l:
|
| 316 |
+
return np.ones_like(a1), (a1 if overwrite_a else a1.copy())
|
| 317 |
+
else:
|
| 318 |
+
P = (np.zeros(shape=[*nd, m], dtype=int) if p_indices
|
| 319 |
+
else np.ones_like(a1))
|
| 320 |
+
return P, np.ones_like(a1), (a1 if overwrite_a else a1.copy())
|
| 321 |
+
|
| 322 |
+
# Then check overwrite permission
|
| 323 |
+
if not _datacopied(a1, a): # "a" still alive through "a1"
|
| 324 |
+
if not overwrite_a:
|
| 325 |
+
# Data belongs to "a" so make a copy
|
| 326 |
+
a1 = a1.copy(order='C')
|
| 327 |
+
# else: Do nothing we'll use "a" if possible
|
| 328 |
+
# else: a1 has its own data thus free to scratch
|
| 329 |
+
|
| 330 |
+
# Then layout checks, might happen that overwrite is allowed but original
|
| 331 |
+
# array was read-only or non-contiguous.
|
| 332 |
+
|
| 333 |
+
if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
|
| 334 |
+
a1 = a1.copy(order='C')
|
| 335 |
+
|
| 336 |
+
if not nd: # 2D array
|
| 337 |
+
|
| 338 |
+
p = np.empty(m, dtype=np.int32)
|
| 339 |
+
u = np.zeros([k, k], dtype=a1.dtype)
|
| 340 |
+
lu_dispatcher(a1, u, p, permute_l)
|
| 341 |
+
P, L, U = (p, a1, u) if m > n else (p, u, a1)
|
| 342 |
+
|
| 343 |
+
else: # Stacked array
|
| 344 |
+
|
| 345 |
+
# Prepare the contiguous data holders
|
| 346 |
+
P = np.empty([*nd, m], dtype=np.int32) # perm vecs
|
| 347 |
+
|
| 348 |
+
if m > n: # Tall arrays, U will be created
|
| 349 |
+
U = np.zeros([*nd, k, k], dtype=a1.dtype)
|
| 350 |
+
for ind in product(*[range(x) for x in a1.shape[:-2]]):
|
| 351 |
+
lu_dispatcher(a1[ind], U[ind], P[ind], permute_l)
|
| 352 |
+
L = a1
|
| 353 |
+
|
| 354 |
+
else: # Fat arrays, L will be created
|
| 355 |
+
L = np.zeros([*nd, k, k], dtype=a1.dtype)
|
| 356 |
+
for ind in product(*[range(x) for x in a1.shape[:-2]]):
|
| 357 |
+
lu_dispatcher(a1[ind], L[ind], P[ind], permute_l)
|
| 358 |
+
U = a1
|
| 359 |
+
|
| 360 |
+
# Convert permutation vecs to permutation arrays
|
| 361 |
+
# permute_l=False needed to enter here to avoid wasted efforts
|
| 362 |
+
if (not p_indices) and (not permute_l):
|
| 363 |
+
if nd:
|
| 364 |
+
Pa = np.zeros([*nd, m, m], dtype=real_dchar)
|
| 365 |
+
# An unreadable index hack - One-hot encoding for perm matrices
|
| 366 |
+
nd_ix = np.ix_(*([np.arange(x) for x in nd]+[np.arange(m)]))
|
| 367 |
+
Pa[(*nd_ix, P)] = 1
|
| 368 |
+
P = Pa
|
| 369 |
+
else: # 2D case
|
| 370 |
+
Pa = np.zeros([m, m], dtype=real_dchar)
|
| 371 |
+
Pa[np.arange(m), P] = 1
|
| 372 |
+
P = Pa
|
| 373 |
+
|
| 374 |
+
return (L, U) if permute_l else (P, L, U)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu_cython.pyi
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from numpy.typing import NDArray
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
def lu_decompose(a: NDArray[Any], lu: NDArray[Any], perm: NDArray[Any], permute_l: bool) -> None: ... # noqa: E501
|
| 5 |
+
|
| 6 |
+
def lu_dispatcher(a: NDArray[Any], lu: NDArray[Any], perm: NDArray[Any], permute_l: bool) -> None: ... # noqa: E501
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_polar.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
from scipy.linalg import svd
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
__all__ = ['polar']
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def polar(a, side="right"):
|
| 9 |
+
"""
|
| 10 |
+
Compute the polar decomposition.
|
| 11 |
+
|
| 12 |
+
Returns the factors of the polar decomposition [1]_ `u` and `p` such
|
| 13 |
+
that ``a = up`` (if `side` is "right") or ``a = pu`` (if `side` is
|
| 14 |
+
"left"), where `p` is positive semidefinite. Depending on the shape
|
| 15 |
+
of `a`, either the rows or columns of `u` are orthonormal. When `a`
|
| 16 |
+
is a square array, `u` is a square unitary array. When `a` is not
|
| 17 |
+
square, the "canonical polar decomposition" [2]_ is computed.
|
| 18 |
+
|
| 19 |
+
Parameters
|
| 20 |
+
----------
|
| 21 |
+
a : (m, n) array_like
|
| 22 |
+
The array to be factored.
|
| 23 |
+
side : {'left', 'right'}, optional
|
| 24 |
+
Determines whether a right or left polar decomposition is computed.
|
| 25 |
+
If `side` is "right", then ``a = up``. If `side` is "left", then
|
| 26 |
+
``a = pu``. The default is "right".
|
| 27 |
+
|
| 28 |
+
Returns
|
| 29 |
+
-------
|
| 30 |
+
u : (m, n) ndarray
|
| 31 |
+
If `a` is square, then `u` is unitary. If m > n, then the columns
|
| 32 |
+
of `a` are orthonormal, and if m < n, then the rows of `u` are
|
| 33 |
+
orthonormal.
|
| 34 |
+
p : ndarray
|
| 35 |
+
`p` is Hermitian positive semidefinite. If `a` is nonsingular, `p`
|
| 36 |
+
is positive definite. The shape of `p` is (n, n) or (m, m), depending
|
| 37 |
+
on whether `side` is "right" or "left", respectively.
|
| 38 |
+
|
| 39 |
+
References
|
| 40 |
+
----------
|
| 41 |
+
.. [1] R. A. Horn and C. R. Johnson, "Matrix Analysis", Cambridge
|
| 42 |
+
University Press, 1985.
|
| 43 |
+
.. [2] N. J. Higham, "Functions of Matrices: Theory and Computation",
|
| 44 |
+
SIAM, 2008.
|
| 45 |
+
|
| 46 |
+
Examples
|
| 47 |
+
--------
|
| 48 |
+
>>> import numpy as np
|
| 49 |
+
>>> from scipy.linalg import polar
|
| 50 |
+
>>> a = np.array([[1, -1], [2, 4]])
|
| 51 |
+
>>> u, p = polar(a)
|
| 52 |
+
>>> u
|
| 53 |
+
array([[ 0.85749293, -0.51449576],
|
| 54 |
+
[ 0.51449576, 0.85749293]])
|
| 55 |
+
>>> p
|
| 56 |
+
array([[ 1.88648444, 1.2004901 ],
|
| 57 |
+
[ 1.2004901 , 3.94446746]])
|
| 58 |
+
|
| 59 |
+
A non-square example, with m < n:
|
| 60 |
+
|
| 61 |
+
>>> b = np.array([[0.5, 1, 2], [1.5, 3, 4]])
|
| 62 |
+
>>> u, p = polar(b)
|
| 63 |
+
>>> u
|
| 64 |
+
array([[-0.21196618, -0.42393237, 0.88054056],
|
| 65 |
+
[ 0.39378971, 0.78757942, 0.4739708 ]])
|
| 66 |
+
>>> p
|
| 67 |
+
array([[ 0.48470147, 0.96940295, 1.15122648],
|
| 68 |
+
[ 0.96940295, 1.9388059 , 2.30245295],
|
| 69 |
+
[ 1.15122648, 2.30245295, 3.65696431]])
|
| 70 |
+
>>> u.dot(p) # Verify the decomposition.
|
| 71 |
+
array([[ 0.5, 1. , 2. ],
|
| 72 |
+
[ 1.5, 3. , 4. ]])
|
| 73 |
+
>>> u.dot(u.T) # The rows of u are orthonormal.
|
| 74 |
+
array([[ 1.00000000e+00, -2.07353665e-17],
|
| 75 |
+
[ -2.07353665e-17, 1.00000000e+00]])
|
| 76 |
+
|
| 77 |
+
Another non-square example, with m > n:
|
| 78 |
+
|
| 79 |
+
>>> c = b.T
|
| 80 |
+
>>> u, p = polar(c)
|
| 81 |
+
>>> u
|
| 82 |
+
array([[-0.21196618, 0.39378971],
|
| 83 |
+
[-0.42393237, 0.78757942],
|
| 84 |
+
[ 0.88054056, 0.4739708 ]])
|
| 85 |
+
>>> p
|
| 86 |
+
array([[ 1.23116567, 1.93241587],
|
| 87 |
+
[ 1.93241587, 4.84930602]])
|
| 88 |
+
>>> u.dot(p) # Verify the decomposition.
|
| 89 |
+
array([[ 0.5, 1.5],
|
| 90 |
+
[ 1. , 3. ],
|
| 91 |
+
[ 2. , 4. ]])
|
| 92 |
+
>>> u.T.dot(u) # The columns of u are orthonormal.
|
| 93 |
+
array([[ 1.00000000e+00, -1.26363763e-16],
|
| 94 |
+
[ -1.26363763e-16, 1.00000000e+00]])
|
| 95 |
+
|
| 96 |
+
"""
|
| 97 |
+
if side not in ['right', 'left']:
|
| 98 |
+
raise ValueError("`side` must be either 'right' or 'left'")
|
| 99 |
+
a = np.asarray(a)
|
| 100 |
+
if a.ndim != 2:
|
| 101 |
+
raise ValueError("`a` must be a 2-D array.")
|
| 102 |
+
|
| 103 |
+
w, s, vh = svd(a, full_matrices=False)
|
| 104 |
+
u = w.dot(vh)
|
| 105 |
+
if side == 'right':
|
| 106 |
+
# a = up
|
| 107 |
+
p = (vh.T.conj() * s).dot(vh)
|
| 108 |
+
else:
|
| 109 |
+
# a = pu
|
| 110 |
+
p = (w * s).dot(w.T.conj())
|
| 111 |
+
return u, p
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qr.py
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""QR decomposition functions."""
|
| 2 |
+
import numpy
|
| 3 |
+
|
| 4 |
+
# Local imports
|
| 5 |
+
from .lapack import get_lapack_funcs
|
| 6 |
+
from ._misc import _datacopied
|
| 7 |
+
|
| 8 |
+
__all__ = ['qr', 'qr_multiply', 'rq']
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def safecall(f, name, *args, **kwargs):
|
| 12 |
+
"""Call a LAPACK routine, determining lwork automatically and handling
|
| 13 |
+
error return values"""
|
| 14 |
+
lwork = kwargs.get("lwork", None)
|
| 15 |
+
if lwork in (None, -1):
|
| 16 |
+
kwargs['lwork'] = -1
|
| 17 |
+
ret = f(*args, **kwargs)
|
| 18 |
+
kwargs['lwork'] = ret[-2][0].real.astype(numpy.int_)
|
| 19 |
+
ret = f(*args, **kwargs)
|
| 20 |
+
if ret[-1] < 0:
|
| 21 |
+
raise ValueError("illegal value in %dth argument of internal %s"
|
| 22 |
+
% (-ret[-1], name))
|
| 23 |
+
return ret[:-2]
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def qr(a, overwrite_a=False, lwork=None, mode='full', pivoting=False,
|
| 27 |
+
check_finite=True):
|
| 28 |
+
"""
|
| 29 |
+
Compute QR decomposition of a matrix.
|
| 30 |
+
|
| 31 |
+
Calculate the decomposition ``A = Q R`` where Q is unitary/orthogonal
|
| 32 |
+
and R upper triangular.
|
| 33 |
+
|
| 34 |
+
Parameters
|
| 35 |
+
----------
|
| 36 |
+
a : (M, N) array_like
|
| 37 |
+
Matrix to be decomposed
|
| 38 |
+
overwrite_a : bool, optional
|
| 39 |
+
Whether data in `a` is overwritten (may improve performance if
|
| 40 |
+
`overwrite_a` is set to True by reusing the existing input data
|
| 41 |
+
structure rather than creating a new one.)
|
| 42 |
+
lwork : int, optional
|
| 43 |
+
Work array size, lwork >= a.shape[1]. If None or -1, an optimal size
|
| 44 |
+
is computed.
|
| 45 |
+
mode : {'full', 'r', 'economic', 'raw'}, optional
|
| 46 |
+
Determines what information is to be returned: either both Q and R
|
| 47 |
+
('full', default), only R ('r') or both Q and R but computed in
|
| 48 |
+
economy-size ('economic', see Notes). The final option 'raw'
|
| 49 |
+
(added in SciPy 0.11) makes the function return two matrices
|
| 50 |
+
(Q, TAU) in the internal format used by LAPACK.
|
| 51 |
+
pivoting : bool, optional
|
| 52 |
+
Whether or not factorization should include pivoting for rank-revealing
|
| 53 |
+
qr decomposition. If pivoting, compute the decomposition
|
| 54 |
+
``A[:, P] = Q @ R`` as above, but where P is chosen such that the
|
| 55 |
+
diagonal of R is non-increasing.
|
| 56 |
+
check_finite : bool, optional
|
| 57 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 58 |
+
Disabling may give a performance gain, but may result in problems
|
| 59 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 60 |
+
|
| 61 |
+
Returns
|
| 62 |
+
-------
|
| 63 |
+
Q : float or complex ndarray
|
| 64 |
+
Of shape (M, M), or (M, K) for ``mode='economic'``. Not returned
|
| 65 |
+
if ``mode='r'``. Replaced by tuple ``(Q, TAU)`` if ``mode='raw'``.
|
| 66 |
+
R : float or complex ndarray
|
| 67 |
+
Of shape (M, N), or (K, N) for ``mode in ['economic', 'raw']``.
|
| 68 |
+
``K = min(M, N)``.
|
| 69 |
+
P : int ndarray
|
| 70 |
+
Of shape (N,) for ``pivoting=True``. Not returned if
|
| 71 |
+
``pivoting=False``.
|
| 72 |
+
|
| 73 |
+
Raises
|
| 74 |
+
------
|
| 75 |
+
LinAlgError
|
| 76 |
+
Raised if decomposition fails
|
| 77 |
+
|
| 78 |
+
Notes
|
| 79 |
+
-----
|
| 80 |
+
This is an interface to the LAPACK routines dgeqrf, zgeqrf,
|
| 81 |
+
dorgqr, zungqr, dgeqp3, and zgeqp3.
|
| 82 |
+
|
| 83 |
+
If ``mode=economic``, the shapes of Q and R are (M, K) and (K, N) instead
|
| 84 |
+
of (M,M) and (M,N), with ``K=min(M,N)``.
|
| 85 |
+
|
| 86 |
+
Examples
|
| 87 |
+
--------
|
| 88 |
+
>>> import numpy as np
|
| 89 |
+
>>> from scipy import linalg
|
| 90 |
+
>>> rng = np.random.default_rng()
|
| 91 |
+
>>> a = rng.standard_normal((9, 6))
|
| 92 |
+
|
| 93 |
+
>>> q, r = linalg.qr(a)
|
| 94 |
+
>>> np.allclose(a, np.dot(q, r))
|
| 95 |
+
True
|
| 96 |
+
>>> q.shape, r.shape
|
| 97 |
+
((9, 9), (9, 6))
|
| 98 |
+
|
| 99 |
+
>>> r2 = linalg.qr(a, mode='r')
|
| 100 |
+
>>> np.allclose(r, r2)
|
| 101 |
+
True
|
| 102 |
+
|
| 103 |
+
>>> q3, r3 = linalg.qr(a, mode='economic')
|
| 104 |
+
>>> q3.shape, r3.shape
|
| 105 |
+
((9, 6), (6, 6))
|
| 106 |
+
|
| 107 |
+
>>> q4, r4, p4 = linalg.qr(a, pivoting=True)
|
| 108 |
+
>>> d = np.abs(np.diag(r4))
|
| 109 |
+
>>> np.all(d[1:] <= d[:-1])
|
| 110 |
+
True
|
| 111 |
+
>>> np.allclose(a[:, p4], np.dot(q4, r4))
|
| 112 |
+
True
|
| 113 |
+
>>> q4.shape, r4.shape, p4.shape
|
| 114 |
+
((9, 9), (9, 6), (6,))
|
| 115 |
+
|
| 116 |
+
>>> q5, r5, p5 = linalg.qr(a, mode='economic', pivoting=True)
|
| 117 |
+
>>> q5.shape, r5.shape, p5.shape
|
| 118 |
+
((9, 6), (6, 6), (6,))
|
| 119 |
+
|
| 120 |
+
"""
|
| 121 |
+
# 'qr' was the old default, equivalent to 'full'. Neither 'full' nor
|
| 122 |
+
# 'qr' are used below.
|
| 123 |
+
# 'raw' is used internally by qr_multiply
|
| 124 |
+
if mode not in ['full', 'qr', 'r', 'economic', 'raw']:
|
| 125 |
+
raise ValueError("Mode argument should be one of ['full', 'r',"
|
| 126 |
+
"'economic', 'raw']")
|
| 127 |
+
|
| 128 |
+
if check_finite:
|
| 129 |
+
a1 = numpy.asarray_chkfinite(a)
|
| 130 |
+
else:
|
| 131 |
+
a1 = numpy.asarray(a)
|
| 132 |
+
if len(a1.shape) != 2:
|
| 133 |
+
raise ValueError("expected a 2-D array")
|
| 134 |
+
M, N = a1.shape
|
| 135 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 136 |
+
|
| 137 |
+
if pivoting:
|
| 138 |
+
geqp3, = get_lapack_funcs(('geqp3',), (a1,))
|
| 139 |
+
qr, jpvt, tau = safecall(geqp3, "geqp3", a1, overwrite_a=overwrite_a)
|
| 140 |
+
jpvt -= 1 # geqp3 returns a 1-based index array, so subtract 1
|
| 141 |
+
else:
|
| 142 |
+
geqrf, = get_lapack_funcs(('geqrf',), (a1,))
|
| 143 |
+
qr, tau = safecall(geqrf, "geqrf", a1, lwork=lwork,
|
| 144 |
+
overwrite_a=overwrite_a)
|
| 145 |
+
|
| 146 |
+
if mode not in ['economic', 'raw'] or M < N:
|
| 147 |
+
R = numpy.triu(qr)
|
| 148 |
+
else:
|
| 149 |
+
R = numpy.triu(qr[:N, :])
|
| 150 |
+
|
| 151 |
+
if pivoting:
|
| 152 |
+
Rj = R, jpvt
|
| 153 |
+
else:
|
| 154 |
+
Rj = R,
|
| 155 |
+
|
| 156 |
+
if mode == 'r':
|
| 157 |
+
return Rj
|
| 158 |
+
elif mode == 'raw':
|
| 159 |
+
return ((qr, tau),) + Rj
|
| 160 |
+
|
| 161 |
+
gor_un_gqr, = get_lapack_funcs(('orgqr',), (qr,))
|
| 162 |
+
|
| 163 |
+
if M < N:
|
| 164 |
+
Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qr[:, :M], tau,
|
| 165 |
+
lwork=lwork, overwrite_a=1)
|
| 166 |
+
elif mode == 'economic':
|
| 167 |
+
Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qr, tau, lwork=lwork,
|
| 168 |
+
overwrite_a=1)
|
| 169 |
+
else:
|
| 170 |
+
t = qr.dtype.char
|
| 171 |
+
qqr = numpy.empty((M, M), dtype=t)
|
| 172 |
+
qqr[:, :N] = qr
|
| 173 |
+
Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qqr, tau, lwork=lwork,
|
| 174 |
+
overwrite_a=1)
|
| 175 |
+
|
| 176 |
+
return (Q,) + Rj
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def qr_multiply(a, c, mode='right', pivoting=False, conjugate=False,
|
| 180 |
+
overwrite_a=False, overwrite_c=False):
|
| 181 |
+
"""
|
| 182 |
+
Calculate the QR decomposition and multiply Q with a matrix.
|
| 183 |
+
|
| 184 |
+
Calculate the decomposition ``A = Q R`` where Q is unitary/orthogonal
|
| 185 |
+
and R upper triangular. Multiply Q with a vector or a matrix c.
|
| 186 |
+
|
| 187 |
+
Parameters
|
| 188 |
+
----------
|
| 189 |
+
a : (M, N), array_like
|
| 190 |
+
Input array
|
| 191 |
+
c : array_like
|
| 192 |
+
Input array to be multiplied by ``q``.
|
| 193 |
+
mode : {'left', 'right'}, optional
|
| 194 |
+
``Q @ c`` is returned if mode is 'left', ``c @ Q`` is returned if
|
| 195 |
+
mode is 'right'.
|
| 196 |
+
The shape of c must be appropriate for the matrix multiplications,
|
| 197 |
+
if mode is 'left', ``min(a.shape) == c.shape[0]``,
|
| 198 |
+
if mode is 'right', ``a.shape[0] == c.shape[1]``.
|
| 199 |
+
pivoting : bool, optional
|
| 200 |
+
Whether or not factorization should include pivoting for rank-revealing
|
| 201 |
+
qr decomposition, see the documentation of qr.
|
| 202 |
+
conjugate : bool, optional
|
| 203 |
+
Whether Q should be complex-conjugated. This might be faster
|
| 204 |
+
than explicit conjugation.
|
| 205 |
+
overwrite_a : bool, optional
|
| 206 |
+
Whether data in a is overwritten (may improve performance)
|
| 207 |
+
overwrite_c : bool, optional
|
| 208 |
+
Whether data in c is overwritten (may improve performance).
|
| 209 |
+
If this is used, c must be big enough to keep the result,
|
| 210 |
+
i.e. ``c.shape[0]`` = ``a.shape[0]`` if mode is 'left'.
|
| 211 |
+
|
| 212 |
+
Returns
|
| 213 |
+
-------
|
| 214 |
+
CQ : ndarray
|
| 215 |
+
The product of ``Q`` and ``c``.
|
| 216 |
+
R : (K, N), ndarray
|
| 217 |
+
R array of the resulting QR factorization where ``K = min(M, N)``.
|
| 218 |
+
P : (N,) ndarray
|
| 219 |
+
Integer pivot array. Only returned when ``pivoting=True``.
|
| 220 |
+
|
| 221 |
+
Raises
|
| 222 |
+
------
|
| 223 |
+
LinAlgError
|
| 224 |
+
Raised if QR decomposition fails.
|
| 225 |
+
|
| 226 |
+
Notes
|
| 227 |
+
-----
|
| 228 |
+
This is an interface to the LAPACK routines ``?GEQRF``, ``?ORMQR``,
|
| 229 |
+
``?UNMQR``, and ``?GEQP3``.
|
| 230 |
+
|
| 231 |
+
.. versionadded:: 0.11.0
|
| 232 |
+
|
| 233 |
+
Examples
|
| 234 |
+
--------
|
| 235 |
+
>>> import numpy as np
|
| 236 |
+
>>> from scipy.linalg import qr_multiply, qr
|
| 237 |
+
>>> A = np.array([[1, 3, 3], [2, 3, 2], [2, 3, 3], [1, 3, 2]])
|
| 238 |
+
>>> qc, r1, piv1 = qr_multiply(A, 2*np.eye(4), pivoting=1)
|
| 239 |
+
>>> qc
|
| 240 |
+
array([[-1., 1., -1.],
|
| 241 |
+
[-1., -1., 1.],
|
| 242 |
+
[-1., -1., -1.],
|
| 243 |
+
[-1., 1., 1.]])
|
| 244 |
+
>>> r1
|
| 245 |
+
array([[-6., -3., -5. ],
|
| 246 |
+
[ 0., -1., -1.11022302e-16],
|
| 247 |
+
[ 0., 0., -1. ]])
|
| 248 |
+
>>> piv1
|
| 249 |
+
array([1, 0, 2], dtype=int32)
|
| 250 |
+
>>> q2, r2, piv2 = qr(A, mode='economic', pivoting=1)
|
| 251 |
+
>>> np.allclose(2*q2 - qc, np.zeros((4, 3)))
|
| 252 |
+
True
|
| 253 |
+
|
| 254 |
+
"""
|
| 255 |
+
if mode not in ['left', 'right']:
|
| 256 |
+
raise ValueError("Mode argument can only be 'left' or 'right' but "
|
| 257 |
+
f"not '{mode}'")
|
| 258 |
+
c = numpy.asarray_chkfinite(c)
|
| 259 |
+
if c.ndim < 2:
|
| 260 |
+
onedim = True
|
| 261 |
+
c = numpy.atleast_2d(c)
|
| 262 |
+
if mode == "left":
|
| 263 |
+
c = c.T
|
| 264 |
+
else:
|
| 265 |
+
onedim = False
|
| 266 |
+
|
| 267 |
+
a = numpy.atleast_2d(numpy.asarray(a)) # chkfinite done in qr
|
| 268 |
+
M, N = a.shape
|
| 269 |
+
|
| 270 |
+
if mode == 'left':
|
| 271 |
+
if c.shape[0] != min(M, N + overwrite_c*(M-N)):
|
| 272 |
+
raise ValueError('Array shapes are not compatible for Q @ c'
|
| 273 |
+
f' operation: {a.shape} vs {c.shape}')
|
| 274 |
+
else:
|
| 275 |
+
if M != c.shape[1]:
|
| 276 |
+
raise ValueError('Array shapes are not compatible for c @ Q'
|
| 277 |
+
f' operation: {c.shape} vs {a.shape}')
|
| 278 |
+
|
| 279 |
+
raw = qr(a, overwrite_a, None, "raw", pivoting)
|
| 280 |
+
Q, tau = raw[0]
|
| 281 |
+
|
| 282 |
+
gor_un_mqr, = get_lapack_funcs(('ormqr',), (Q,))
|
| 283 |
+
if gor_un_mqr.typecode in ('s', 'd'):
|
| 284 |
+
trans = "T"
|
| 285 |
+
else:
|
| 286 |
+
trans = "C"
|
| 287 |
+
|
| 288 |
+
Q = Q[:, :min(M, N)]
|
| 289 |
+
if M > N and mode == "left" and not overwrite_c:
|
| 290 |
+
if conjugate:
|
| 291 |
+
cc = numpy.zeros((c.shape[1], M), dtype=c.dtype, order="F")
|
| 292 |
+
cc[:, :N] = c.T
|
| 293 |
+
else:
|
| 294 |
+
cc = numpy.zeros((M, c.shape[1]), dtype=c.dtype, order="F")
|
| 295 |
+
cc[:N, :] = c
|
| 296 |
+
trans = "N"
|
| 297 |
+
if conjugate:
|
| 298 |
+
lr = "R"
|
| 299 |
+
else:
|
| 300 |
+
lr = "L"
|
| 301 |
+
overwrite_c = True
|
| 302 |
+
elif c.flags["C_CONTIGUOUS"] and trans == "T" or conjugate:
|
| 303 |
+
cc = c.T
|
| 304 |
+
if mode == "left":
|
| 305 |
+
lr = "R"
|
| 306 |
+
else:
|
| 307 |
+
lr = "L"
|
| 308 |
+
else:
|
| 309 |
+
trans = "N"
|
| 310 |
+
cc = c
|
| 311 |
+
if mode == "left":
|
| 312 |
+
lr = "L"
|
| 313 |
+
else:
|
| 314 |
+
lr = "R"
|
| 315 |
+
cQ, = safecall(gor_un_mqr, "gormqr/gunmqr", lr, trans, Q, tau, cc,
|
| 316 |
+
overwrite_c=overwrite_c)
|
| 317 |
+
if trans != "N":
|
| 318 |
+
cQ = cQ.T
|
| 319 |
+
if mode == "right":
|
| 320 |
+
cQ = cQ[:, :min(M, N)]
|
| 321 |
+
if onedim:
|
| 322 |
+
cQ = cQ.ravel()
|
| 323 |
+
|
| 324 |
+
return (cQ,) + raw[1:]
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
def rq(a, overwrite_a=False, lwork=None, mode='full', check_finite=True):
|
| 328 |
+
"""
|
| 329 |
+
Compute RQ decomposition of a matrix.
|
| 330 |
+
|
| 331 |
+
Calculate the decomposition ``A = R Q`` where Q is unitary/orthogonal
|
| 332 |
+
and R upper triangular.
|
| 333 |
+
|
| 334 |
+
Parameters
|
| 335 |
+
----------
|
| 336 |
+
a : (M, N) array_like
|
| 337 |
+
Matrix to be decomposed
|
| 338 |
+
overwrite_a : bool, optional
|
| 339 |
+
Whether data in a is overwritten (may improve performance)
|
| 340 |
+
lwork : int, optional
|
| 341 |
+
Work array size, lwork >= a.shape[1]. If None or -1, an optimal size
|
| 342 |
+
is computed.
|
| 343 |
+
mode : {'full', 'r', 'economic'}, optional
|
| 344 |
+
Determines what information is to be returned: either both Q and R
|
| 345 |
+
('full', default), only R ('r') or both Q and R but computed in
|
| 346 |
+
economy-size ('economic', see Notes).
|
| 347 |
+
check_finite : bool, optional
|
| 348 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 349 |
+
Disabling may give a performance gain, but may result in problems
|
| 350 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 351 |
+
|
| 352 |
+
Returns
|
| 353 |
+
-------
|
| 354 |
+
R : float or complex ndarray
|
| 355 |
+
Of shape (M, N) or (M, K) for ``mode='economic'``. ``K = min(M, N)``.
|
| 356 |
+
Q : float or complex ndarray
|
| 357 |
+
Of shape (N, N) or (K, N) for ``mode='economic'``. Not returned
|
| 358 |
+
if ``mode='r'``.
|
| 359 |
+
|
| 360 |
+
Raises
|
| 361 |
+
------
|
| 362 |
+
LinAlgError
|
| 363 |
+
If decomposition fails.
|
| 364 |
+
|
| 365 |
+
Notes
|
| 366 |
+
-----
|
| 367 |
+
This is an interface to the LAPACK routines sgerqf, dgerqf, cgerqf, zgerqf,
|
| 368 |
+
sorgrq, dorgrq, cungrq and zungrq.
|
| 369 |
+
|
| 370 |
+
If ``mode=economic``, the shapes of Q and R are (K, N) and (M, K) instead
|
| 371 |
+
of (N,N) and (M,N), with ``K=min(M,N)``.
|
| 372 |
+
|
| 373 |
+
Examples
|
| 374 |
+
--------
|
| 375 |
+
>>> import numpy as np
|
| 376 |
+
>>> from scipy import linalg
|
| 377 |
+
>>> rng = np.random.default_rng()
|
| 378 |
+
>>> a = rng.standard_normal((6, 9))
|
| 379 |
+
>>> r, q = linalg.rq(a)
|
| 380 |
+
>>> np.allclose(a, r @ q)
|
| 381 |
+
True
|
| 382 |
+
>>> r.shape, q.shape
|
| 383 |
+
((6, 9), (9, 9))
|
| 384 |
+
>>> r2 = linalg.rq(a, mode='r')
|
| 385 |
+
>>> np.allclose(r, r2)
|
| 386 |
+
True
|
| 387 |
+
>>> r3, q3 = linalg.rq(a, mode='economic')
|
| 388 |
+
>>> r3.shape, q3.shape
|
| 389 |
+
((6, 6), (6, 9))
|
| 390 |
+
|
| 391 |
+
"""
|
| 392 |
+
if mode not in ['full', 'r', 'economic']:
|
| 393 |
+
raise ValueError(
|
| 394 |
+
"Mode argument should be one of ['full', 'r', 'economic']")
|
| 395 |
+
|
| 396 |
+
if check_finite:
|
| 397 |
+
a1 = numpy.asarray_chkfinite(a)
|
| 398 |
+
else:
|
| 399 |
+
a1 = numpy.asarray(a)
|
| 400 |
+
if len(a1.shape) != 2:
|
| 401 |
+
raise ValueError('expected matrix')
|
| 402 |
+
M, N = a1.shape
|
| 403 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 404 |
+
|
| 405 |
+
gerqf, = get_lapack_funcs(('gerqf',), (a1,))
|
| 406 |
+
rq, tau = safecall(gerqf, 'gerqf', a1, lwork=lwork,
|
| 407 |
+
overwrite_a=overwrite_a)
|
| 408 |
+
if not mode == 'economic' or N < M:
|
| 409 |
+
R = numpy.triu(rq, N-M)
|
| 410 |
+
else:
|
| 411 |
+
R = numpy.triu(rq[-M:, -M:])
|
| 412 |
+
|
| 413 |
+
if mode == 'r':
|
| 414 |
+
return R
|
| 415 |
+
|
| 416 |
+
gor_un_grq, = get_lapack_funcs(('orgrq',), (rq,))
|
| 417 |
+
|
| 418 |
+
if N < M:
|
| 419 |
+
Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq[-N:], tau, lwork=lwork,
|
| 420 |
+
overwrite_a=1)
|
| 421 |
+
elif mode == 'economic':
|
| 422 |
+
Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq, tau, lwork=lwork,
|
| 423 |
+
overwrite_a=1)
|
| 424 |
+
else:
|
| 425 |
+
rq1 = numpy.empty((N, N), dtype=rq.dtype)
|
| 426 |
+
rq1[-M:] = rq
|
| 427 |
+
Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq1, tau, lwork=lwork,
|
| 428 |
+
overwrite_a=1)
|
| 429 |
+
|
| 430 |
+
return R, Q
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qz.py
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
from numpy import asarray_chkfinite
|
| 5 |
+
from ._misc import LinAlgError, _datacopied, LinAlgWarning
|
| 6 |
+
from .lapack import get_lapack_funcs
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
__all__ = ['qz', 'ordqz']
|
| 10 |
+
|
| 11 |
+
_double_precision = ['i', 'l', 'd']
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _select_function(sort):
|
| 15 |
+
if callable(sort):
|
| 16 |
+
# assume the user knows what they're doing
|
| 17 |
+
sfunction = sort
|
| 18 |
+
elif sort == 'lhp':
|
| 19 |
+
sfunction = _lhp
|
| 20 |
+
elif sort == 'rhp':
|
| 21 |
+
sfunction = _rhp
|
| 22 |
+
elif sort == 'iuc':
|
| 23 |
+
sfunction = _iuc
|
| 24 |
+
elif sort == 'ouc':
|
| 25 |
+
sfunction = _ouc
|
| 26 |
+
else:
|
| 27 |
+
raise ValueError("sort parameter must be None, a callable, or "
|
| 28 |
+
"one of ('lhp','rhp','iuc','ouc')")
|
| 29 |
+
|
| 30 |
+
return sfunction
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _lhp(x, y):
|
| 34 |
+
out = np.empty_like(x, dtype=bool)
|
| 35 |
+
nonzero = (y != 0)
|
| 36 |
+
# handles (x, y) = (0, 0) too
|
| 37 |
+
out[~nonzero] = False
|
| 38 |
+
out[nonzero] = (np.real(x[nonzero]/y[nonzero]) < 0.0)
|
| 39 |
+
return out
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def _rhp(x, y):
|
| 43 |
+
out = np.empty_like(x, dtype=bool)
|
| 44 |
+
nonzero = (y != 0)
|
| 45 |
+
# handles (x, y) = (0, 0) too
|
| 46 |
+
out[~nonzero] = False
|
| 47 |
+
out[nonzero] = (np.real(x[nonzero]/y[nonzero]) > 0.0)
|
| 48 |
+
return out
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def _iuc(x, y):
|
| 52 |
+
out = np.empty_like(x, dtype=bool)
|
| 53 |
+
nonzero = (y != 0)
|
| 54 |
+
# handles (x, y) = (0, 0) too
|
| 55 |
+
out[~nonzero] = False
|
| 56 |
+
out[nonzero] = (abs(x[nonzero]/y[nonzero]) < 1.0)
|
| 57 |
+
return out
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def _ouc(x, y):
|
| 61 |
+
out = np.empty_like(x, dtype=bool)
|
| 62 |
+
xzero = (x == 0)
|
| 63 |
+
yzero = (y == 0)
|
| 64 |
+
out[xzero & yzero] = False
|
| 65 |
+
out[~xzero & yzero] = True
|
| 66 |
+
out[~yzero] = (abs(x[~yzero]/y[~yzero]) > 1.0)
|
| 67 |
+
return out
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _qz(A, B, output='real', lwork=None, sort=None, overwrite_a=False,
|
| 71 |
+
overwrite_b=False, check_finite=True):
|
| 72 |
+
if sort is not None:
|
| 73 |
+
# Disabled due to segfaults on win32, see ticket 1717.
|
| 74 |
+
raise ValueError("The 'sort' input of qz() has to be None and will be "
|
| 75 |
+
"removed in a future release. Use ordqz instead.")
|
| 76 |
+
|
| 77 |
+
if output not in ['real', 'complex', 'r', 'c']:
|
| 78 |
+
raise ValueError("argument must be 'real', or 'complex'")
|
| 79 |
+
|
| 80 |
+
if check_finite:
|
| 81 |
+
a1 = asarray_chkfinite(A)
|
| 82 |
+
b1 = asarray_chkfinite(B)
|
| 83 |
+
else:
|
| 84 |
+
a1 = np.asarray(A)
|
| 85 |
+
b1 = np.asarray(B)
|
| 86 |
+
|
| 87 |
+
a_m, a_n = a1.shape
|
| 88 |
+
b_m, b_n = b1.shape
|
| 89 |
+
if not (a_m == a_n == b_m == b_n):
|
| 90 |
+
raise ValueError("Array dimensions must be square and agree")
|
| 91 |
+
|
| 92 |
+
typa = a1.dtype.char
|
| 93 |
+
if output in ['complex', 'c'] and typa not in ['F', 'D']:
|
| 94 |
+
if typa in _double_precision:
|
| 95 |
+
a1 = a1.astype('D')
|
| 96 |
+
typa = 'D'
|
| 97 |
+
else:
|
| 98 |
+
a1 = a1.astype('F')
|
| 99 |
+
typa = 'F'
|
| 100 |
+
typb = b1.dtype.char
|
| 101 |
+
if output in ['complex', 'c'] and typb not in ['F', 'D']:
|
| 102 |
+
if typb in _double_precision:
|
| 103 |
+
b1 = b1.astype('D')
|
| 104 |
+
typb = 'D'
|
| 105 |
+
else:
|
| 106 |
+
b1 = b1.astype('F')
|
| 107 |
+
typb = 'F'
|
| 108 |
+
|
| 109 |
+
overwrite_a = overwrite_a or (_datacopied(a1, A))
|
| 110 |
+
overwrite_b = overwrite_b or (_datacopied(b1, B))
|
| 111 |
+
|
| 112 |
+
gges, = get_lapack_funcs(('gges',), (a1, b1))
|
| 113 |
+
|
| 114 |
+
if lwork is None or lwork == -1:
|
| 115 |
+
# get optimal work array size
|
| 116 |
+
result = gges(lambda x: None, a1, b1, lwork=-1)
|
| 117 |
+
lwork = result[-2][0].real.astype(int)
|
| 118 |
+
|
| 119 |
+
def sfunction(x):
|
| 120 |
+
return None
|
| 121 |
+
result = gges(sfunction, a1, b1, lwork=lwork, overwrite_a=overwrite_a,
|
| 122 |
+
overwrite_b=overwrite_b, sort_t=0)
|
| 123 |
+
|
| 124 |
+
info = result[-1]
|
| 125 |
+
if info < 0:
|
| 126 |
+
raise ValueError(f"Illegal value in argument {-info} of gges")
|
| 127 |
+
elif info > 0 and info <= a_n:
|
| 128 |
+
warnings.warn("The QZ iteration failed. (a,b) are not in Schur "
|
| 129 |
+
"form, but ALPHAR(j), ALPHAI(j), and BETA(j) should be "
|
| 130 |
+
f"correct for J={info-1},...,N", LinAlgWarning,
|
| 131 |
+
stacklevel=3)
|
| 132 |
+
elif info == a_n+1:
|
| 133 |
+
raise LinAlgError("Something other than QZ iteration failed")
|
| 134 |
+
elif info == a_n+2:
|
| 135 |
+
raise LinAlgError("After reordering, roundoff changed values of some "
|
| 136 |
+
"complex eigenvalues so that leading eigenvalues "
|
| 137 |
+
"in the Generalized Schur form no longer satisfy "
|
| 138 |
+
"sort=True. This could also be due to scaling.")
|
| 139 |
+
elif info == a_n+3:
|
| 140 |
+
raise LinAlgError("Reordering failed in <s,d,c,z>tgsen")
|
| 141 |
+
|
| 142 |
+
return result, gges.typecode
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def qz(A, B, output='real', lwork=None, sort=None, overwrite_a=False,
|
| 146 |
+
overwrite_b=False, check_finite=True):
|
| 147 |
+
"""
|
| 148 |
+
QZ decomposition for generalized eigenvalues of a pair of matrices.
|
| 149 |
+
|
| 150 |
+
The QZ, or generalized Schur, decomposition for a pair of n-by-n
|
| 151 |
+
matrices (A,B) is::
|
| 152 |
+
|
| 153 |
+
(A,B) = (Q @ AA @ Z*, Q @ BB @ Z*)
|
| 154 |
+
|
| 155 |
+
where AA, BB is in generalized Schur form if BB is upper-triangular
|
| 156 |
+
with non-negative diagonal and AA is upper-triangular, or for real QZ
|
| 157 |
+
decomposition (``output='real'``) block upper triangular with 1x1
|
| 158 |
+
and 2x2 blocks. In this case, the 1x1 blocks correspond to real
|
| 159 |
+
generalized eigenvalues and 2x2 blocks are 'standardized' by making
|
| 160 |
+
the corresponding elements of BB have the form::
|
| 161 |
+
|
| 162 |
+
[ a 0 ]
|
| 163 |
+
[ 0 b ]
|
| 164 |
+
|
| 165 |
+
and the pair of corresponding 2x2 blocks in AA and BB will have a complex
|
| 166 |
+
conjugate pair of generalized eigenvalues. If (``output='complex'``) or
|
| 167 |
+
A and B are complex matrices, Z' denotes the conjugate-transpose of Z.
|
| 168 |
+
Q and Z are unitary matrices.
|
| 169 |
+
|
| 170 |
+
Parameters
|
| 171 |
+
----------
|
| 172 |
+
A : (N, N) array_like
|
| 173 |
+
2-D array to decompose
|
| 174 |
+
B : (N, N) array_like
|
| 175 |
+
2-D array to decompose
|
| 176 |
+
output : {'real', 'complex'}, optional
|
| 177 |
+
Construct the real or complex QZ decomposition for real matrices.
|
| 178 |
+
Default is 'real'.
|
| 179 |
+
lwork : int, optional
|
| 180 |
+
Work array size. If None or -1, it is automatically computed.
|
| 181 |
+
sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
|
| 182 |
+
NOTE: THIS INPUT IS DISABLED FOR NOW. Use ordqz instead.
|
| 183 |
+
|
| 184 |
+
Specifies whether the upper eigenvalues should be sorted. A callable
|
| 185 |
+
may be passed that, given a eigenvalue, returns a boolean denoting
|
| 186 |
+
whether the eigenvalue should be sorted to the top-left (True). For
|
| 187 |
+
real matrix pairs, the sort function takes three real arguments
|
| 188 |
+
(alphar, alphai, beta). The eigenvalue
|
| 189 |
+
``x = (alphar + alphai*1j)/beta``. For complex matrix pairs or
|
| 190 |
+
output='complex', the sort function takes two complex arguments
|
| 191 |
+
(alpha, beta). The eigenvalue ``x = (alpha/beta)``. Alternatively,
|
| 192 |
+
string parameters may be used:
|
| 193 |
+
|
| 194 |
+
- 'lhp' Left-hand plane (x.real < 0.0)
|
| 195 |
+
- 'rhp' Right-hand plane (x.real > 0.0)
|
| 196 |
+
- 'iuc' Inside the unit circle (x*x.conjugate() < 1.0)
|
| 197 |
+
- 'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
|
| 198 |
+
|
| 199 |
+
Defaults to None (no sorting).
|
| 200 |
+
overwrite_a : bool, optional
|
| 201 |
+
Whether to overwrite data in a (may improve performance)
|
| 202 |
+
overwrite_b : bool, optional
|
| 203 |
+
Whether to overwrite data in b (may improve performance)
|
| 204 |
+
check_finite : bool, optional
|
| 205 |
+
If true checks the elements of `A` and `B` are finite numbers. If
|
| 206 |
+
false does no checking and passes matrix through to
|
| 207 |
+
underlying algorithm.
|
| 208 |
+
|
| 209 |
+
Returns
|
| 210 |
+
-------
|
| 211 |
+
AA : (N, N) ndarray
|
| 212 |
+
Generalized Schur form of A.
|
| 213 |
+
BB : (N, N) ndarray
|
| 214 |
+
Generalized Schur form of B.
|
| 215 |
+
Q : (N, N) ndarray
|
| 216 |
+
The left Schur vectors.
|
| 217 |
+
Z : (N, N) ndarray
|
| 218 |
+
The right Schur vectors.
|
| 219 |
+
|
| 220 |
+
See Also
|
| 221 |
+
--------
|
| 222 |
+
ordqz
|
| 223 |
+
|
| 224 |
+
Notes
|
| 225 |
+
-----
|
| 226 |
+
Q is transposed versus the equivalent function in Matlab.
|
| 227 |
+
|
| 228 |
+
.. versionadded:: 0.11.0
|
| 229 |
+
|
| 230 |
+
Examples
|
| 231 |
+
--------
|
| 232 |
+
>>> import numpy as np
|
| 233 |
+
>>> from scipy.linalg import qz
|
| 234 |
+
|
| 235 |
+
>>> A = np.array([[1, 2, -1], [5, 5, 5], [2, 4, -8]])
|
| 236 |
+
>>> B = np.array([[1, 1, -3], [3, 1, -1], [5, 6, -2]])
|
| 237 |
+
|
| 238 |
+
Compute the decomposition. The QZ decomposition is not unique, so
|
| 239 |
+
depending on the underlying library that is used, there may be
|
| 240 |
+
differences in the signs of coefficients in the following output.
|
| 241 |
+
|
| 242 |
+
>>> AA, BB, Q, Z = qz(A, B)
|
| 243 |
+
>>> AA
|
| 244 |
+
array([[-1.36949157, -4.05459025, 7.44389431],
|
| 245 |
+
[ 0. , 7.65653432, 5.13476017],
|
| 246 |
+
[ 0. , -0.65978437, 2.4186015 ]]) # may vary
|
| 247 |
+
>>> BB
|
| 248 |
+
array([[ 1.71890633, -1.64723705, -0.72696385],
|
| 249 |
+
[ 0. , 8.6965692 , -0. ],
|
| 250 |
+
[ 0. , 0. , 2.27446233]]) # may vary
|
| 251 |
+
>>> Q
|
| 252 |
+
array([[-0.37048362, 0.1903278 , 0.90912992],
|
| 253 |
+
[-0.90073232, 0.16534124, -0.40167593],
|
| 254 |
+
[ 0.22676676, 0.96769706, -0.11017818]]) # may vary
|
| 255 |
+
>>> Z
|
| 256 |
+
array([[-0.67660785, 0.63528924, -0.37230283],
|
| 257 |
+
[ 0.70243299, 0.70853819, -0.06753907],
|
| 258 |
+
[ 0.22088393, -0.30721526, -0.92565062]]) # may vary
|
| 259 |
+
|
| 260 |
+
Verify the QZ decomposition. With real output, we only need the
|
| 261 |
+
transpose of ``Z`` in the following expressions.
|
| 262 |
+
|
| 263 |
+
>>> Q @ AA @ Z.T # Should be A
|
| 264 |
+
array([[ 1., 2., -1.],
|
| 265 |
+
[ 5., 5., 5.],
|
| 266 |
+
[ 2., 4., -8.]])
|
| 267 |
+
>>> Q @ BB @ Z.T # Should be B
|
| 268 |
+
array([[ 1., 1., -3.],
|
| 269 |
+
[ 3., 1., -1.],
|
| 270 |
+
[ 5., 6., -2.]])
|
| 271 |
+
|
| 272 |
+
Repeat the decomposition, but with ``output='complex'``.
|
| 273 |
+
|
| 274 |
+
>>> AA, BB, Q, Z = qz(A, B, output='complex')
|
| 275 |
+
|
| 276 |
+
For conciseness in the output, we use ``np.set_printoptions()`` to set
|
| 277 |
+
the output precision of NumPy arrays to 3 and display tiny values as 0.
|
| 278 |
+
|
| 279 |
+
>>> np.set_printoptions(precision=3, suppress=True)
|
| 280 |
+
>>> AA
|
| 281 |
+
array([[-1.369+0.j , 2.248+4.237j, 4.861-5.022j],
|
| 282 |
+
[ 0. +0.j , 7.037+2.922j, 0.794+4.932j],
|
| 283 |
+
[ 0. +0.j , 0. +0.j , 2.655-1.103j]]) # may vary
|
| 284 |
+
>>> BB
|
| 285 |
+
array([[ 1.719+0.j , -1.115+1.j , -0.763-0.646j],
|
| 286 |
+
[ 0. +0.j , 7.24 +0.j , -3.144+3.322j],
|
| 287 |
+
[ 0. +0.j , 0. +0.j , 2.732+0.j ]]) # may vary
|
| 288 |
+
>>> Q
|
| 289 |
+
array([[ 0.326+0.175j, -0.273-0.029j, -0.886-0.052j],
|
| 290 |
+
[ 0.794+0.426j, -0.093+0.134j, 0.402-0.02j ],
|
| 291 |
+
[-0.2 -0.107j, -0.816+0.482j, 0.151-0.167j]]) # may vary
|
| 292 |
+
>>> Z
|
| 293 |
+
array([[ 0.596+0.32j , -0.31 +0.414j, 0.393-0.347j],
|
| 294 |
+
[-0.619-0.332j, -0.479+0.314j, 0.154-0.393j],
|
| 295 |
+
[-0.195-0.104j, 0.576+0.27j , 0.715+0.187j]]) # may vary
|
| 296 |
+
|
| 297 |
+
With complex arrays, we must use ``Z.conj().T`` in the following
|
| 298 |
+
expressions to verify the decomposition.
|
| 299 |
+
|
| 300 |
+
>>> Q @ AA @ Z.conj().T # Should be A
|
| 301 |
+
array([[ 1.-0.j, 2.-0.j, -1.-0.j],
|
| 302 |
+
[ 5.+0.j, 5.+0.j, 5.-0.j],
|
| 303 |
+
[ 2.+0.j, 4.+0.j, -8.+0.j]])
|
| 304 |
+
>>> Q @ BB @ Z.conj().T # Should be B
|
| 305 |
+
array([[ 1.+0.j, 1.+0.j, -3.+0.j],
|
| 306 |
+
[ 3.-0.j, 1.-0.j, -1.+0.j],
|
| 307 |
+
[ 5.+0.j, 6.+0.j, -2.+0.j]])
|
| 308 |
+
|
| 309 |
+
"""
|
| 310 |
+
# output for real
|
| 311 |
+
# AA, BB, sdim, alphar, alphai, beta, vsl, vsr, work, info
|
| 312 |
+
# output for complex
|
| 313 |
+
# AA, BB, sdim, alpha, beta, vsl, vsr, work, info
|
| 314 |
+
result, _ = _qz(A, B, output=output, lwork=lwork, sort=sort,
|
| 315 |
+
overwrite_a=overwrite_a, overwrite_b=overwrite_b,
|
| 316 |
+
check_finite=check_finite)
|
| 317 |
+
return result[0], result[1], result[-4], result[-3]
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
def ordqz(A, B, sort='lhp', output='real', overwrite_a=False,
|
| 321 |
+
overwrite_b=False, check_finite=True):
|
| 322 |
+
"""QZ decomposition for a pair of matrices with reordering.
|
| 323 |
+
|
| 324 |
+
Parameters
|
| 325 |
+
----------
|
| 326 |
+
A : (N, N) array_like
|
| 327 |
+
2-D array to decompose
|
| 328 |
+
B : (N, N) array_like
|
| 329 |
+
2-D array to decompose
|
| 330 |
+
sort : {callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
|
| 331 |
+
Specifies whether the upper eigenvalues should be sorted. A
|
| 332 |
+
callable may be passed that, given an ordered pair ``(alpha,
|
| 333 |
+
beta)`` representing the eigenvalue ``x = (alpha/beta)``,
|
| 334 |
+
returns a boolean denoting whether the eigenvalue should be
|
| 335 |
+
sorted to the top-left (True). For the real matrix pairs
|
| 336 |
+
``beta`` is real while ``alpha`` can be complex, and for
|
| 337 |
+
complex matrix pairs both ``alpha`` and ``beta`` can be
|
| 338 |
+
complex. The callable must be able to accept a NumPy
|
| 339 |
+
array. Alternatively, string parameters may be used:
|
| 340 |
+
|
| 341 |
+
- 'lhp' Left-hand plane (x.real < 0.0)
|
| 342 |
+
- 'rhp' Right-hand plane (x.real > 0.0)
|
| 343 |
+
- 'iuc' Inside the unit circle (x*x.conjugate() < 1.0)
|
| 344 |
+
- 'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
|
| 345 |
+
|
| 346 |
+
With the predefined sorting functions, an infinite eigenvalue
|
| 347 |
+
(i.e., ``alpha != 0`` and ``beta = 0``) is considered to lie in
|
| 348 |
+
neither the left-hand nor the right-hand plane, but it is
|
| 349 |
+
considered to lie outside the unit circle. For the eigenvalue
|
| 350 |
+
``(alpha, beta) = (0, 0)``, the predefined sorting functions
|
| 351 |
+
all return `False`.
|
| 352 |
+
output : str {'real','complex'}, optional
|
| 353 |
+
Construct the real or complex QZ decomposition for real matrices.
|
| 354 |
+
Default is 'real'.
|
| 355 |
+
overwrite_a : bool, optional
|
| 356 |
+
If True, the contents of A are overwritten.
|
| 357 |
+
overwrite_b : bool, optional
|
| 358 |
+
If True, the contents of B are overwritten.
|
| 359 |
+
check_finite : bool, optional
|
| 360 |
+
If true checks the elements of `A` and `B` are finite numbers. If
|
| 361 |
+
false does no checking and passes matrix through to
|
| 362 |
+
underlying algorithm.
|
| 363 |
+
|
| 364 |
+
Returns
|
| 365 |
+
-------
|
| 366 |
+
AA : (N, N) ndarray
|
| 367 |
+
Generalized Schur form of A.
|
| 368 |
+
BB : (N, N) ndarray
|
| 369 |
+
Generalized Schur form of B.
|
| 370 |
+
alpha : (N,) ndarray
|
| 371 |
+
alpha = alphar + alphai * 1j. See notes.
|
| 372 |
+
beta : (N,) ndarray
|
| 373 |
+
See notes.
|
| 374 |
+
Q : (N, N) ndarray
|
| 375 |
+
The left Schur vectors.
|
| 376 |
+
Z : (N, N) ndarray
|
| 377 |
+
The right Schur vectors.
|
| 378 |
+
|
| 379 |
+
See Also
|
| 380 |
+
--------
|
| 381 |
+
qz
|
| 382 |
+
|
| 383 |
+
Notes
|
| 384 |
+
-----
|
| 385 |
+
On exit, ``(ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N``, will be the
|
| 386 |
+
generalized eigenvalues. ``ALPHAR(j) + ALPHAI(j)*i`` and
|
| 387 |
+
``BETA(j),j=1,...,N`` are the diagonals of the complex Schur form (S,T)
|
| 388 |
+
that would result if the 2-by-2 diagonal blocks of the real generalized
|
| 389 |
+
Schur form of (A,B) were further reduced to triangular form using complex
|
| 390 |
+
unitary transformations. If ALPHAI(j) is zero, then the jth eigenvalue is
|
| 391 |
+
real; if positive, then the ``j``\\ th and ``(j+1)``\\ st eigenvalues are a
|
| 392 |
+
complex conjugate pair, with ``ALPHAI(j+1)`` negative.
|
| 393 |
+
|
| 394 |
+
.. versionadded:: 0.17.0
|
| 395 |
+
|
| 396 |
+
Examples
|
| 397 |
+
--------
|
| 398 |
+
>>> import numpy as np
|
| 399 |
+
>>> from scipy.linalg import ordqz
|
| 400 |
+
>>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
|
| 401 |
+
>>> B = np.array([[0, 6, 0, 0], [5, 0, 2, 1], [5, 2, 6, 6], [4, 7, 7, 7]])
|
| 402 |
+
>>> AA, BB, alpha, beta, Q, Z = ordqz(A, B, sort='lhp')
|
| 403 |
+
|
| 404 |
+
Since we have sorted for left half plane eigenvalues, negatives come first
|
| 405 |
+
|
| 406 |
+
>>> (alpha/beta).real < 0
|
| 407 |
+
array([ True, True, False, False], dtype=bool)
|
| 408 |
+
|
| 409 |
+
"""
|
| 410 |
+
(AA, BB, _, *ab, Q, Z, _, _), typ = _qz(A, B, output=output, sort=None,
|
| 411 |
+
overwrite_a=overwrite_a,
|
| 412 |
+
overwrite_b=overwrite_b,
|
| 413 |
+
check_finite=check_finite)
|
| 414 |
+
|
| 415 |
+
if typ == 's':
|
| 416 |
+
alpha, beta = ab[0] + ab[1]*np.complex64(1j), ab[2]
|
| 417 |
+
elif typ == 'd':
|
| 418 |
+
alpha, beta = ab[0] + ab[1]*1.j, ab[2]
|
| 419 |
+
else:
|
| 420 |
+
alpha, beta = ab
|
| 421 |
+
|
| 422 |
+
sfunction = _select_function(sort)
|
| 423 |
+
select = sfunction(alpha, beta)
|
| 424 |
+
|
| 425 |
+
tgsen = get_lapack_funcs('tgsen', (AA, BB))
|
| 426 |
+
# the real case needs 4n + 16 lwork
|
| 427 |
+
lwork = 4*AA.shape[0] + 16 if typ in 'sd' else 1
|
| 428 |
+
AAA, BBB, *ab, QQ, ZZ, _, _, _, _, info = tgsen(select, AA, BB, Q, Z,
|
| 429 |
+
ijob=0,
|
| 430 |
+
lwork=lwork, liwork=1)
|
| 431 |
+
|
| 432 |
+
# Once more for tgsen output
|
| 433 |
+
if typ == 's':
|
| 434 |
+
alpha, beta = ab[0] + ab[1]*np.complex64(1j), ab[2]
|
| 435 |
+
elif typ == 'd':
|
| 436 |
+
alpha, beta = ab[0] + ab[1]*1.j, ab[2]
|
| 437 |
+
else:
|
| 438 |
+
alpha, beta = ab
|
| 439 |
+
|
| 440 |
+
if info < 0:
|
| 441 |
+
raise ValueError(f"Illegal value in argument {-info} of tgsen")
|
| 442 |
+
elif info == 1:
|
| 443 |
+
raise ValueError("Reordering of (A, B) failed because the transformed"
|
| 444 |
+
" matrix pair (A, B) would be too far from "
|
| 445 |
+
"generalized Schur form; the problem is very "
|
| 446 |
+
"ill-conditioned. (A, B) may have been partially "
|
| 447 |
+
"reordered.")
|
| 448 |
+
|
| 449 |
+
return AAA, BBB, alpha, beta, QQ, ZZ
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_schur.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Schur decomposition functions."""
|
| 2 |
+
import numpy
|
| 3 |
+
from numpy import asarray_chkfinite, single, asarray, array
|
| 4 |
+
from numpy.linalg import norm
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
# Local imports.
|
| 8 |
+
from ._misc import LinAlgError, _datacopied
|
| 9 |
+
from .lapack import get_lapack_funcs
|
| 10 |
+
from ._decomp import eigvals
|
| 11 |
+
|
| 12 |
+
__all__ = ['schur', 'rsf2csf']
|
| 13 |
+
|
| 14 |
+
_double_precision = ['i', 'l', 'd']
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def schur(a, output='real', lwork=None, overwrite_a=False, sort=None,
|
| 18 |
+
check_finite=True):
|
| 19 |
+
"""
|
| 20 |
+
Compute Schur decomposition of a matrix.
|
| 21 |
+
|
| 22 |
+
The Schur decomposition is::
|
| 23 |
+
|
| 24 |
+
A = Z T Z^H
|
| 25 |
+
|
| 26 |
+
where Z is unitary and T is either upper-triangular, or for real
|
| 27 |
+
Schur decomposition (output='real'), quasi-upper triangular. In
|
| 28 |
+
the quasi-triangular form, 2x2 blocks describing complex-valued
|
| 29 |
+
eigenvalue pairs may extrude from the diagonal.
|
| 30 |
+
|
| 31 |
+
Parameters
|
| 32 |
+
----------
|
| 33 |
+
a : (M, M) array_like
|
| 34 |
+
Matrix to decompose
|
| 35 |
+
output : {'real', 'complex'}, optional
|
| 36 |
+
Construct the real or complex Schur decomposition (for real matrices).
|
| 37 |
+
lwork : int, optional
|
| 38 |
+
Work array size. If None or -1, it is automatically computed.
|
| 39 |
+
overwrite_a : bool, optional
|
| 40 |
+
Whether to overwrite data in a (may improve performance).
|
| 41 |
+
sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
|
| 42 |
+
Specifies whether the upper eigenvalues should be sorted. A callable
|
| 43 |
+
may be passed that, given a eigenvalue, returns a boolean denoting
|
| 44 |
+
whether the eigenvalue should be sorted to the top-left (True).
|
| 45 |
+
Alternatively, string parameters may be used::
|
| 46 |
+
|
| 47 |
+
'lhp' Left-hand plane (x.real < 0.0)
|
| 48 |
+
'rhp' Right-hand plane (x.real > 0.0)
|
| 49 |
+
'iuc' Inside the unit circle (x*x.conjugate() <= 1.0)
|
| 50 |
+
'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
|
| 51 |
+
|
| 52 |
+
Defaults to None (no sorting).
|
| 53 |
+
check_finite : bool, optional
|
| 54 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 55 |
+
Disabling may give a performance gain, but may result in problems
|
| 56 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 57 |
+
|
| 58 |
+
Returns
|
| 59 |
+
-------
|
| 60 |
+
T : (M, M) ndarray
|
| 61 |
+
Schur form of A. It is real-valued for the real Schur decomposition.
|
| 62 |
+
Z : (M, M) ndarray
|
| 63 |
+
An unitary Schur transformation matrix for A.
|
| 64 |
+
It is real-valued for the real Schur decomposition.
|
| 65 |
+
sdim : int
|
| 66 |
+
If and only if sorting was requested, a third return value will
|
| 67 |
+
contain the number of eigenvalues satisfying the sort condition.
|
| 68 |
+
|
| 69 |
+
Raises
|
| 70 |
+
------
|
| 71 |
+
LinAlgError
|
| 72 |
+
Error raised under three conditions:
|
| 73 |
+
|
| 74 |
+
1. The algorithm failed due to a failure of the QR algorithm to
|
| 75 |
+
compute all eigenvalues.
|
| 76 |
+
2. If eigenvalue sorting was requested, the eigenvalues could not be
|
| 77 |
+
reordered due to a failure to separate eigenvalues, usually because
|
| 78 |
+
of poor conditioning.
|
| 79 |
+
3. If eigenvalue sorting was requested, roundoff errors caused the
|
| 80 |
+
leading eigenvalues to no longer satisfy the sorting condition.
|
| 81 |
+
|
| 82 |
+
See Also
|
| 83 |
+
--------
|
| 84 |
+
rsf2csf : Convert real Schur form to complex Schur form
|
| 85 |
+
|
| 86 |
+
Examples
|
| 87 |
+
--------
|
| 88 |
+
>>> import numpy as np
|
| 89 |
+
>>> from scipy.linalg import schur, eigvals
|
| 90 |
+
>>> A = np.array([[0, 2, 2], [0, 1, 2], [1, 0, 1]])
|
| 91 |
+
>>> T, Z = schur(A)
|
| 92 |
+
>>> T
|
| 93 |
+
array([[ 2.65896708, 1.42440458, -1.92933439],
|
| 94 |
+
[ 0. , -0.32948354, -0.49063704],
|
| 95 |
+
[ 0. , 1.31178921, -0.32948354]])
|
| 96 |
+
>>> Z
|
| 97 |
+
array([[0.72711591, -0.60156188, 0.33079564],
|
| 98 |
+
[0.52839428, 0.79801892, 0.28976765],
|
| 99 |
+
[0.43829436, 0.03590414, -0.89811411]])
|
| 100 |
+
|
| 101 |
+
>>> T2, Z2 = schur(A, output='complex')
|
| 102 |
+
>>> T2
|
| 103 |
+
array([[ 2.65896708, -1.22839825+1.32378589j, 0.42590089+1.51937378j], # may vary
|
| 104 |
+
[ 0. , -0.32948354+0.80225456j, -0.59877807+0.56192146j],
|
| 105 |
+
[ 0. , 0. , -0.32948354-0.80225456j]])
|
| 106 |
+
>>> eigvals(T2)
|
| 107 |
+
array([2.65896708, -0.32948354+0.80225456j, -0.32948354-0.80225456j])
|
| 108 |
+
|
| 109 |
+
An arbitrary custom eig-sorting condition, having positive imaginary part,
|
| 110 |
+
which is satisfied by only one eigenvalue
|
| 111 |
+
|
| 112 |
+
>>> T3, Z3, sdim = schur(A, output='complex', sort=lambda x: x.imag > 0)
|
| 113 |
+
>>> sdim
|
| 114 |
+
1
|
| 115 |
+
|
| 116 |
+
"""
|
| 117 |
+
if output not in ['real', 'complex', 'r', 'c']:
|
| 118 |
+
raise ValueError("argument must be 'real', or 'complex'")
|
| 119 |
+
if check_finite:
|
| 120 |
+
a1 = asarray_chkfinite(a)
|
| 121 |
+
else:
|
| 122 |
+
a1 = asarray(a)
|
| 123 |
+
if numpy.issubdtype(a1.dtype, numpy.integer):
|
| 124 |
+
a1 = asarray(a, dtype=numpy.dtype("long"))
|
| 125 |
+
if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]):
|
| 126 |
+
raise ValueError('expected square matrix')
|
| 127 |
+
typ = a1.dtype.char
|
| 128 |
+
if output in ['complex', 'c'] and typ not in ['F', 'D']:
|
| 129 |
+
if typ in _double_precision:
|
| 130 |
+
a1 = a1.astype('D')
|
| 131 |
+
typ = 'D'
|
| 132 |
+
else:
|
| 133 |
+
a1 = a1.astype('F')
|
| 134 |
+
typ = 'F'
|
| 135 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 136 |
+
gees, = get_lapack_funcs(('gees',), (a1,))
|
| 137 |
+
if lwork is None or lwork == -1:
|
| 138 |
+
# get optimal work array
|
| 139 |
+
result = gees(lambda x: None, a1, lwork=-1)
|
| 140 |
+
lwork = result[-2][0].real.astype(numpy.int_)
|
| 141 |
+
|
| 142 |
+
if sort is None:
|
| 143 |
+
sort_t = 0
|
| 144 |
+
def sfunction(x):
|
| 145 |
+
return None
|
| 146 |
+
else:
|
| 147 |
+
sort_t = 1
|
| 148 |
+
if callable(sort):
|
| 149 |
+
sfunction = sort
|
| 150 |
+
elif sort == 'lhp':
|
| 151 |
+
def sfunction(x):
|
| 152 |
+
return x.real < 0.0
|
| 153 |
+
elif sort == 'rhp':
|
| 154 |
+
def sfunction(x):
|
| 155 |
+
return x.real >= 0.0
|
| 156 |
+
elif sort == 'iuc':
|
| 157 |
+
def sfunction(x):
|
| 158 |
+
return abs(x) <= 1.0
|
| 159 |
+
elif sort == 'ouc':
|
| 160 |
+
def sfunction(x):
|
| 161 |
+
return abs(x) > 1.0
|
| 162 |
+
else:
|
| 163 |
+
raise ValueError("'sort' parameter must either be 'None', or a "
|
| 164 |
+
"callable, or one of ('lhp','rhp','iuc','ouc')")
|
| 165 |
+
|
| 166 |
+
result = gees(sfunction, a1, lwork=lwork, overwrite_a=overwrite_a,
|
| 167 |
+
sort_t=sort_t)
|
| 168 |
+
|
| 169 |
+
info = result[-1]
|
| 170 |
+
if info < 0:
|
| 171 |
+
raise ValueError(f'illegal value in {-info}-th argument of internal gees')
|
| 172 |
+
elif info == a1.shape[0] + 1:
|
| 173 |
+
raise LinAlgError('Eigenvalues could not be separated for reordering.')
|
| 174 |
+
elif info == a1.shape[0] + 2:
|
| 175 |
+
raise LinAlgError('Leading eigenvalues do not satisfy sort condition.')
|
| 176 |
+
elif info > 0:
|
| 177 |
+
raise LinAlgError("Schur form not found. Possibly ill-conditioned.")
|
| 178 |
+
|
| 179 |
+
if sort_t == 0:
|
| 180 |
+
return result[0], result[-3]
|
| 181 |
+
else:
|
| 182 |
+
return result[0], result[-3], result[1]
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
eps = numpy.finfo(float).eps
|
| 186 |
+
feps = numpy.finfo(single).eps
|
| 187 |
+
|
| 188 |
+
_array_kind = {'b': 0, 'h': 0, 'B': 0, 'i': 0, 'l': 0,
|
| 189 |
+
'f': 0, 'd': 0, 'F': 1, 'D': 1}
|
| 190 |
+
_array_precision = {'i': 1, 'l': 1, 'f': 0, 'd': 1, 'F': 0, 'D': 1}
|
| 191 |
+
_array_type = [['f', 'd'], ['F', 'D']]
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
def _commonType(*arrays):
|
| 195 |
+
kind = 0
|
| 196 |
+
precision = 0
|
| 197 |
+
for a in arrays:
|
| 198 |
+
t = a.dtype.char
|
| 199 |
+
kind = max(kind, _array_kind[t])
|
| 200 |
+
precision = max(precision, _array_precision[t])
|
| 201 |
+
return _array_type[kind][precision]
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def _castCopy(type, *arrays):
|
| 205 |
+
cast_arrays = ()
|
| 206 |
+
for a in arrays:
|
| 207 |
+
if a.dtype.char == type:
|
| 208 |
+
cast_arrays = cast_arrays + (a.copy(),)
|
| 209 |
+
else:
|
| 210 |
+
cast_arrays = cast_arrays + (a.astype(type),)
|
| 211 |
+
if len(cast_arrays) == 1:
|
| 212 |
+
return cast_arrays[0]
|
| 213 |
+
else:
|
| 214 |
+
return cast_arrays
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
def rsf2csf(T, Z, check_finite=True):
|
| 218 |
+
"""
|
| 219 |
+
Convert real Schur form to complex Schur form.
|
| 220 |
+
|
| 221 |
+
Convert a quasi-diagonal real-valued Schur form to the upper-triangular
|
| 222 |
+
complex-valued Schur form.
|
| 223 |
+
|
| 224 |
+
Parameters
|
| 225 |
+
----------
|
| 226 |
+
T : (M, M) array_like
|
| 227 |
+
Real Schur form of the original array
|
| 228 |
+
Z : (M, M) array_like
|
| 229 |
+
Schur transformation matrix
|
| 230 |
+
check_finite : bool, optional
|
| 231 |
+
Whether to check that the input arrays contain only finite numbers.
|
| 232 |
+
Disabling may give a performance gain, but may result in problems
|
| 233 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 234 |
+
|
| 235 |
+
Returns
|
| 236 |
+
-------
|
| 237 |
+
T : (M, M) ndarray
|
| 238 |
+
Complex Schur form of the original array
|
| 239 |
+
Z : (M, M) ndarray
|
| 240 |
+
Schur transformation matrix corresponding to the complex form
|
| 241 |
+
|
| 242 |
+
See Also
|
| 243 |
+
--------
|
| 244 |
+
schur : Schur decomposition of an array
|
| 245 |
+
|
| 246 |
+
Examples
|
| 247 |
+
--------
|
| 248 |
+
>>> import numpy as np
|
| 249 |
+
>>> from scipy.linalg import schur, rsf2csf
|
| 250 |
+
>>> A = np.array([[0, 2, 2], [0, 1, 2], [1, 0, 1]])
|
| 251 |
+
>>> T, Z = schur(A)
|
| 252 |
+
>>> T
|
| 253 |
+
array([[ 2.65896708, 1.42440458, -1.92933439],
|
| 254 |
+
[ 0. , -0.32948354, -0.49063704],
|
| 255 |
+
[ 0. , 1.31178921, -0.32948354]])
|
| 256 |
+
>>> Z
|
| 257 |
+
array([[0.72711591, -0.60156188, 0.33079564],
|
| 258 |
+
[0.52839428, 0.79801892, 0.28976765],
|
| 259 |
+
[0.43829436, 0.03590414, -0.89811411]])
|
| 260 |
+
>>> T2 , Z2 = rsf2csf(T, Z)
|
| 261 |
+
>>> T2
|
| 262 |
+
array([[2.65896708+0.j, -1.64592781+0.743164187j, -1.21516887+1.00660462j],
|
| 263 |
+
[0.+0.j , -0.32948354+8.02254558e-01j, -0.82115218-2.77555756e-17j],
|
| 264 |
+
[0.+0.j , 0.+0.j, -0.32948354-0.802254558j]])
|
| 265 |
+
>>> Z2
|
| 266 |
+
array([[0.72711591+0.j, 0.28220393-0.31385693j, 0.51319638-0.17258824j],
|
| 267 |
+
[0.52839428+0.j, 0.24720268+0.41635578j, -0.68079517-0.15118243j],
|
| 268 |
+
[0.43829436+0.j, -0.76618703+0.01873251j, -0.03063006+0.46857912j]])
|
| 269 |
+
|
| 270 |
+
"""
|
| 271 |
+
if check_finite:
|
| 272 |
+
Z, T = map(asarray_chkfinite, (Z, T))
|
| 273 |
+
else:
|
| 274 |
+
Z, T = map(asarray, (Z, T))
|
| 275 |
+
|
| 276 |
+
for ind, X in enumerate([Z, T]):
|
| 277 |
+
if X.ndim != 2 or X.shape[0] != X.shape[1]:
|
| 278 |
+
raise ValueError("Input '{}' must be square.".format('ZT'[ind]))
|
| 279 |
+
|
| 280 |
+
if T.shape[0] != Z.shape[0]:
|
| 281 |
+
message = f"Input array shapes must match: Z: {Z.shape} vs. T: {T.shape}"
|
| 282 |
+
raise ValueError(message)
|
| 283 |
+
N = T.shape[0]
|
| 284 |
+
t = _commonType(Z, T, array([3.0], 'F'))
|
| 285 |
+
Z, T = _castCopy(t, Z, T)
|
| 286 |
+
|
| 287 |
+
for m in range(N-1, 0, -1):
|
| 288 |
+
if abs(T[m, m-1]) > eps*(abs(T[m-1, m-1]) + abs(T[m, m])):
|
| 289 |
+
mu = eigvals(T[m-1:m+1, m-1:m+1]) - T[m, m]
|
| 290 |
+
r = norm([mu[0], T[m, m-1]])
|
| 291 |
+
c = mu[0] / r
|
| 292 |
+
s = T[m, m-1] / r
|
| 293 |
+
G = array([[c.conj(), s], [-s, c]], dtype=t)
|
| 294 |
+
|
| 295 |
+
T[m-1:m+1, m-1:] = G.dot(T[m-1:m+1, m-1:])
|
| 296 |
+
T[:m+1, m-1:m+1] = T[:m+1, m-1:m+1].dot(G.conj().T)
|
| 297 |
+
Z[:, m-1:m+1] = Z[:, m-1:m+1].dot(G.conj().T)
|
| 298 |
+
|
| 299 |
+
T[m, m-1] = 0.0
|
| 300 |
+
return T, Z
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_svd.py
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""SVD decomposition functions."""
|
| 2 |
+
import numpy
|
| 3 |
+
from numpy import zeros, r_, diag, dot, arccos, arcsin, where, clip
|
| 4 |
+
|
| 5 |
+
# Local imports.
|
| 6 |
+
from ._misc import LinAlgError, _datacopied
|
| 7 |
+
from .lapack import get_lapack_funcs, _compute_lwork
|
| 8 |
+
from ._decomp import _asarray_validated
|
| 9 |
+
|
| 10 |
+
__all__ = ['svd', 'svdvals', 'diagsvd', 'orth', 'subspace_angles', 'null_space']
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False,
|
| 14 |
+
check_finite=True, lapack_driver='gesdd'):
|
| 15 |
+
"""
|
| 16 |
+
Singular Value Decomposition.
|
| 17 |
+
|
| 18 |
+
Factorizes the matrix `a` into two unitary matrices ``U`` and ``Vh``, and
|
| 19 |
+
a 1-D array ``s`` of singular values (real, non-negative) such that
|
| 20 |
+
``a == U @ S @ Vh``, where ``S`` is a suitably shaped matrix of zeros with
|
| 21 |
+
main diagonal ``s``.
|
| 22 |
+
|
| 23 |
+
Parameters
|
| 24 |
+
----------
|
| 25 |
+
a : (M, N) array_like
|
| 26 |
+
Matrix to decompose.
|
| 27 |
+
full_matrices : bool, optional
|
| 28 |
+
If True (default), `U` and `Vh` are of shape ``(M, M)``, ``(N, N)``.
|
| 29 |
+
If False, the shapes are ``(M, K)`` and ``(K, N)``, where
|
| 30 |
+
``K = min(M, N)``.
|
| 31 |
+
compute_uv : bool, optional
|
| 32 |
+
Whether to compute also ``U`` and ``Vh`` in addition to ``s``.
|
| 33 |
+
Default is True.
|
| 34 |
+
overwrite_a : bool, optional
|
| 35 |
+
Whether to overwrite `a`; may improve performance.
|
| 36 |
+
Default is False.
|
| 37 |
+
check_finite : bool, optional
|
| 38 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 39 |
+
Disabling may give a performance gain, but may result in problems
|
| 40 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 41 |
+
lapack_driver : {'gesdd', 'gesvd'}, optional
|
| 42 |
+
Whether to use the more efficient divide-and-conquer approach
|
| 43 |
+
(``'gesdd'``) or general rectangular approach (``'gesvd'``)
|
| 44 |
+
to compute the SVD. MATLAB and Octave use the ``'gesvd'`` approach.
|
| 45 |
+
Default is ``'gesdd'``.
|
| 46 |
+
|
| 47 |
+
.. versionadded:: 0.18
|
| 48 |
+
|
| 49 |
+
Returns
|
| 50 |
+
-------
|
| 51 |
+
U : ndarray
|
| 52 |
+
Unitary matrix having left singular vectors as columns.
|
| 53 |
+
Of shape ``(M, M)`` or ``(M, K)``, depending on `full_matrices`.
|
| 54 |
+
s : ndarray
|
| 55 |
+
The singular values, sorted in non-increasing order.
|
| 56 |
+
Of shape (K,), with ``K = min(M, N)``.
|
| 57 |
+
Vh : ndarray
|
| 58 |
+
Unitary matrix having right singular vectors as rows.
|
| 59 |
+
Of shape ``(N, N)`` or ``(K, N)`` depending on `full_matrices`.
|
| 60 |
+
|
| 61 |
+
For ``compute_uv=False``, only ``s`` is returned.
|
| 62 |
+
|
| 63 |
+
Raises
|
| 64 |
+
------
|
| 65 |
+
LinAlgError
|
| 66 |
+
If SVD computation does not converge.
|
| 67 |
+
|
| 68 |
+
See Also
|
| 69 |
+
--------
|
| 70 |
+
svdvals : Compute singular values of a matrix.
|
| 71 |
+
diagsvd : Construct the Sigma matrix, given the vector s.
|
| 72 |
+
|
| 73 |
+
Examples
|
| 74 |
+
--------
|
| 75 |
+
>>> import numpy as np
|
| 76 |
+
>>> from scipy import linalg
|
| 77 |
+
>>> rng = np.random.default_rng()
|
| 78 |
+
>>> m, n = 9, 6
|
| 79 |
+
>>> a = rng.standard_normal((m, n)) + 1.j*rng.standard_normal((m, n))
|
| 80 |
+
>>> U, s, Vh = linalg.svd(a)
|
| 81 |
+
>>> U.shape, s.shape, Vh.shape
|
| 82 |
+
((9, 9), (6,), (6, 6))
|
| 83 |
+
|
| 84 |
+
Reconstruct the original matrix from the decomposition:
|
| 85 |
+
|
| 86 |
+
>>> sigma = np.zeros((m, n))
|
| 87 |
+
>>> for i in range(min(m, n)):
|
| 88 |
+
... sigma[i, i] = s[i]
|
| 89 |
+
>>> a1 = np.dot(U, np.dot(sigma, Vh))
|
| 90 |
+
>>> np.allclose(a, a1)
|
| 91 |
+
True
|
| 92 |
+
|
| 93 |
+
Alternatively, use ``full_matrices=False`` (notice that the shape of
|
| 94 |
+
``U`` is then ``(m, n)`` instead of ``(m, m)``):
|
| 95 |
+
|
| 96 |
+
>>> U, s, Vh = linalg.svd(a, full_matrices=False)
|
| 97 |
+
>>> U.shape, s.shape, Vh.shape
|
| 98 |
+
((9, 6), (6,), (6, 6))
|
| 99 |
+
>>> S = np.diag(s)
|
| 100 |
+
>>> np.allclose(a, np.dot(U, np.dot(S, Vh)))
|
| 101 |
+
True
|
| 102 |
+
|
| 103 |
+
>>> s2 = linalg.svd(a, compute_uv=False)
|
| 104 |
+
>>> np.allclose(s, s2)
|
| 105 |
+
True
|
| 106 |
+
|
| 107 |
+
"""
|
| 108 |
+
a1 = _asarray_validated(a, check_finite=check_finite)
|
| 109 |
+
if len(a1.shape) != 2:
|
| 110 |
+
raise ValueError('expected matrix')
|
| 111 |
+
m, n = a1.shape
|
| 112 |
+
overwrite_a = overwrite_a or (_datacopied(a1, a))
|
| 113 |
+
|
| 114 |
+
if not isinstance(lapack_driver, str):
|
| 115 |
+
raise TypeError('lapack_driver must be a string')
|
| 116 |
+
if lapack_driver not in ('gesdd', 'gesvd'):
|
| 117 |
+
message = f'lapack_driver must be "gesdd" or "gesvd", not "{lapack_driver}"'
|
| 118 |
+
raise ValueError(message)
|
| 119 |
+
|
| 120 |
+
if lapack_driver == 'gesdd' and compute_uv:
|
| 121 |
+
# XXX: revisit int32 when ILP64 lapack becomes a thing
|
| 122 |
+
max_mn, min_mn = (m, n) if m > n else (n, m)
|
| 123 |
+
if full_matrices:
|
| 124 |
+
if max_mn*max_mn > numpy.iinfo(numpy.int32).max:
|
| 125 |
+
raise ValueError(f"Indexing a matrix size {max_mn} x {max_mn} "
|
| 126 |
+
" would incur integer overflow in LAPACK.")
|
| 127 |
+
else:
|
| 128 |
+
sz = max(m * min_mn, n * min_mn)
|
| 129 |
+
if max(m * min_mn, n * min_mn) > numpy.iinfo(numpy.int32).max:
|
| 130 |
+
raise ValueError(f"Indexing a matrix of {sz} elements would "
|
| 131 |
+
"incur an in integer overflow in LAPACK.")
|
| 132 |
+
|
| 133 |
+
funcs = (lapack_driver, lapack_driver + '_lwork')
|
| 134 |
+
gesXd, gesXd_lwork = get_lapack_funcs(funcs, (a1,), ilp64='preferred')
|
| 135 |
+
|
| 136 |
+
# compute optimal lwork
|
| 137 |
+
lwork = _compute_lwork(gesXd_lwork, a1.shape[0], a1.shape[1],
|
| 138 |
+
compute_uv=compute_uv, full_matrices=full_matrices)
|
| 139 |
+
|
| 140 |
+
# perform decomposition
|
| 141 |
+
u, s, v, info = gesXd(a1, compute_uv=compute_uv, lwork=lwork,
|
| 142 |
+
full_matrices=full_matrices, overwrite_a=overwrite_a)
|
| 143 |
+
|
| 144 |
+
if info > 0:
|
| 145 |
+
raise LinAlgError("SVD did not converge")
|
| 146 |
+
if info < 0:
|
| 147 |
+
raise ValueError('illegal value in %dth argument of internal gesdd'
|
| 148 |
+
% -info)
|
| 149 |
+
if compute_uv:
|
| 150 |
+
return u, s, v
|
| 151 |
+
else:
|
| 152 |
+
return s
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def svdvals(a, overwrite_a=False, check_finite=True):
|
| 156 |
+
"""
|
| 157 |
+
Compute singular values of a matrix.
|
| 158 |
+
|
| 159 |
+
Parameters
|
| 160 |
+
----------
|
| 161 |
+
a : (M, N) array_like
|
| 162 |
+
Matrix to decompose.
|
| 163 |
+
overwrite_a : bool, optional
|
| 164 |
+
Whether to overwrite `a`; may improve performance.
|
| 165 |
+
Default is False.
|
| 166 |
+
check_finite : bool, optional
|
| 167 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 168 |
+
Disabling may give a performance gain, but may result in problems
|
| 169 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 170 |
+
|
| 171 |
+
Returns
|
| 172 |
+
-------
|
| 173 |
+
s : (min(M, N),) ndarray
|
| 174 |
+
The singular values, sorted in decreasing order.
|
| 175 |
+
|
| 176 |
+
Raises
|
| 177 |
+
------
|
| 178 |
+
LinAlgError
|
| 179 |
+
If SVD computation does not converge.
|
| 180 |
+
|
| 181 |
+
See Also
|
| 182 |
+
--------
|
| 183 |
+
svd : Compute the full singular value decomposition of a matrix.
|
| 184 |
+
diagsvd : Construct the Sigma matrix, given the vector s.
|
| 185 |
+
|
| 186 |
+
Notes
|
| 187 |
+
-----
|
| 188 |
+
``svdvals(a)`` only differs from ``svd(a, compute_uv=False)`` by its
|
| 189 |
+
handling of the edge case of empty ``a``, where it returns an
|
| 190 |
+
empty sequence:
|
| 191 |
+
|
| 192 |
+
>>> import numpy as np
|
| 193 |
+
>>> a = np.empty((0, 2))
|
| 194 |
+
>>> from scipy.linalg import svdvals
|
| 195 |
+
>>> svdvals(a)
|
| 196 |
+
array([], dtype=float64)
|
| 197 |
+
|
| 198 |
+
Examples
|
| 199 |
+
--------
|
| 200 |
+
>>> import numpy as np
|
| 201 |
+
>>> from scipy.linalg import svdvals
|
| 202 |
+
>>> m = np.array([[1.0, 0.0],
|
| 203 |
+
... [2.0, 3.0],
|
| 204 |
+
... [1.0, 1.0],
|
| 205 |
+
... [0.0, 2.0],
|
| 206 |
+
... [1.0, 0.0]])
|
| 207 |
+
>>> svdvals(m)
|
| 208 |
+
array([ 4.28091555, 1.63516424])
|
| 209 |
+
|
| 210 |
+
We can verify the maximum singular value of `m` by computing the maximum
|
| 211 |
+
length of `m.dot(u)` over all the unit vectors `u` in the (x,y) plane.
|
| 212 |
+
We approximate "all" the unit vectors with a large sample. Because
|
| 213 |
+
of linearity, we only need the unit vectors with angles in [0, pi].
|
| 214 |
+
|
| 215 |
+
>>> t = np.linspace(0, np.pi, 2000)
|
| 216 |
+
>>> u = np.array([np.cos(t), np.sin(t)])
|
| 217 |
+
>>> np.linalg.norm(m.dot(u), axis=0).max()
|
| 218 |
+
4.2809152422538475
|
| 219 |
+
|
| 220 |
+
`p` is a projection matrix with rank 1. With exact arithmetic,
|
| 221 |
+
its singular values would be [1, 0, 0, 0].
|
| 222 |
+
|
| 223 |
+
>>> v = np.array([0.1, 0.3, 0.9, 0.3])
|
| 224 |
+
>>> p = np.outer(v, v)
|
| 225 |
+
>>> svdvals(p)
|
| 226 |
+
array([ 1.00000000e+00, 2.02021698e-17, 1.56692500e-17,
|
| 227 |
+
8.15115104e-34])
|
| 228 |
+
|
| 229 |
+
The singular values of an orthogonal matrix are all 1. Here, we
|
| 230 |
+
create a random orthogonal matrix by using the `rvs()` method of
|
| 231 |
+
`scipy.stats.ortho_group`.
|
| 232 |
+
|
| 233 |
+
>>> from scipy.stats import ortho_group
|
| 234 |
+
>>> orth = ortho_group.rvs(4)
|
| 235 |
+
>>> svdvals(orth)
|
| 236 |
+
array([ 1., 1., 1., 1.])
|
| 237 |
+
|
| 238 |
+
"""
|
| 239 |
+
a = _asarray_validated(a, check_finite=check_finite)
|
| 240 |
+
if a.size:
|
| 241 |
+
return svd(a, compute_uv=0, overwrite_a=overwrite_a,
|
| 242 |
+
check_finite=False)
|
| 243 |
+
elif len(a.shape) != 2:
|
| 244 |
+
raise ValueError('expected matrix')
|
| 245 |
+
else:
|
| 246 |
+
return numpy.empty(0)
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def diagsvd(s, M, N):
|
| 250 |
+
"""
|
| 251 |
+
Construct the sigma matrix in SVD from singular values and size M, N.
|
| 252 |
+
|
| 253 |
+
Parameters
|
| 254 |
+
----------
|
| 255 |
+
s : (M,) or (N,) array_like
|
| 256 |
+
Singular values
|
| 257 |
+
M : int
|
| 258 |
+
Size of the matrix whose singular values are `s`.
|
| 259 |
+
N : int
|
| 260 |
+
Size of the matrix whose singular values are `s`.
|
| 261 |
+
|
| 262 |
+
Returns
|
| 263 |
+
-------
|
| 264 |
+
S : (M, N) ndarray
|
| 265 |
+
The S-matrix in the singular value decomposition
|
| 266 |
+
|
| 267 |
+
See Also
|
| 268 |
+
--------
|
| 269 |
+
svd : Singular value decomposition of a matrix
|
| 270 |
+
svdvals : Compute singular values of a matrix.
|
| 271 |
+
|
| 272 |
+
Examples
|
| 273 |
+
--------
|
| 274 |
+
>>> import numpy as np
|
| 275 |
+
>>> from scipy.linalg import diagsvd
|
| 276 |
+
>>> vals = np.array([1, 2, 3]) # The array representing the computed svd
|
| 277 |
+
>>> diagsvd(vals, 3, 4)
|
| 278 |
+
array([[1, 0, 0, 0],
|
| 279 |
+
[0, 2, 0, 0],
|
| 280 |
+
[0, 0, 3, 0]])
|
| 281 |
+
>>> diagsvd(vals, 4, 3)
|
| 282 |
+
array([[1, 0, 0],
|
| 283 |
+
[0, 2, 0],
|
| 284 |
+
[0, 0, 3],
|
| 285 |
+
[0, 0, 0]])
|
| 286 |
+
|
| 287 |
+
"""
|
| 288 |
+
part = diag(s)
|
| 289 |
+
typ = part.dtype.char
|
| 290 |
+
MorN = len(s)
|
| 291 |
+
if MorN == M:
|
| 292 |
+
return numpy.hstack((part, zeros((M, N - M), dtype=typ)))
|
| 293 |
+
elif MorN == N:
|
| 294 |
+
return r_[part, zeros((M - N, N), dtype=typ)]
|
| 295 |
+
else:
|
| 296 |
+
raise ValueError("Length of s must be M or N.")
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
# Orthonormal decomposition
|
| 300 |
+
|
| 301 |
+
def orth(A, rcond=None):
|
| 302 |
+
"""
|
| 303 |
+
Construct an orthonormal basis for the range of A using SVD
|
| 304 |
+
|
| 305 |
+
Parameters
|
| 306 |
+
----------
|
| 307 |
+
A : (M, N) array_like
|
| 308 |
+
Input array
|
| 309 |
+
rcond : float, optional
|
| 310 |
+
Relative condition number. Singular values ``s`` smaller than
|
| 311 |
+
``rcond * max(s)`` are considered zero.
|
| 312 |
+
Default: floating point eps * max(M,N).
|
| 313 |
+
|
| 314 |
+
Returns
|
| 315 |
+
-------
|
| 316 |
+
Q : (M, K) ndarray
|
| 317 |
+
Orthonormal basis for the range of A.
|
| 318 |
+
K = effective rank of A, as determined by rcond
|
| 319 |
+
|
| 320 |
+
See Also
|
| 321 |
+
--------
|
| 322 |
+
svd : Singular value decomposition of a matrix
|
| 323 |
+
null_space : Matrix null space
|
| 324 |
+
|
| 325 |
+
Examples
|
| 326 |
+
--------
|
| 327 |
+
>>> import numpy as np
|
| 328 |
+
>>> from scipy.linalg import orth
|
| 329 |
+
>>> A = np.array([[2, 0, 0], [0, 5, 0]]) # rank 2 array
|
| 330 |
+
>>> orth(A)
|
| 331 |
+
array([[0., 1.],
|
| 332 |
+
[1., 0.]])
|
| 333 |
+
>>> orth(A.T)
|
| 334 |
+
array([[0., 1.],
|
| 335 |
+
[1., 0.],
|
| 336 |
+
[0., 0.]])
|
| 337 |
+
|
| 338 |
+
"""
|
| 339 |
+
u, s, vh = svd(A, full_matrices=False)
|
| 340 |
+
M, N = u.shape[0], vh.shape[1]
|
| 341 |
+
if rcond is None:
|
| 342 |
+
rcond = numpy.finfo(s.dtype).eps * max(M, N)
|
| 343 |
+
tol = numpy.amax(s) * rcond
|
| 344 |
+
num = numpy.sum(s > tol, dtype=int)
|
| 345 |
+
Q = u[:, :num]
|
| 346 |
+
return Q
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
def null_space(A, rcond=None):
|
| 350 |
+
"""
|
| 351 |
+
Construct an orthonormal basis for the null space of A using SVD
|
| 352 |
+
|
| 353 |
+
Parameters
|
| 354 |
+
----------
|
| 355 |
+
A : (M, N) array_like
|
| 356 |
+
Input array
|
| 357 |
+
rcond : float, optional
|
| 358 |
+
Relative condition number. Singular values ``s`` smaller than
|
| 359 |
+
``rcond * max(s)`` are considered zero.
|
| 360 |
+
Default: floating point eps * max(M,N).
|
| 361 |
+
|
| 362 |
+
Returns
|
| 363 |
+
-------
|
| 364 |
+
Z : (N, K) ndarray
|
| 365 |
+
Orthonormal basis for the null space of A.
|
| 366 |
+
K = dimension of effective null space, as determined by rcond
|
| 367 |
+
|
| 368 |
+
See Also
|
| 369 |
+
--------
|
| 370 |
+
svd : Singular value decomposition of a matrix
|
| 371 |
+
orth : Matrix range
|
| 372 |
+
|
| 373 |
+
Examples
|
| 374 |
+
--------
|
| 375 |
+
1-D null space:
|
| 376 |
+
|
| 377 |
+
>>> import numpy as np
|
| 378 |
+
>>> from scipy.linalg import null_space
|
| 379 |
+
>>> A = np.array([[1, 1], [1, 1]])
|
| 380 |
+
>>> ns = null_space(A)
|
| 381 |
+
>>> ns * np.copysign(1, ns[0,0]) # Remove the sign ambiguity of the vector
|
| 382 |
+
array([[ 0.70710678],
|
| 383 |
+
[-0.70710678]])
|
| 384 |
+
|
| 385 |
+
2-D null space:
|
| 386 |
+
|
| 387 |
+
>>> from numpy.random import default_rng
|
| 388 |
+
>>> rng = default_rng()
|
| 389 |
+
>>> B = rng.random((3, 5))
|
| 390 |
+
>>> Z = null_space(B)
|
| 391 |
+
>>> Z.shape
|
| 392 |
+
(5, 2)
|
| 393 |
+
>>> np.allclose(B.dot(Z), 0)
|
| 394 |
+
True
|
| 395 |
+
|
| 396 |
+
The basis vectors are orthonormal (up to rounding error):
|
| 397 |
+
|
| 398 |
+
>>> Z.T.dot(Z)
|
| 399 |
+
array([[ 1.00000000e+00, 6.92087741e-17],
|
| 400 |
+
[ 6.92087741e-17, 1.00000000e+00]])
|
| 401 |
+
|
| 402 |
+
"""
|
| 403 |
+
u, s, vh = svd(A, full_matrices=True)
|
| 404 |
+
M, N = u.shape[0], vh.shape[1]
|
| 405 |
+
if rcond is None:
|
| 406 |
+
rcond = numpy.finfo(s.dtype).eps * max(M, N)
|
| 407 |
+
tol = numpy.amax(s) * rcond
|
| 408 |
+
num = numpy.sum(s > tol, dtype=int)
|
| 409 |
+
Q = vh[num:,:].T.conj()
|
| 410 |
+
return Q
|
| 411 |
+
|
| 412 |
+
|
| 413 |
+
def subspace_angles(A, B):
|
| 414 |
+
r"""
|
| 415 |
+
Compute the subspace angles between two matrices.
|
| 416 |
+
|
| 417 |
+
Parameters
|
| 418 |
+
----------
|
| 419 |
+
A : (M, N) array_like
|
| 420 |
+
The first input array.
|
| 421 |
+
B : (M, K) array_like
|
| 422 |
+
The second input array.
|
| 423 |
+
|
| 424 |
+
Returns
|
| 425 |
+
-------
|
| 426 |
+
angles : ndarray, shape (min(N, K),)
|
| 427 |
+
The subspace angles between the column spaces of `A` and `B` in
|
| 428 |
+
descending order.
|
| 429 |
+
|
| 430 |
+
See Also
|
| 431 |
+
--------
|
| 432 |
+
orth
|
| 433 |
+
svd
|
| 434 |
+
|
| 435 |
+
Notes
|
| 436 |
+
-----
|
| 437 |
+
This computes the subspace angles according to the formula
|
| 438 |
+
provided in [1]_. For equivalence with MATLAB and Octave behavior,
|
| 439 |
+
use ``angles[0]``.
|
| 440 |
+
|
| 441 |
+
.. versionadded:: 1.0
|
| 442 |
+
|
| 443 |
+
References
|
| 444 |
+
----------
|
| 445 |
+
.. [1] Knyazev A, Argentati M (2002) Principal Angles between Subspaces
|
| 446 |
+
in an A-Based Scalar Product: Algorithms and Perturbation
|
| 447 |
+
Estimates. SIAM J. Sci. Comput. 23:2008-2040.
|
| 448 |
+
|
| 449 |
+
Examples
|
| 450 |
+
--------
|
| 451 |
+
An Hadamard matrix, which has orthogonal columns, so we expect that
|
| 452 |
+
the suspace angle to be :math:`\frac{\pi}{2}`:
|
| 453 |
+
|
| 454 |
+
>>> import numpy as np
|
| 455 |
+
>>> from scipy.linalg import hadamard, subspace_angles
|
| 456 |
+
>>> rng = np.random.default_rng()
|
| 457 |
+
>>> H = hadamard(4)
|
| 458 |
+
>>> print(H)
|
| 459 |
+
[[ 1 1 1 1]
|
| 460 |
+
[ 1 -1 1 -1]
|
| 461 |
+
[ 1 1 -1 -1]
|
| 462 |
+
[ 1 -1 -1 1]]
|
| 463 |
+
>>> np.rad2deg(subspace_angles(H[:, :2], H[:, 2:]))
|
| 464 |
+
array([ 90., 90.])
|
| 465 |
+
|
| 466 |
+
And the subspace angle of a matrix to itself should be zero:
|
| 467 |
+
|
| 468 |
+
>>> subspace_angles(H[:, :2], H[:, :2]) <= 2 * np.finfo(float).eps
|
| 469 |
+
array([ True, True], dtype=bool)
|
| 470 |
+
|
| 471 |
+
The angles between non-orthogonal subspaces are in between these extremes:
|
| 472 |
+
|
| 473 |
+
>>> x = rng.standard_normal((4, 3))
|
| 474 |
+
>>> np.rad2deg(subspace_angles(x[:, :2], x[:, [2]]))
|
| 475 |
+
array([ 55.832]) # random
|
| 476 |
+
"""
|
| 477 |
+
# Steps here omit the U and V calculation steps from the paper
|
| 478 |
+
|
| 479 |
+
# 1. Compute orthonormal bases of column-spaces
|
| 480 |
+
A = _asarray_validated(A, check_finite=True)
|
| 481 |
+
if len(A.shape) != 2:
|
| 482 |
+
raise ValueError(f'expected 2D array, got shape {A.shape}')
|
| 483 |
+
QA = orth(A)
|
| 484 |
+
del A
|
| 485 |
+
|
| 486 |
+
B = _asarray_validated(B, check_finite=True)
|
| 487 |
+
if len(B.shape) != 2:
|
| 488 |
+
raise ValueError(f'expected 2D array, got shape {B.shape}')
|
| 489 |
+
if len(B) != len(QA):
|
| 490 |
+
raise ValueError('A and B must have the same number of rows, got '
|
| 491 |
+
f'{QA.shape[0]} and {B.shape[0]}')
|
| 492 |
+
QB = orth(B)
|
| 493 |
+
del B
|
| 494 |
+
|
| 495 |
+
# 2. Compute SVD for cosine
|
| 496 |
+
QA_H_QB = dot(QA.T.conj(), QB)
|
| 497 |
+
sigma = svdvals(QA_H_QB)
|
| 498 |
+
|
| 499 |
+
# 3. Compute matrix B
|
| 500 |
+
if QA.shape[1] >= QB.shape[1]:
|
| 501 |
+
B = QB - dot(QA, QA_H_QB)
|
| 502 |
+
else:
|
| 503 |
+
B = QA - dot(QB, QA_H_QB.T.conj())
|
| 504 |
+
del QA, QB, QA_H_QB
|
| 505 |
+
|
| 506 |
+
# 4. Compute SVD for sine
|
| 507 |
+
mask = sigma ** 2 >= 0.5
|
| 508 |
+
if mask.any():
|
| 509 |
+
mu_arcsin = arcsin(clip(svdvals(B, overwrite_a=True), -1., 1.))
|
| 510 |
+
else:
|
| 511 |
+
mu_arcsin = 0.
|
| 512 |
+
|
| 513 |
+
# 5. Compute the principal angles
|
| 514 |
+
# with reverse ordering of sigma because smallest sigma belongs to largest
|
| 515 |
+
# angle theta
|
| 516 |
+
theta = where(mask, mu_arcsin, arccos(clip(sigma[::-1], -1., 1.)))
|
| 517 |
+
return theta
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_expm_frechet.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Frechet derivative of the matrix exponential."""
|
| 2 |
+
import numpy as np
|
| 3 |
+
import scipy.linalg
|
| 4 |
+
|
| 5 |
+
__all__ = ['expm_frechet', 'expm_cond']
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def expm_frechet(A, E, method=None, compute_expm=True, check_finite=True):
|
| 9 |
+
"""
|
| 10 |
+
Frechet derivative of the matrix exponential of A in the direction E.
|
| 11 |
+
|
| 12 |
+
Parameters
|
| 13 |
+
----------
|
| 14 |
+
A : (N, N) array_like
|
| 15 |
+
Matrix of which to take the matrix exponential.
|
| 16 |
+
E : (N, N) array_like
|
| 17 |
+
Matrix direction in which to take the Frechet derivative.
|
| 18 |
+
method : str, optional
|
| 19 |
+
Choice of algorithm. Should be one of
|
| 20 |
+
|
| 21 |
+
- `SPS` (default)
|
| 22 |
+
- `blockEnlarge`
|
| 23 |
+
|
| 24 |
+
compute_expm : bool, optional
|
| 25 |
+
Whether to compute also `expm_A` in addition to `expm_frechet_AE`.
|
| 26 |
+
Default is True.
|
| 27 |
+
check_finite : bool, optional
|
| 28 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 29 |
+
Disabling may give a performance gain, but may result in problems
|
| 30 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 31 |
+
|
| 32 |
+
Returns
|
| 33 |
+
-------
|
| 34 |
+
expm_A : ndarray
|
| 35 |
+
Matrix exponential of A.
|
| 36 |
+
expm_frechet_AE : ndarray
|
| 37 |
+
Frechet derivative of the matrix exponential of A in the direction E.
|
| 38 |
+
For ``compute_expm = False``, only `expm_frechet_AE` is returned.
|
| 39 |
+
|
| 40 |
+
See Also
|
| 41 |
+
--------
|
| 42 |
+
expm : Compute the exponential of a matrix.
|
| 43 |
+
|
| 44 |
+
Notes
|
| 45 |
+
-----
|
| 46 |
+
This section describes the available implementations that can be selected
|
| 47 |
+
by the `method` parameter. The default method is *SPS*.
|
| 48 |
+
|
| 49 |
+
Method *blockEnlarge* is a naive algorithm.
|
| 50 |
+
|
| 51 |
+
Method *SPS* is Scaling-Pade-Squaring [1]_.
|
| 52 |
+
It is a sophisticated implementation which should take
|
| 53 |
+
only about 3/8 as much time as the naive implementation.
|
| 54 |
+
The asymptotics are the same.
|
| 55 |
+
|
| 56 |
+
.. versionadded:: 0.13.0
|
| 57 |
+
|
| 58 |
+
References
|
| 59 |
+
----------
|
| 60 |
+
.. [1] Awad H. Al-Mohy and Nicholas J. Higham (2009)
|
| 61 |
+
Computing the Frechet Derivative of the Matrix Exponential,
|
| 62 |
+
with an application to Condition Number Estimation.
|
| 63 |
+
SIAM Journal On Matrix Analysis and Applications.,
|
| 64 |
+
30 (4). pp. 1639-1657. ISSN 1095-7162
|
| 65 |
+
|
| 66 |
+
Examples
|
| 67 |
+
--------
|
| 68 |
+
>>> import numpy as np
|
| 69 |
+
>>> from scipy import linalg
|
| 70 |
+
>>> rng = np.random.default_rng()
|
| 71 |
+
|
| 72 |
+
>>> A = rng.standard_normal((3, 3))
|
| 73 |
+
>>> E = rng.standard_normal((3, 3))
|
| 74 |
+
>>> expm_A, expm_frechet_AE = linalg.expm_frechet(A, E)
|
| 75 |
+
>>> expm_A.shape, expm_frechet_AE.shape
|
| 76 |
+
((3, 3), (3, 3))
|
| 77 |
+
|
| 78 |
+
Create a 6x6 matrix containing [[A, E], [0, A]]:
|
| 79 |
+
|
| 80 |
+
>>> M = np.zeros((6, 6))
|
| 81 |
+
>>> M[:3, :3] = A
|
| 82 |
+
>>> M[:3, 3:] = E
|
| 83 |
+
>>> M[3:, 3:] = A
|
| 84 |
+
|
| 85 |
+
>>> expm_M = linalg.expm(M)
|
| 86 |
+
>>> np.allclose(expm_A, expm_M[:3, :3])
|
| 87 |
+
True
|
| 88 |
+
>>> np.allclose(expm_frechet_AE, expm_M[:3, 3:])
|
| 89 |
+
True
|
| 90 |
+
|
| 91 |
+
"""
|
| 92 |
+
if check_finite:
|
| 93 |
+
A = np.asarray_chkfinite(A)
|
| 94 |
+
E = np.asarray_chkfinite(E)
|
| 95 |
+
else:
|
| 96 |
+
A = np.asarray(A)
|
| 97 |
+
E = np.asarray(E)
|
| 98 |
+
if A.ndim != 2 or A.shape[0] != A.shape[1]:
|
| 99 |
+
raise ValueError('expected A to be a square matrix')
|
| 100 |
+
if E.ndim != 2 or E.shape[0] != E.shape[1]:
|
| 101 |
+
raise ValueError('expected E to be a square matrix')
|
| 102 |
+
if A.shape != E.shape:
|
| 103 |
+
raise ValueError('expected A and E to be the same shape')
|
| 104 |
+
if method is None:
|
| 105 |
+
method = 'SPS'
|
| 106 |
+
if method == 'SPS':
|
| 107 |
+
expm_A, expm_frechet_AE = expm_frechet_algo_64(A, E)
|
| 108 |
+
elif method == 'blockEnlarge':
|
| 109 |
+
expm_A, expm_frechet_AE = expm_frechet_block_enlarge(A, E)
|
| 110 |
+
else:
|
| 111 |
+
raise ValueError('Unknown implementation %s' % method)
|
| 112 |
+
if compute_expm:
|
| 113 |
+
return expm_A, expm_frechet_AE
|
| 114 |
+
else:
|
| 115 |
+
return expm_frechet_AE
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def expm_frechet_block_enlarge(A, E):
|
| 119 |
+
"""
|
| 120 |
+
This is a helper function, mostly for testing and profiling.
|
| 121 |
+
Return expm(A), frechet(A, E)
|
| 122 |
+
"""
|
| 123 |
+
n = A.shape[0]
|
| 124 |
+
M = np.vstack([
|
| 125 |
+
np.hstack([A, E]),
|
| 126 |
+
np.hstack([np.zeros_like(A), A])])
|
| 127 |
+
expm_M = scipy.linalg.expm(M)
|
| 128 |
+
return expm_M[:n, :n], expm_M[:n, n:]
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
"""
|
| 132 |
+
Maximal values ell_m of ||2**-s A|| such that the backward error bound
|
| 133 |
+
does not exceed 2**-53.
|
| 134 |
+
"""
|
| 135 |
+
ell_table_61 = (
|
| 136 |
+
None,
|
| 137 |
+
# 1
|
| 138 |
+
2.11e-8,
|
| 139 |
+
3.56e-4,
|
| 140 |
+
1.08e-2,
|
| 141 |
+
6.49e-2,
|
| 142 |
+
2.00e-1,
|
| 143 |
+
4.37e-1,
|
| 144 |
+
7.83e-1,
|
| 145 |
+
1.23e0,
|
| 146 |
+
1.78e0,
|
| 147 |
+
2.42e0,
|
| 148 |
+
# 11
|
| 149 |
+
3.13e0,
|
| 150 |
+
3.90e0,
|
| 151 |
+
4.74e0,
|
| 152 |
+
5.63e0,
|
| 153 |
+
6.56e0,
|
| 154 |
+
7.52e0,
|
| 155 |
+
8.53e0,
|
| 156 |
+
9.56e0,
|
| 157 |
+
1.06e1,
|
| 158 |
+
1.17e1,
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
# The b vectors and U and V are copypasted
|
| 163 |
+
# from scipy.sparse.linalg.matfuncs.py.
|
| 164 |
+
# M, Lu, Lv follow (6.11), (6.12), (6.13), (3.3)
|
| 165 |
+
|
| 166 |
+
def _diff_pade3(A, E, ident):
|
| 167 |
+
b = (120., 60., 12., 1.)
|
| 168 |
+
A2 = A.dot(A)
|
| 169 |
+
M2 = np.dot(A, E) + np.dot(E, A)
|
| 170 |
+
U = A.dot(b[3]*A2 + b[1]*ident)
|
| 171 |
+
V = b[2]*A2 + b[0]*ident
|
| 172 |
+
Lu = A.dot(b[3]*M2) + E.dot(b[3]*A2 + b[1]*ident)
|
| 173 |
+
Lv = b[2]*M2
|
| 174 |
+
return U, V, Lu, Lv
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def _diff_pade5(A, E, ident):
|
| 178 |
+
b = (30240., 15120., 3360., 420., 30., 1.)
|
| 179 |
+
A2 = A.dot(A)
|
| 180 |
+
M2 = np.dot(A, E) + np.dot(E, A)
|
| 181 |
+
A4 = np.dot(A2, A2)
|
| 182 |
+
M4 = np.dot(A2, M2) + np.dot(M2, A2)
|
| 183 |
+
U = A.dot(b[5]*A4 + b[3]*A2 + b[1]*ident)
|
| 184 |
+
V = b[4]*A4 + b[2]*A2 + b[0]*ident
|
| 185 |
+
Lu = (A.dot(b[5]*M4 + b[3]*M2) +
|
| 186 |
+
E.dot(b[5]*A4 + b[3]*A2 + b[1]*ident))
|
| 187 |
+
Lv = b[4]*M4 + b[2]*M2
|
| 188 |
+
return U, V, Lu, Lv
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def _diff_pade7(A, E, ident):
|
| 192 |
+
b = (17297280., 8648640., 1995840., 277200., 25200., 1512., 56., 1.)
|
| 193 |
+
A2 = A.dot(A)
|
| 194 |
+
M2 = np.dot(A, E) + np.dot(E, A)
|
| 195 |
+
A4 = np.dot(A2, A2)
|
| 196 |
+
M4 = np.dot(A2, M2) + np.dot(M2, A2)
|
| 197 |
+
A6 = np.dot(A2, A4)
|
| 198 |
+
M6 = np.dot(A4, M2) + np.dot(M4, A2)
|
| 199 |
+
U = A.dot(b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident)
|
| 200 |
+
V = b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
|
| 201 |
+
Lu = (A.dot(b[7]*M6 + b[5]*M4 + b[3]*M2) +
|
| 202 |
+
E.dot(b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident))
|
| 203 |
+
Lv = b[6]*M6 + b[4]*M4 + b[2]*M2
|
| 204 |
+
return U, V, Lu, Lv
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def _diff_pade9(A, E, ident):
|
| 208 |
+
b = (17643225600., 8821612800., 2075673600., 302702400., 30270240.,
|
| 209 |
+
2162160., 110880., 3960., 90., 1.)
|
| 210 |
+
A2 = A.dot(A)
|
| 211 |
+
M2 = np.dot(A, E) + np.dot(E, A)
|
| 212 |
+
A4 = np.dot(A2, A2)
|
| 213 |
+
M4 = np.dot(A2, M2) + np.dot(M2, A2)
|
| 214 |
+
A6 = np.dot(A2, A4)
|
| 215 |
+
M6 = np.dot(A4, M2) + np.dot(M4, A2)
|
| 216 |
+
A8 = np.dot(A4, A4)
|
| 217 |
+
M8 = np.dot(A4, M4) + np.dot(M4, A4)
|
| 218 |
+
U = A.dot(b[9]*A8 + b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident)
|
| 219 |
+
V = b[8]*A8 + b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
|
| 220 |
+
Lu = (A.dot(b[9]*M8 + b[7]*M6 + b[5]*M4 + b[3]*M2) +
|
| 221 |
+
E.dot(b[9]*A8 + b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident))
|
| 222 |
+
Lv = b[8]*M8 + b[6]*M6 + b[4]*M4 + b[2]*M2
|
| 223 |
+
return U, V, Lu, Lv
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def expm_frechet_algo_64(A, E):
|
| 227 |
+
n = A.shape[0]
|
| 228 |
+
s = None
|
| 229 |
+
ident = np.identity(n)
|
| 230 |
+
A_norm_1 = scipy.linalg.norm(A, 1)
|
| 231 |
+
m_pade_pairs = (
|
| 232 |
+
(3, _diff_pade3),
|
| 233 |
+
(5, _diff_pade5),
|
| 234 |
+
(7, _diff_pade7),
|
| 235 |
+
(9, _diff_pade9))
|
| 236 |
+
for m, pade in m_pade_pairs:
|
| 237 |
+
if A_norm_1 <= ell_table_61[m]:
|
| 238 |
+
U, V, Lu, Lv = pade(A, E, ident)
|
| 239 |
+
s = 0
|
| 240 |
+
break
|
| 241 |
+
if s is None:
|
| 242 |
+
# scaling
|
| 243 |
+
s = max(0, int(np.ceil(np.log2(A_norm_1 / ell_table_61[13]))))
|
| 244 |
+
A = A * 2.0**-s
|
| 245 |
+
E = E * 2.0**-s
|
| 246 |
+
# pade order 13
|
| 247 |
+
A2 = np.dot(A, A)
|
| 248 |
+
M2 = np.dot(A, E) + np.dot(E, A)
|
| 249 |
+
A4 = np.dot(A2, A2)
|
| 250 |
+
M4 = np.dot(A2, M2) + np.dot(M2, A2)
|
| 251 |
+
A6 = np.dot(A2, A4)
|
| 252 |
+
M6 = np.dot(A4, M2) + np.dot(M4, A2)
|
| 253 |
+
b = (64764752532480000., 32382376266240000., 7771770303897600.,
|
| 254 |
+
1187353796428800., 129060195264000., 10559470521600.,
|
| 255 |
+
670442572800., 33522128640., 1323241920., 40840800., 960960.,
|
| 256 |
+
16380., 182., 1.)
|
| 257 |
+
W1 = b[13]*A6 + b[11]*A4 + b[9]*A2
|
| 258 |
+
W2 = b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident
|
| 259 |
+
Z1 = b[12]*A6 + b[10]*A4 + b[8]*A2
|
| 260 |
+
Z2 = b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
|
| 261 |
+
W = np.dot(A6, W1) + W2
|
| 262 |
+
U = np.dot(A, W)
|
| 263 |
+
V = np.dot(A6, Z1) + Z2
|
| 264 |
+
Lw1 = b[13]*M6 + b[11]*M4 + b[9]*M2
|
| 265 |
+
Lw2 = b[7]*M6 + b[5]*M4 + b[3]*M2
|
| 266 |
+
Lz1 = b[12]*M6 + b[10]*M4 + b[8]*M2
|
| 267 |
+
Lz2 = b[6]*M6 + b[4]*M4 + b[2]*M2
|
| 268 |
+
Lw = np.dot(A6, Lw1) + np.dot(M6, W1) + Lw2
|
| 269 |
+
Lu = np.dot(A, Lw) + np.dot(E, W)
|
| 270 |
+
Lv = np.dot(A6, Lz1) + np.dot(M6, Z1) + Lz2
|
| 271 |
+
# factor once and solve twice
|
| 272 |
+
lu_piv = scipy.linalg.lu_factor(-U + V)
|
| 273 |
+
R = scipy.linalg.lu_solve(lu_piv, U + V)
|
| 274 |
+
L = scipy.linalg.lu_solve(lu_piv, Lu + Lv + np.dot((Lu - Lv), R))
|
| 275 |
+
# squaring
|
| 276 |
+
for k in range(s):
|
| 277 |
+
L = np.dot(R, L) + np.dot(L, R)
|
| 278 |
+
R = np.dot(R, R)
|
| 279 |
+
return R, L
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def vec(M):
|
| 283 |
+
"""
|
| 284 |
+
Stack columns of M to construct a single vector.
|
| 285 |
+
|
| 286 |
+
This is somewhat standard notation in linear algebra.
|
| 287 |
+
|
| 288 |
+
Parameters
|
| 289 |
+
----------
|
| 290 |
+
M : 2-D array_like
|
| 291 |
+
Input matrix
|
| 292 |
+
|
| 293 |
+
Returns
|
| 294 |
+
-------
|
| 295 |
+
v : 1-D ndarray
|
| 296 |
+
Output vector
|
| 297 |
+
|
| 298 |
+
"""
|
| 299 |
+
return M.T.ravel()
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
def expm_frechet_kronform(A, method=None, check_finite=True):
|
| 303 |
+
"""
|
| 304 |
+
Construct the Kronecker form of the Frechet derivative of expm.
|
| 305 |
+
|
| 306 |
+
Parameters
|
| 307 |
+
----------
|
| 308 |
+
A : array_like with shape (N, N)
|
| 309 |
+
Matrix to be expm'd.
|
| 310 |
+
method : str, optional
|
| 311 |
+
Extra keyword to be passed to expm_frechet.
|
| 312 |
+
check_finite : bool, optional
|
| 313 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 314 |
+
Disabling may give a performance gain, but may result in problems
|
| 315 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 316 |
+
|
| 317 |
+
Returns
|
| 318 |
+
-------
|
| 319 |
+
K : 2-D ndarray with shape (N*N, N*N)
|
| 320 |
+
Kronecker form of the Frechet derivative of the matrix exponential.
|
| 321 |
+
|
| 322 |
+
Notes
|
| 323 |
+
-----
|
| 324 |
+
This function is used to help compute the condition number
|
| 325 |
+
of the matrix exponential.
|
| 326 |
+
|
| 327 |
+
See Also
|
| 328 |
+
--------
|
| 329 |
+
expm : Compute a matrix exponential.
|
| 330 |
+
expm_frechet : Compute the Frechet derivative of the matrix exponential.
|
| 331 |
+
expm_cond : Compute the relative condition number of the matrix exponential
|
| 332 |
+
in the Frobenius norm.
|
| 333 |
+
|
| 334 |
+
"""
|
| 335 |
+
if check_finite:
|
| 336 |
+
A = np.asarray_chkfinite(A)
|
| 337 |
+
else:
|
| 338 |
+
A = np.asarray(A)
|
| 339 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 340 |
+
raise ValueError('expected a square matrix')
|
| 341 |
+
|
| 342 |
+
n = A.shape[0]
|
| 343 |
+
ident = np.identity(n)
|
| 344 |
+
cols = []
|
| 345 |
+
for i in range(n):
|
| 346 |
+
for j in range(n):
|
| 347 |
+
E = np.outer(ident[i], ident[j])
|
| 348 |
+
F = expm_frechet(A, E,
|
| 349 |
+
method=method, compute_expm=False, check_finite=False)
|
| 350 |
+
cols.append(vec(F))
|
| 351 |
+
return np.vstack(cols).T
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
def expm_cond(A, check_finite=True):
|
| 355 |
+
"""
|
| 356 |
+
Relative condition number of the matrix exponential in the Frobenius norm.
|
| 357 |
+
|
| 358 |
+
Parameters
|
| 359 |
+
----------
|
| 360 |
+
A : 2-D array_like
|
| 361 |
+
Square input matrix with shape (N, N).
|
| 362 |
+
check_finite : bool, optional
|
| 363 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 364 |
+
Disabling may give a performance gain, but may result in problems
|
| 365 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 366 |
+
|
| 367 |
+
Returns
|
| 368 |
+
-------
|
| 369 |
+
kappa : float
|
| 370 |
+
The relative condition number of the matrix exponential
|
| 371 |
+
in the Frobenius norm
|
| 372 |
+
|
| 373 |
+
See Also
|
| 374 |
+
--------
|
| 375 |
+
expm : Compute the exponential of a matrix.
|
| 376 |
+
expm_frechet : Compute the Frechet derivative of the matrix exponential.
|
| 377 |
+
|
| 378 |
+
Notes
|
| 379 |
+
-----
|
| 380 |
+
A faster estimate for the condition number in the 1-norm
|
| 381 |
+
has been published but is not yet implemented in SciPy.
|
| 382 |
+
|
| 383 |
+
.. versionadded:: 0.14.0
|
| 384 |
+
|
| 385 |
+
Examples
|
| 386 |
+
--------
|
| 387 |
+
>>> import numpy as np
|
| 388 |
+
>>> from scipy.linalg import expm_cond
|
| 389 |
+
>>> A = np.array([[-0.3, 0.2, 0.6], [0.6, 0.3, -0.1], [-0.7, 1.2, 0.9]])
|
| 390 |
+
>>> k = expm_cond(A)
|
| 391 |
+
>>> k
|
| 392 |
+
1.7787805864469866
|
| 393 |
+
|
| 394 |
+
"""
|
| 395 |
+
if check_finite:
|
| 396 |
+
A = np.asarray_chkfinite(A)
|
| 397 |
+
else:
|
| 398 |
+
A = np.asarray(A)
|
| 399 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 400 |
+
raise ValueError('expected a square matrix')
|
| 401 |
+
|
| 402 |
+
X = scipy.linalg.expm(A)
|
| 403 |
+
K = expm_frechet_kronform(A, check_finite=False)
|
| 404 |
+
|
| 405 |
+
# The following norm choices are deliberate.
|
| 406 |
+
# The norms of A and X are Frobenius norms,
|
| 407 |
+
# and the norm of K is the induced 2-norm.
|
| 408 |
+
A_norm = scipy.linalg.norm(A, 'fro')
|
| 409 |
+
X_norm = scipy.linalg.norm(X, 'fro')
|
| 410 |
+
K_norm = scipy.linalg.norm(K, 2)
|
| 411 |
+
|
| 412 |
+
kappa = (K_norm * A_norm) / X_norm
|
| 413 |
+
return kappa
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_interpolative_backend.py
ADDED
|
@@ -0,0 +1,1681 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#******************************************************************************
|
| 2 |
+
# Copyright (C) 2013 Kenneth L. Ho
|
| 3 |
+
#
|
| 4 |
+
# Redistribution and use in source and binary forms, with or without
|
| 5 |
+
# modification, are permitted provided that the following conditions are met:
|
| 6 |
+
#
|
| 7 |
+
# Redistributions of source code must retain the above copyright notice, this
|
| 8 |
+
# list of conditions and the following disclaimer. Redistributions in binary
|
| 9 |
+
# form must reproduce the above copyright notice, this list of conditions and
|
| 10 |
+
# the following disclaimer in the documentation and/or other materials
|
| 11 |
+
# provided with the distribution.
|
| 12 |
+
#
|
| 13 |
+
# None of the names of the copyright holders may be used to endorse or
|
| 14 |
+
# promote products derived from this software without specific prior written
|
| 15 |
+
# 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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
| 21 |
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
| 22 |
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
| 23 |
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
| 24 |
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
| 25 |
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
| 26 |
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
| 27 |
+
# POSSIBILITY OF SUCH DAMAGE.
|
| 28 |
+
#******************************************************************************
|
| 29 |
+
|
| 30 |
+
"""
|
| 31 |
+
Direct wrappers for Fortran `id_dist` backend.
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
import scipy.linalg._interpolative as _id
|
| 35 |
+
import numpy as np
|
| 36 |
+
|
| 37 |
+
_RETCODE_ERROR = RuntimeError("nonzero return code")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def _asfortranarray_copy(A):
|
| 41 |
+
"""
|
| 42 |
+
Same as np.asfortranarray, but ensure a copy
|
| 43 |
+
"""
|
| 44 |
+
A = np.asarray(A)
|
| 45 |
+
if A.flags.f_contiguous:
|
| 46 |
+
A = A.copy(order="F")
|
| 47 |
+
else:
|
| 48 |
+
A = np.asfortranarray(A)
|
| 49 |
+
return A
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
#------------------------------------------------------------------------------
|
| 53 |
+
# id_rand.f
|
| 54 |
+
#------------------------------------------------------------------------------
|
| 55 |
+
|
| 56 |
+
def id_srand(n):
|
| 57 |
+
"""
|
| 58 |
+
Generate standard uniform pseudorandom numbers via a very efficient lagged
|
| 59 |
+
Fibonacci method.
|
| 60 |
+
|
| 61 |
+
:param n:
|
| 62 |
+
Number of pseudorandom numbers to generate.
|
| 63 |
+
:type n: int
|
| 64 |
+
|
| 65 |
+
:return:
|
| 66 |
+
Pseudorandom numbers.
|
| 67 |
+
:rtype: :class:`numpy.ndarray`
|
| 68 |
+
"""
|
| 69 |
+
return _id.id_srand(n)
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def id_srandi(t):
|
| 73 |
+
"""
|
| 74 |
+
Initialize seed values for :func:`id_srand` (any appropriately random
|
| 75 |
+
numbers will do).
|
| 76 |
+
|
| 77 |
+
:param t:
|
| 78 |
+
Array of 55 seed values.
|
| 79 |
+
:type t: :class:`numpy.ndarray`
|
| 80 |
+
"""
|
| 81 |
+
t = np.asfortranarray(t)
|
| 82 |
+
_id.id_srandi(t)
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def id_srando():
|
| 86 |
+
"""
|
| 87 |
+
Reset seed values to their original values.
|
| 88 |
+
"""
|
| 89 |
+
_id.id_srando()
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
#------------------------------------------------------------------------------
|
| 93 |
+
# idd_frm.f
|
| 94 |
+
#------------------------------------------------------------------------------
|
| 95 |
+
|
| 96 |
+
def idd_frm(n, w, x):
|
| 97 |
+
"""
|
| 98 |
+
Transform real vector via a composition of Rokhlin's random transform,
|
| 99 |
+
random subselection, and an FFT.
|
| 100 |
+
|
| 101 |
+
In contrast to :func:`idd_sfrm`, this routine works best when the length of
|
| 102 |
+
the transformed vector is the power-of-two integer output by
|
| 103 |
+
:func:`idd_frmi`, or when the length is not specified but instead
|
| 104 |
+
determined a posteriori from the output. The returned transformed vector is
|
| 105 |
+
randomly permuted.
|
| 106 |
+
|
| 107 |
+
:param n:
|
| 108 |
+
Greatest power-of-two integer satisfying `n <= x.size` as obtained from
|
| 109 |
+
:func:`idd_frmi`; `n` is also the length of the output vector.
|
| 110 |
+
:type n: int
|
| 111 |
+
:param w:
|
| 112 |
+
Initialization array constructed by :func:`idd_frmi`.
|
| 113 |
+
:type w: :class:`numpy.ndarray`
|
| 114 |
+
:param x:
|
| 115 |
+
Vector to be transformed.
|
| 116 |
+
:type x: :class:`numpy.ndarray`
|
| 117 |
+
|
| 118 |
+
:return:
|
| 119 |
+
Transformed vector.
|
| 120 |
+
:rtype: :class:`numpy.ndarray`
|
| 121 |
+
"""
|
| 122 |
+
return _id.idd_frm(n, w, x)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def idd_sfrm(l, n, w, x):
|
| 126 |
+
"""
|
| 127 |
+
Transform real vector via a composition of Rokhlin's random transform,
|
| 128 |
+
random subselection, and an FFT.
|
| 129 |
+
|
| 130 |
+
In contrast to :func:`idd_frm`, this routine works best when the length of
|
| 131 |
+
the transformed vector is known a priori.
|
| 132 |
+
|
| 133 |
+
:param l:
|
| 134 |
+
Length of transformed vector, satisfying `l <= n`.
|
| 135 |
+
:type l: int
|
| 136 |
+
:param n:
|
| 137 |
+
Greatest power-of-two integer satisfying `n <= x.size` as obtained from
|
| 138 |
+
:func:`idd_sfrmi`.
|
| 139 |
+
:type n: int
|
| 140 |
+
:param w:
|
| 141 |
+
Initialization array constructed by :func:`idd_sfrmi`.
|
| 142 |
+
:type w: :class:`numpy.ndarray`
|
| 143 |
+
:param x:
|
| 144 |
+
Vector to be transformed.
|
| 145 |
+
:type x: :class:`numpy.ndarray`
|
| 146 |
+
|
| 147 |
+
:return:
|
| 148 |
+
Transformed vector.
|
| 149 |
+
:rtype: :class:`numpy.ndarray`
|
| 150 |
+
"""
|
| 151 |
+
return _id.idd_sfrm(l, n, w, x)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def idd_frmi(m):
|
| 155 |
+
"""
|
| 156 |
+
Initialize data for :func:`idd_frm`.
|
| 157 |
+
|
| 158 |
+
:param m:
|
| 159 |
+
Length of vector to be transformed.
|
| 160 |
+
:type m: int
|
| 161 |
+
|
| 162 |
+
:return:
|
| 163 |
+
Greatest power-of-two integer `n` satisfying `n <= m`.
|
| 164 |
+
:rtype: int
|
| 165 |
+
:return:
|
| 166 |
+
Initialization array to be used by :func:`idd_frm`.
|
| 167 |
+
:rtype: :class:`numpy.ndarray`
|
| 168 |
+
"""
|
| 169 |
+
return _id.idd_frmi(m)
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def idd_sfrmi(l, m):
|
| 173 |
+
"""
|
| 174 |
+
Initialize data for :func:`idd_sfrm`.
|
| 175 |
+
|
| 176 |
+
:param l:
|
| 177 |
+
Length of output transformed vector.
|
| 178 |
+
:type l: int
|
| 179 |
+
:param m:
|
| 180 |
+
Length of the vector to be transformed.
|
| 181 |
+
:type m: int
|
| 182 |
+
|
| 183 |
+
:return:
|
| 184 |
+
Greatest power-of-two integer `n` satisfying `n <= m`.
|
| 185 |
+
:rtype: int
|
| 186 |
+
:return:
|
| 187 |
+
Initialization array to be used by :func:`idd_sfrm`.
|
| 188 |
+
:rtype: :class:`numpy.ndarray`
|
| 189 |
+
"""
|
| 190 |
+
return _id.idd_sfrmi(l, m)
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
#------------------------------------------------------------------------------
|
| 194 |
+
# idd_id.f
|
| 195 |
+
#------------------------------------------------------------------------------
|
| 196 |
+
|
| 197 |
+
def iddp_id(eps, A):
|
| 198 |
+
"""
|
| 199 |
+
Compute ID of a real matrix to a specified relative precision.
|
| 200 |
+
|
| 201 |
+
:param eps:
|
| 202 |
+
Relative precision.
|
| 203 |
+
:type eps: float
|
| 204 |
+
:param A:
|
| 205 |
+
Matrix.
|
| 206 |
+
:type A: :class:`numpy.ndarray`
|
| 207 |
+
|
| 208 |
+
:return:
|
| 209 |
+
Rank of ID.
|
| 210 |
+
:rtype: int
|
| 211 |
+
:return:
|
| 212 |
+
Column index array.
|
| 213 |
+
:rtype: :class:`numpy.ndarray`
|
| 214 |
+
:return:
|
| 215 |
+
Interpolation coefficients.
|
| 216 |
+
:rtype: :class:`numpy.ndarray`
|
| 217 |
+
"""
|
| 218 |
+
A = _asfortranarray_copy(A)
|
| 219 |
+
k, idx, rnorms = _id.iddp_id(eps, A)
|
| 220 |
+
n = A.shape[1]
|
| 221 |
+
proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
|
| 222 |
+
return k, idx, proj
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def iddr_id(A, k):
|
| 226 |
+
"""
|
| 227 |
+
Compute ID of a real matrix to a specified rank.
|
| 228 |
+
|
| 229 |
+
:param A:
|
| 230 |
+
Matrix.
|
| 231 |
+
:type A: :class:`numpy.ndarray`
|
| 232 |
+
:param k:
|
| 233 |
+
Rank of ID.
|
| 234 |
+
:type k: int
|
| 235 |
+
|
| 236 |
+
:return:
|
| 237 |
+
Column index array.
|
| 238 |
+
:rtype: :class:`numpy.ndarray`
|
| 239 |
+
:return:
|
| 240 |
+
Interpolation coefficients.
|
| 241 |
+
:rtype: :class:`numpy.ndarray`
|
| 242 |
+
"""
|
| 243 |
+
A = _asfortranarray_copy(A)
|
| 244 |
+
idx, rnorms = _id.iddr_id(A, k)
|
| 245 |
+
n = A.shape[1]
|
| 246 |
+
proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
|
| 247 |
+
return idx, proj
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
def idd_reconid(B, idx, proj):
|
| 251 |
+
"""
|
| 252 |
+
Reconstruct matrix from real ID.
|
| 253 |
+
|
| 254 |
+
:param B:
|
| 255 |
+
Skeleton matrix.
|
| 256 |
+
:type B: :class:`numpy.ndarray`
|
| 257 |
+
:param idx:
|
| 258 |
+
Column index array.
|
| 259 |
+
:type idx: :class:`numpy.ndarray`
|
| 260 |
+
:param proj:
|
| 261 |
+
Interpolation coefficients.
|
| 262 |
+
:type proj: :class:`numpy.ndarray`
|
| 263 |
+
|
| 264 |
+
:return:
|
| 265 |
+
Reconstructed matrix.
|
| 266 |
+
:rtype: :class:`numpy.ndarray`
|
| 267 |
+
"""
|
| 268 |
+
B = np.asfortranarray(B)
|
| 269 |
+
if proj.size > 0:
|
| 270 |
+
return _id.idd_reconid(B, idx, proj)
|
| 271 |
+
else:
|
| 272 |
+
return B[:, np.argsort(idx)]
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def idd_reconint(idx, proj):
|
| 276 |
+
"""
|
| 277 |
+
Reconstruct interpolation matrix from real ID.
|
| 278 |
+
|
| 279 |
+
:param idx:
|
| 280 |
+
Column index array.
|
| 281 |
+
:type idx: :class:`numpy.ndarray`
|
| 282 |
+
:param proj:
|
| 283 |
+
Interpolation coefficients.
|
| 284 |
+
:type proj: :class:`numpy.ndarray`
|
| 285 |
+
|
| 286 |
+
:return:
|
| 287 |
+
Interpolation matrix.
|
| 288 |
+
:rtype: :class:`numpy.ndarray`
|
| 289 |
+
"""
|
| 290 |
+
return _id.idd_reconint(idx, proj)
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
def idd_copycols(A, k, idx):
|
| 294 |
+
"""
|
| 295 |
+
Reconstruct skeleton matrix from real ID.
|
| 296 |
+
|
| 297 |
+
:param A:
|
| 298 |
+
Original matrix.
|
| 299 |
+
:type A: :class:`numpy.ndarray`
|
| 300 |
+
:param k:
|
| 301 |
+
Rank of ID.
|
| 302 |
+
:type k: int
|
| 303 |
+
:param idx:
|
| 304 |
+
Column index array.
|
| 305 |
+
:type idx: :class:`numpy.ndarray`
|
| 306 |
+
|
| 307 |
+
:return:
|
| 308 |
+
Skeleton matrix.
|
| 309 |
+
:rtype: :class:`numpy.ndarray`
|
| 310 |
+
"""
|
| 311 |
+
A = np.asfortranarray(A)
|
| 312 |
+
return _id.idd_copycols(A, k, idx)
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
#------------------------------------------------------------------------------
|
| 316 |
+
# idd_id2svd.f
|
| 317 |
+
#------------------------------------------------------------------------------
|
| 318 |
+
|
| 319 |
+
def idd_id2svd(B, idx, proj):
|
| 320 |
+
"""
|
| 321 |
+
Convert real ID to SVD.
|
| 322 |
+
|
| 323 |
+
:param B:
|
| 324 |
+
Skeleton matrix.
|
| 325 |
+
:type B: :class:`numpy.ndarray`
|
| 326 |
+
:param idx:
|
| 327 |
+
Column index array.
|
| 328 |
+
:type idx: :class:`numpy.ndarray`
|
| 329 |
+
:param proj:
|
| 330 |
+
Interpolation coefficients.
|
| 331 |
+
:type proj: :class:`numpy.ndarray`
|
| 332 |
+
|
| 333 |
+
:return:
|
| 334 |
+
Left singular vectors.
|
| 335 |
+
:rtype: :class:`numpy.ndarray`
|
| 336 |
+
:return:
|
| 337 |
+
Right singular vectors.
|
| 338 |
+
:rtype: :class:`numpy.ndarray`
|
| 339 |
+
:return:
|
| 340 |
+
Singular values.
|
| 341 |
+
:rtype: :class:`numpy.ndarray`
|
| 342 |
+
"""
|
| 343 |
+
B = np.asfortranarray(B)
|
| 344 |
+
U, V, S, ier = _id.idd_id2svd(B, idx, proj)
|
| 345 |
+
if ier:
|
| 346 |
+
raise _RETCODE_ERROR
|
| 347 |
+
return U, V, S
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
#------------------------------------------------------------------------------
|
| 351 |
+
# idd_snorm.f
|
| 352 |
+
#------------------------------------------------------------------------------
|
| 353 |
+
|
| 354 |
+
def idd_snorm(m, n, matvect, matvec, its=20):
|
| 355 |
+
"""
|
| 356 |
+
Estimate spectral norm of a real matrix by the randomized power method.
|
| 357 |
+
|
| 358 |
+
:param m:
|
| 359 |
+
Matrix row dimension.
|
| 360 |
+
:type m: int
|
| 361 |
+
:param n:
|
| 362 |
+
Matrix column dimension.
|
| 363 |
+
:type n: int
|
| 364 |
+
:param matvect:
|
| 365 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 366 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 367 |
+
respectively.
|
| 368 |
+
:type matvect: function
|
| 369 |
+
:param matvec:
|
| 370 |
+
Function to apply the matrix to a vector, with call signature
|
| 371 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 372 |
+
respectively.
|
| 373 |
+
:type matvec: function
|
| 374 |
+
:param its:
|
| 375 |
+
Number of power method iterations.
|
| 376 |
+
:type its: int
|
| 377 |
+
|
| 378 |
+
:return:
|
| 379 |
+
Spectral norm estimate.
|
| 380 |
+
:rtype: float
|
| 381 |
+
"""
|
| 382 |
+
snorm, v = _id.idd_snorm(m, n, matvect, matvec, its)
|
| 383 |
+
return snorm
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
def idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its=20):
|
| 387 |
+
"""
|
| 388 |
+
Estimate spectral norm of the difference of two real matrices by the
|
| 389 |
+
randomized power method.
|
| 390 |
+
|
| 391 |
+
:param m:
|
| 392 |
+
Matrix row dimension.
|
| 393 |
+
:type m: int
|
| 394 |
+
:param n:
|
| 395 |
+
Matrix column dimension.
|
| 396 |
+
:type n: int
|
| 397 |
+
:param matvect:
|
| 398 |
+
Function to apply the transpose of the first matrix to a vector, with
|
| 399 |
+
call signature `y = matvect(x)`, where `x` and `y` are the input and
|
| 400 |
+
output vectors, respectively.
|
| 401 |
+
:type matvect: function
|
| 402 |
+
:param matvect2:
|
| 403 |
+
Function to apply the transpose of the second matrix to a vector, with
|
| 404 |
+
call signature `y = matvect2(x)`, where `x` and `y` are the input and
|
| 405 |
+
output vectors, respectively.
|
| 406 |
+
:type matvect2: function
|
| 407 |
+
:param matvec:
|
| 408 |
+
Function to apply the first matrix to a vector, with call signature
|
| 409 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 410 |
+
respectively.
|
| 411 |
+
:type matvec: function
|
| 412 |
+
:param matvec2:
|
| 413 |
+
Function to apply the second matrix to a vector, with call signature
|
| 414 |
+
`y = matvec2(x)`, where `x` and `y` are the input and output vectors,
|
| 415 |
+
respectively.
|
| 416 |
+
:type matvec2: function
|
| 417 |
+
:param its:
|
| 418 |
+
Number of power method iterations.
|
| 419 |
+
:type its: int
|
| 420 |
+
|
| 421 |
+
:return:
|
| 422 |
+
Spectral norm estimate of matrix difference.
|
| 423 |
+
:rtype: float
|
| 424 |
+
"""
|
| 425 |
+
return _id.idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its)
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
#------------------------------------------------------------------------------
|
| 429 |
+
# idd_svd.f
|
| 430 |
+
#------------------------------------------------------------------------------
|
| 431 |
+
|
| 432 |
+
def iddr_svd(A, k):
|
| 433 |
+
"""
|
| 434 |
+
Compute SVD of a real matrix to a specified rank.
|
| 435 |
+
|
| 436 |
+
:param A:
|
| 437 |
+
Matrix.
|
| 438 |
+
:type A: :class:`numpy.ndarray`
|
| 439 |
+
:param k:
|
| 440 |
+
Rank of SVD.
|
| 441 |
+
:type k: int
|
| 442 |
+
|
| 443 |
+
:return:
|
| 444 |
+
Left singular vectors.
|
| 445 |
+
:rtype: :class:`numpy.ndarray`
|
| 446 |
+
:return:
|
| 447 |
+
Right singular vectors.
|
| 448 |
+
:rtype: :class:`numpy.ndarray`
|
| 449 |
+
:return:
|
| 450 |
+
Singular values.
|
| 451 |
+
:rtype: :class:`numpy.ndarray`
|
| 452 |
+
"""
|
| 453 |
+
A = np.asfortranarray(A)
|
| 454 |
+
U, V, S, ier = _id.iddr_svd(A, k)
|
| 455 |
+
if ier:
|
| 456 |
+
raise _RETCODE_ERROR
|
| 457 |
+
return U, V, S
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
def iddp_svd(eps, A):
|
| 461 |
+
"""
|
| 462 |
+
Compute SVD of a real matrix to a specified relative precision.
|
| 463 |
+
|
| 464 |
+
:param eps:
|
| 465 |
+
Relative precision.
|
| 466 |
+
:type eps: float
|
| 467 |
+
:param A:
|
| 468 |
+
Matrix.
|
| 469 |
+
:type A: :class:`numpy.ndarray`
|
| 470 |
+
|
| 471 |
+
:return:
|
| 472 |
+
Left singular vectors.
|
| 473 |
+
:rtype: :class:`numpy.ndarray`
|
| 474 |
+
:return:
|
| 475 |
+
Right singular vectors.
|
| 476 |
+
:rtype: :class:`numpy.ndarray`
|
| 477 |
+
:return:
|
| 478 |
+
Singular values.
|
| 479 |
+
:rtype: :class:`numpy.ndarray`
|
| 480 |
+
"""
|
| 481 |
+
A = np.asfortranarray(A)
|
| 482 |
+
m, n = A.shape
|
| 483 |
+
k, iU, iV, iS, w, ier = _id.iddp_svd(eps, A)
|
| 484 |
+
if ier:
|
| 485 |
+
raise _RETCODE_ERROR
|
| 486 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 487 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 488 |
+
S = w[iS-1:iS+k-1]
|
| 489 |
+
return U, V, S
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
#------------------------------------------------------------------------------
|
| 493 |
+
# iddp_aid.f
|
| 494 |
+
#------------------------------------------------------------------------------
|
| 495 |
+
|
| 496 |
+
def iddp_aid(eps, A):
|
| 497 |
+
"""
|
| 498 |
+
Compute ID of a real matrix to a specified relative precision using random
|
| 499 |
+
sampling.
|
| 500 |
+
|
| 501 |
+
:param eps:
|
| 502 |
+
Relative precision.
|
| 503 |
+
:type eps: float
|
| 504 |
+
:param A:
|
| 505 |
+
Matrix.
|
| 506 |
+
:type A: :class:`numpy.ndarray`
|
| 507 |
+
|
| 508 |
+
:return:
|
| 509 |
+
Rank of ID.
|
| 510 |
+
:rtype: int
|
| 511 |
+
:return:
|
| 512 |
+
Column index array.
|
| 513 |
+
:rtype: :class:`numpy.ndarray`
|
| 514 |
+
:return:
|
| 515 |
+
Interpolation coefficients.
|
| 516 |
+
:rtype: :class:`numpy.ndarray`
|
| 517 |
+
"""
|
| 518 |
+
A = np.asfortranarray(A)
|
| 519 |
+
m, n = A.shape
|
| 520 |
+
n2, w = idd_frmi(m)
|
| 521 |
+
proj = np.empty(n*(2*n2 + 1) + n2 + 1, order='F')
|
| 522 |
+
k, idx, proj = _id.iddp_aid(eps, A, w, proj)
|
| 523 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 524 |
+
return k, idx, proj
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
def idd_estrank(eps, A):
|
| 528 |
+
"""
|
| 529 |
+
Estimate rank of a real matrix to a specified relative precision using
|
| 530 |
+
random sampling.
|
| 531 |
+
|
| 532 |
+
The output rank is typically about 8 higher than the actual rank.
|
| 533 |
+
|
| 534 |
+
:param eps:
|
| 535 |
+
Relative precision.
|
| 536 |
+
:type eps: float
|
| 537 |
+
:param A:
|
| 538 |
+
Matrix.
|
| 539 |
+
:type A: :class:`numpy.ndarray`
|
| 540 |
+
|
| 541 |
+
:return:
|
| 542 |
+
Rank estimate.
|
| 543 |
+
:rtype: int
|
| 544 |
+
"""
|
| 545 |
+
A = np.asfortranarray(A)
|
| 546 |
+
m, n = A.shape
|
| 547 |
+
n2, w = idd_frmi(m)
|
| 548 |
+
ra = np.empty(n*n2 + (n + 1)*(n2 + 1), order='F')
|
| 549 |
+
k, ra = _id.idd_estrank(eps, A, w, ra)
|
| 550 |
+
return k
|
| 551 |
+
|
| 552 |
+
|
| 553 |
+
#------------------------------------------------------------------------------
|
| 554 |
+
# iddp_asvd.f
|
| 555 |
+
#------------------------------------------------------------------------------
|
| 556 |
+
|
| 557 |
+
def iddp_asvd(eps, A):
|
| 558 |
+
"""
|
| 559 |
+
Compute SVD of a real matrix to a specified relative precision using random
|
| 560 |
+
sampling.
|
| 561 |
+
|
| 562 |
+
:param eps:
|
| 563 |
+
Relative precision.
|
| 564 |
+
:type eps: float
|
| 565 |
+
:param A:
|
| 566 |
+
Matrix.
|
| 567 |
+
:type A: :class:`numpy.ndarray`
|
| 568 |
+
|
| 569 |
+
:return:
|
| 570 |
+
Left singular vectors.
|
| 571 |
+
:rtype: :class:`numpy.ndarray`
|
| 572 |
+
:return:
|
| 573 |
+
Right singular vectors.
|
| 574 |
+
:rtype: :class:`numpy.ndarray`
|
| 575 |
+
:return:
|
| 576 |
+
Singular values.
|
| 577 |
+
:rtype: :class:`numpy.ndarray`
|
| 578 |
+
"""
|
| 579 |
+
A = np.asfortranarray(A)
|
| 580 |
+
m, n = A.shape
|
| 581 |
+
n2, winit = _id.idd_frmi(m)
|
| 582 |
+
w = np.empty(
|
| 583 |
+
max((min(m, n) + 1)*(3*m + 5*n + 1) + 25*min(m, n)**2,
|
| 584 |
+
(2*n + 1)*(n2 + 1)),
|
| 585 |
+
order='F')
|
| 586 |
+
k, iU, iV, iS, w, ier = _id.iddp_asvd(eps, A, winit, w)
|
| 587 |
+
if ier:
|
| 588 |
+
raise _RETCODE_ERROR
|
| 589 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 590 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 591 |
+
S = w[iS-1:iS+k-1]
|
| 592 |
+
return U, V, S
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
#------------------------------------------------------------------------------
|
| 596 |
+
# iddp_rid.f
|
| 597 |
+
#------------------------------------------------------------------------------
|
| 598 |
+
|
| 599 |
+
def iddp_rid(eps, m, n, matvect):
|
| 600 |
+
"""
|
| 601 |
+
Compute ID of a real matrix to a specified relative precision using random
|
| 602 |
+
matrix-vector multiplication.
|
| 603 |
+
|
| 604 |
+
:param eps:
|
| 605 |
+
Relative precision.
|
| 606 |
+
:type eps: float
|
| 607 |
+
:param m:
|
| 608 |
+
Matrix row dimension.
|
| 609 |
+
:type m: int
|
| 610 |
+
:param n:
|
| 611 |
+
Matrix column dimension.
|
| 612 |
+
:type n: int
|
| 613 |
+
:param matvect:
|
| 614 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 615 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 616 |
+
respectively.
|
| 617 |
+
:type matvect: function
|
| 618 |
+
|
| 619 |
+
:return:
|
| 620 |
+
Rank of ID.
|
| 621 |
+
:rtype: int
|
| 622 |
+
:return:
|
| 623 |
+
Column index array.
|
| 624 |
+
:rtype: :class:`numpy.ndarray`
|
| 625 |
+
:return:
|
| 626 |
+
Interpolation coefficients.
|
| 627 |
+
:rtype: :class:`numpy.ndarray`
|
| 628 |
+
"""
|
| 629 |
+
proj = np.empty(m + 1 + 2*n*(min(m, n) + 1), order='F')
|
| 630 |
+
k, idx, proj, ier = _id.iddp_rid(eps, m, n, matvect, proj)
|
| 631 |
+
if ier != 0:
|
| 632 |
+
raise _RETCODE_ERROR
|
| 633 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 634 |
+
return k, idx, proj
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
def idd_findrank(eps, m, n, matvect):
|
| 638 |
+
"""
|
| 639 |
+
Estimate rank of a real matrix to a specified relative precision using
|
| 640 |
+
random matrix-vector multiplication.
|
| 641 |
+
|
| 642 |
+
:param eps:
|
| 643 |
+
Relative precision.
|
| 644 |
+
:type eps: float
|
| 645 |
+
:param m:
|
| 646 |
+
Matrix row dimension.
|
| 647 |
+
:type m: int
|
| 648 |
+
:param n:
|
| 649 |
+
Matrix column dimension.
|
| 650 |
+
:type n: int
|
| 651 |
+
:param matvect:
|
| 652 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 653 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 654 |
+
respectively.
|
| 655 |
+
:type matvect: function
|
| 656 |
+
|
| 657 |
+
:return:
|
| 658 |
+
Rank estimate.
|
| 659 |
+
:rtype: int
|
| 660 |
+
"""
|
| 661 |
+
k, ra, ier = _id.idd_findrank(eps, m, n, matvect)
|
| 662 |
+
if ier:
|
| 663 |
+
raise _RETCODE_ERROR
|
| 664 |
+
return k
|
| 665 |
+
|
| 666 |
+
|
| 667 |
+
#------------------------------------------------------------------------------
|
| 668 |
+
# iddp_rsvd.f
|
| 669 |
+
#------------------------------------------------------------------------------
|
| 670 |
+
|
| 671 |
+
def iddp_rsvd(eps, m, n, matvect, matvec):
|
| 672 |
+
"""
|
| 673 |
+
Compute SVD of a real matrix to a specified relative precision using random
|
| 674 |
+
matrix-vector multiplication.
|
| 675 |
+
|
| 676 |
+
:param eps:
|
| 677 |
+
Relative precision.
|
| 678 |
+
:type eps: float
|
| 679 |
+
:param m:
|
| 680 |
+
Matrix row dimension.
|
| 681 |
+
:type m: int
|
| 682 |
+
:param n:
|
| 683 |
+
Matrix column dimension.
|
| 684 |
+
:type n: int
|
| 685 |
+
:param matvect:
|
| 686 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 687 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 688 |
+
respectively.
|
| 689 |
+
:type matvect: function
|
| 690 |
+
:param matvec:
|
| 691 |
+
Function to apply the matrix to a vector, with call signature
|
| 692 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 693 |
+
respectively.
|
| 694 |
+
:type matvec: function
|
| 695 |
+
|
| 696 |
+
:return:
|
| 697 |
+
Left singular vectors.
|
| 698 |
+
:rtype: :class:`numpy.ndarray`
|
| 699 |
+
:return:
|
| 700 |
+
Right singular vectors.
|
| 701 |
+
:rtype: :class:`numpy.ndarray`
|
| 702 |
+
:return:
|
| 703 |
+
Singular values.
|
| 704 |
+
:rtype: :class:`numpy.ndarray`
|
| 705 |
+
"""
|
| 706 |
+
k, iU, iV, iS, w, ier = _id.iddp_rsvd(eps, m, n, matvect, matvec)
|
| 707 |
+
if ier:
|
| 708 |
+
raise _RETCODE_ERROR
|
| 709 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 710 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 711 |
+
S = w[iS-1:iS+k-1]
|
| 712 |
+
return U, V, S
|
| 713 |
+
|
| 714 |
+
|
| 715 |
+
#------------------------------------------------------------------------------
|
| 716 |
+
# iddr_aid.f
|
| 717 |
+
#------------------------------------------------------------------------------
|
| 718 |
+
|
| 719 |
+
def iddr_aid(A, k):
|
| 720 |
+
"""
|
| 721 |
+
Compute ID of a real matrix to a specified rank using random sampling.
|
| 722 |
+
|
| 723 |
+
:param A:
|
| 724 |
+
Matrix.
|
| 725 |
+
:type A: :class:`numpy.ndarray`
|
| 726 |
+
:param k:
|
| 727 |
+
Rank of ID.
|
| 728 |
+
:type k: int
|
| 729 |
+
|
| 730 |
+
:return:
|
| 731 |
+
Column index array.
|
| 732 |
+
:rtype: :class:`numpy.ndarray`
|
| 733 |
+
:return:
|
| 734 |
+
Interpolation coefficients.
|
| 735 |
+
:rtype: :class:`numpy.ndarray`
|
| 736 |
+
"""
|
| 737 |
+
A = np.asfortranarray(A)
|
| 738 |
+
m, n = A.shape
|
| 739 |
+
w = iddr_aidi(m, n, k)
|
| 740 |
+
idx, proj = _id.iddr_aid(A, k, w)
|
| 741 |
+
if k == n:
|
| 742 |
+
proj = np.empty((k, n-k), dtype='float64', order='F')
|
| 743 |
+
else:
|
| 744 |
+
proj = proj.reshape((k, n-k), order='F')
|
| 745 |
+
return idx, proj
|
| 746 |
+
|
| 747 |
+
|
| 748 |
+
def iddr_aidi(m, n, k):
|
| 749 |
+
"""
|
| 750 |
+
Initialize array for :func:`iddr_aid`.
|
| 751 |
+
|
| 752 |
+
:param m:
|
| 753 |
+
Matrix row dimension.
|
| 754 |
+
:type m: int
|
| 755 |
+
:param n:
|
| 756 |
+
Matrix column dimension.
|
| 757 |
+
:type n: int
|
| 758 |
+
:param k:
|
| 759 |
+
Rank of ID.
|
| 760 |
+
:type k: int
|
| 761 |
+
|
| 762 |
+
:return:
|
| 763 |
+
Initialization array to be used by :func:`iddr_aid`.
|
| 764 |
+
:rtype: :class:`numpy.ndarray`
|
| 765 |
+
"""
|
| 766 |
+
return _id.iddr_aidi(m, n, k)
|
| 767 |
+
|
| 768 |
+
|
| 769 |
+
#------------------------------------------------------------------------------
|
| 770 |
+
# iddr_asvd.f
|
| 771 |
+
#------------------------------------------------------------------------------
|
| 772 |
+
|
| 773 |
+
def iddr_asvd(A, k):
|
| 774 |
+
"""
|
| 775 |
+
Compute SVD of a real matrix to a specified rank using random sampling.
|
| 776 |
+
|
| 777 |
+
:param A:
|
| 778 |
+
Matrix.
|
| 779 |
+
:type A: :class:`numpy.ndarray`
|
| 780 |
+
:param k:
|
| 781 |
+
Rank of SVD.
|
| 782 |
+
:type k: int
|
| 783 |
+
|
| 784 |
+
:return:
|
| 785 |
+
Left singular vectors.
|
| 786 |
+
:rtype: :class:`numpy.ndarray`
|
| 787 |
+
:return:
|
| 788 |
+
Right singular vectors.
|
| 789 |
+
:rtype: :class:`numpy.ndarray`
|
| 790 |
+
:return:
|
| 791 |
+
Singular values.
|
| 792 |
+
:rtype: :class:`numpy.ndarray`
|
| 793 |
+
"""
|
| 794 |
+
A = np.asfortranarray(A)
|
| 795 |
+
m, n = A.shape
|
| 796 |
+
w = np.empty((2*k + 28)*m + (6*k + 21)*n + 25*k**2 + 100, order='F')
|
| 797 |
+
w_ = iddr_aidi(m, n, k)
|
| 798 |
+
w[:w_.size] = w_
|
| 799 |
+
U, V, S, ier = _id.iddr_asvd(A, k, w)
|
| 800 |
+
if ier != 0:
|
| 801 |
+
raise _RETCODE_ERROR
|
| 802 |
+
return U, V, S
|
| 803 |
+
|
| 804 |
+
|
| 805 |
+
#------------------------------------------------------------------------------
|
| 806 |
+
# iddr_rid.f
|
| 807 |
+
#------------------------------------------------------------------------------
|
| 808 |
+
|
| 809 |
+
def iddr_rid(m, n, matvect, k):
|
| 810 |
+
"""
|
| 811 |
+
Compute ID of a real matrix to a specified rank using random matrix-vector
|
| 812 |
+
multiplication.
|
| 813 |
+
|
| 814 |
+
:param m:
|
| 815 |
+
Matrix row dimension.
|
| 816 |
+
:type m: int
|
| 817 |
+
:param n:
|
| 818 |
+
Matrix column dimension.
|
| 819 |
+
:type n: int
|
| 820 |
+
:param matvect:
|
| 821 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 822 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 823 |
+
respectively.
|
| 824 |
+
:type matvect: function
|
| 825 |
+
:param k:
|
| 826 |
+
Rank of ID.
|
| 827 |
+
:type k: int
|
| 828 |
+
|
| 829 |
+
:return:
|
| 830 |
+
Column index array.
|
| 831 |
+
:rtype: :class:`numpy.ndarray`
|
| 832 |
+
:return:
|
| 833 |
+
Interpolation coefficients.
|
| 834 |
+
:rtype: :class:`numpy.ndarray`
|
| 835 |
+
"""
|
| 836 |
+
idx, proj = _id.iddr_rid(m, n, matvect, k)
|
| 837 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 838 |
+
return idx, proj
|
| 839 |
+
|
| 840 |
+
|
| 841 |
+
#------------------------------------------------------------------------------
|
| 842 |
+
# iddr_rsvd.f
|
| 843 |
+
#------------------------------------------------------------------------------
|
| 844 |
+
|
| 845 |
+
def iddr_rsvd(m, n, matvect, matvec, k):
|
| 846 |
+
"""
|
| 847 |
+
Compute SVD of a real matrix to a specified rank using random matrix-vector
|
| 848 |
+
multiplication.
|
| 849 |
+
|
| 850 |
+
:param m:
|
| 851 |
+
Matrix row dimension.
|
| 852 |
+
:type m: int
|
| 853 |
+
:param n:
|
| 854 |
+
Matrix column dimension.
|
| 855 |
+
:type n: int
|
| 856 |
+
:param matvect:
|
| 857 |
+
Function to apply the matrix transpose to a vector, with call signature
|
| 858 |
+
`y = matvect(x)`, where `x` and `y` are the input and output vectors,
|
| 859 |
+
respectively.
|
| 860 |
+
:type matvect: function
|
| 861 |
+
:param matvec:
|
| 862 |
+
Function to apply the matrix to a vector, with call signature
|
| 863 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 864 |
+
respectively.
|
| 865 |
+
:type matvec: function
|
| 866 |
+
:param k:
|
| 867 |
+
Rank of SVD.
|
| 868 |
+
:type k: int
|
| 869 |
+
|
| 870 |
+
:return:
|
| 871 |
+
Left singular vectors.
|
| 872 |
+
:rtype: :class:`numpy.ndarray`
|
| 873 |
+
:return:
|
| 874 |
+
Right singular vectors.
|
| 875 |
+
:rtype: :class:`numpy.ndarray`
|
| 876 |
+
:return:
|
| 877 |
+
Singular values.
|
| 878 |
+
:rtype: :class:`numpy.ndarray`
|
| 879 |
+
"""
|
| 880 |
+
U, V, S, ier = _id.iddr_rsvd(m, n, matvect, matvec, k)
|
| 881 |
+
if ier != 0:
|
| 882 |
+
raise _RETCODE_ERROR
|
| 883 |
+
return U, V, S
|
| 884 |
+
|
| 885 |
+
|
| 886 |
+
#------------------------------------------------------------------------------
|
| 887 |
+
# idz_frm.f
|
| 888 |
+
#------------------------------------------------------------------------------
|
| 889 |
+
|
| 890 |
+
def idz_frm(n, w, x):
|
| 891 |
+
"""
|
| 892 |
+
Transform complex vector via a composition of Rokhlin's random transform,
|
| 893 |
+
random subselection, and an FFT.
|
| 894 |
+
|
| 895 |
+
In contrast to :func:`idz_sfrm`, this routine works best when the length of
|
| 896 |
+
the transformed vector is the power-of-two integer output by
|
| 897 |
+
:func:`idz_frmi`, or when the length is not specified but instead
|
| 898 |
+
determined a posteriori from the output. The returned transformed vector is
|
| 899 |
+
randomly permuted.
|
| 900 |
+
|
| 901 |
+
:param n:
|
| 902 |
+
Greatest power-of-two integer satisfying `n <= x.size` as obtained from
|
| 903 |
+
:func:`idz_frmi`; `n` is also the length of the output vector.
|
| 904 |
+
:type n: int
|
| 905 |
+
:param w:
|
| 906 |
+
Initialization array constructed by :func:`idz_frmi`.
|
| 907 |
+
:type w: :class:`numpy.ndarray`
|
| 908 |
+
:param x:
|
| 909 |
+
Vector to be transformed.
|
| 910 |
+
:type x: :class:`numpy.ndarray`
|
| 911 |
+
|
| 912 |
+
:return:
|
| 913 |
+
Transformed vector.
|
| 914 |
+
:rtype: :class:`numpy.ndarray`
|
| 915 |
+
"""
|
| 916 |
+
return _id.idz_frm(n, w, x)
|
| 917 |
+
|
| 918 |
+
|
| 919 |
+
def idz_sfrm(l, n, w, x):
|
| 920 |
+
"""
|
| 921 |
+
Transform complex vector via a composition of Rokhlin's random transform,
|
| 922 |
+
random subselection, and an FFT.
|
| 923 |
+
|
| 924 |
+
In contrast to :func:`idz_frm`, this routine works best when the length of
|
| 925 |
+
the transformed vector is known a priori.
|
| 926 |
+
|
| 927 |
+
:param l:
|
| 928 |
+
Length of transformed vector, satisfying `l <= n`.
|
| 929 |
+
:type l: int
|
| 930 |
+
:param n:
|
| 931 |
+
Greatest power-of-two integer satisfying `n <= x.size` as obtained from
|
| 932 |
+
:func:`idz_sfrmi`.
|
| 933 |
+
:type n: int
|
| 934 |
+
:param w:
|
| 935 |
+
Initialization array constructed by :func:`idd_sfrmi`.
|
| 936 |
+
:type w: :class:`numpy.ndarray`
|
| 937 |
+
:param x:
|
| 938 |
+
Vector to be transformed.
|
| 939 |
+
:type x: :class:`numpy.ndarray`
|
| 940 |
+
|
| 941 |
+
:return:
|
| 942 |
+
Transformed vector.
|
| 943 |
+
:rtype: :class:`numpy.ndarray`
|
| 944 |
+
"""
|
| 945 |
+
return _id.idz_sfrm(l, n, w, x)
|
| 946 |
+
|
| 947 |
+
|
| 948 |
+
def idz_frmi(m):
|
| 949 |
+
"""
|
| 950 |
+
Initialize data for :func:`idz_frm`.
|
| 951 |
+
|
| 952 |
+
:param m:
|
| 953 |
+
Length of vector to be transformed.
|
| 954 |
+
:type m: int
|
| 955 |
+
|
| 956 |
+
:return:
|
| 957 |
+
Greatest power-of-two integer `n` satisfying `n <= m`.
|
| 958 |
+
:rtype: int
|
| 959 |
+
:return:
|
| 960 |
+
Initialization array to be used by :func:`idz_frm`.
|
| 961 |
+
:rtype: :class:`numpy.ndarray`
|
| 962 |
+
"""
|
| 963 |
+
return _id.idz_frmi(m)
|
| 964 |
+
|
| 965 |
+
|
| 966 |
+
def idz_sfrmi(l, m):
|
| 967 |
+
"""
|
| 968 |
+
Initialize data for :func:`idz_sfrm`.
|
| 969 |
+
|
| 970 |
+
:param l:
|
| 971 |
+
Length of output transformed vector.
|
| 972 |
+
:type l: int
|
| 973 |
+
:param m:
|
| 974 |
+
Length of the vector to be transformed.
|
| 975 |
+
:type m: int
|
| 976 |
+
|
| 977 |
+
:return:
|
| 978 |
+
Greatest power-of-two integer `n` satisfying `n <= m`.
|
| 979 |
+
:rtype: int
|
| 980 |
+
:return:
|
| 981 |
+
Initialization array to be used by :func:`idz_sfrm`.
|
| 982 |
+
:rtype: :class:`numpy.ndarray`
|
| 983 |
+
"""
|
| 984 |
+
return _id.idz_sfrmi(l, m)
|
| 985 |
+
|
| 986 |
+
|
| 987 |
+
#------------------------------------------------------------------------------
|
| 988 |
+
# idz_id.f
|
| 989 |
+
#------------------------------------------------------------------------------
|
| 990 |
+
|
| 991 |
+
def idzp_id(eps, A):
|
| 992 |
+
"""
|
| 993 |
+
Compute ID of a complex matrix to a specified relative precision.
|
| 994 |
+
|
| 995 |
+
:param eps:
|
| 996 |
+
Relative precision.
|
| 997 |
+
:type eps: float
|
| 998 |
+
:param A:
|
| 999 |
+
Matrix.
|
| 1000 |
+
:type A: :class:`numpy.ndarray`
|
| 1001 |
+
|
| 1002 |
+
:return:
|
| 1003 |
+
Rank of ID.
|
| 1004 |
+
:rtype: int
|
| 1005 |
+
:return:
|
| 1006 |
+
Column index array.
|
| 1007 |
+
:rtype: :class:`numpy.ndarray`
|
| 1008 |
+
:return:
|
| 1009 |
+
Interpolation coefficients.
|
| 1010 |
+
:rtype: :class:`numpy.ndarray`
|
| 1011 |
+
"""
|
| 1012 |
+
A = _asfortranarray_copy(A)
|
| 1013 |
+
k, idx, rnorms = _id.idzp_id(eps, A)
|
| 1014 |
+
n = A.shape[1]
|
| 1015 |
+
proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
|
| 1016 |
+
return k, idx, proj
|
| 1017 |
+
|
| 1018 |
+
|
| 1019 |
+
def idzr_id(A, k):
|
| 1020 |
+
"""
|
| 1021 |
+
Compute ID of a complex matrix to a specified rank.
|
| 1022 |
+
|
| 1023 |
+
:param A:
|
| 1024 |
+
Matrix.
|
| 1025 |
+
:type A: :class:`numpy.ndarray`
|
| 1026 |
+
:param k:
|
| 1027 |
+
Rank of ID.
|
| 1028 |
+
:type k: int
|
| 1029 |
+
|
| 1030 |
+
:return:
|
| 1031 |
+
Column index array.
|
| 1032 |
+
:rtype: :class:`numpy.ndarray`
|
| 1033 |
+
:return:
|
| 1034 |
+
Interpolation coefficients.
|
| 1035 |
+
:rtype: :class:`numpy.ndarray`
|
| 1036 |
+
"""
|
| 1037 |
+
A = _asfortranarray_copy(A)
|
| 1038 |
+
idx, rnorms = _id.idzr_id(A, k)
|
| 1039 |
+
n = A.shape[1]
|
| 1040 |
+
proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
|
| 1041 |
+
return idx, proj
|
| 1042 |
+
|
| 1043 |
+
|
| 1044 |
+
def idz_reconid(B, idx, proj):
|
| 1045 |
+
"""
|
| 1046 |
+
Reconstruct matrix from complex ID.
|
| 1047 |
+
|
| 1048 |
+
:param B:
|
| 1049 |
+
Skeleton matrix.
|
| 1050 |
+
:type B: :class:`numpy.ndarray`
|
| 1051 |
+
:param idx:
|
| 1052 |
+
Column index array.
|
| 1053 |
+
:type idx: :class:`numpy.ndarray`
|
| 1054 |
+
:param proj:
|
| 1055 |
+
Interpolation coefficients.
|
| 1056 |
+
:type proj: :class:`numpy.ndarray`
|
| 1057 |
+
|
| 1058 |
+
:return:
|
| 1059 |
+
Reconstructed matrix.
|
| 1060 |
+
:rtype: :class:`numpy.ndarray`
|
| 1061 |
+
"""
|
| 1062 |
+
B = np.asfortranarray(B)
|
| 1063 |
+
if proj.size > 0:
|
| 1064 |
+
return _id.idz_reconid(B, idx, proj)
|
| 1065 |
+
else:
|
| 1066 |
+
return B[:, np.argsort(idx)]
|
| 1067 |
+
|
| 1068 |
+
|
| 1069 |
+
def idz_reconint(idx, proj):
|
| 1070 |
+
"""
|
| 1071 |
+
Reconstruct interpolation matrix from complex ID.
|
| 1072 |
+
|
| 1073 |
+
:param idx:
|
| 1074 |
+
Column index array.
|
| 1075 |
+
:type idx: :class:`numpy.ndarray`
|
| 1076 |
+
:param proj:
|
| 1077 |
+
Interpolation coefficients.
|
| 1078 |
+
:type proj: :class:`numpy.ndarray`
|
| 1079 |
+
|
| 1080 |
+
:return:
|
| 1081 |
+
Interpolation matrix.
|
| 1082 |
+
:rtype: :class:`numpy.ndarray`
|
| 1083 |
+
"""
|
| 1084 |
+
return _id.idz_reconint(idx, proj)
|
| 1085 |
+
|
| 1086 |
+
|
| 1087 |
+
def idz_copycols(A, k, idx):
|
| 1088 |
+
"""
|
| 1089 |
+
Reconstruct skeleton matrix from complex ID.
|
| 1090 |
+
|
| 1091 |
+
:param A:
|
| 1092 |
+
Original matrix.
|
| 1093 |
+
:type A: :class:`numpy.ndarray`
|
| 1094 |
+
:param k:
|
| 1095 |
+
Rank of ID.
|
| 1096 |
+
:type k: int
|
| 1097 |
+
:param idx:
|
| 1098 |
+
Column index array.
|
| 1099 |
+
:type idx: :class:`numpy.ndarray`
|
| 1100 |
+
|
| 1101 |
+
:return:
|
| 1102 |
+
Skeleton matrix.
|
| 1103 |
+
:rtype: :class:`numpy.ndarray`
|
| 1104 |
+
"""
|
| 1105 |
+
A = np.asfortranarray(A)
|
| 1106 |
+
return _id.idz_copycols(A, k, idx)
|
| 1107 |
+
|
| 1108 |
+
|
| 1109 |
+
#------------------------------------------------------------------------------
|
| 1110 |
+
# idz_id2svd.f
|
| 1111 |
+
#------------------------------------------------------------------------------
|
| 1112 |
+
|
| 1113 |
+
def idz_id2svd(B, idx, proj):
|
| 1114 |
+
"""
|
| 1115 |
+
Convert complex ID to SVD.
|
| 1116 |
+
|
| 1117 |
+
:param B:
|
| 1118 |
+
Skeleton matrix.
|
| 1119 |
+
:type B: :class:`numpy.ndarray`
|
| 1120 |
+
:param idx:
|
| 1121 |
+
Column index array.
|
| 1122 |
+
:type idx: :class:`numpy.ndarray`
|
| 1123 |
+
:param proj:
|
| 1124 |
+
Interpolation coefficients.
|
| 1125 |
+
:type proj: :class:`numpy.ndarray`
|
| 1126 |
+
|
| 1127 |
+
:return:
|
| 1128 |
+
Left singular vectors.
|
| 1129 |
+
:rtype: :class:`numpy.ndarray`
|
| 1130 |
+
:return:
|
| 1131 |
+
Right singular vectors.
|
| 1132 |
+
:rtype: :class:`numpy.ndarray`
|
| 1133 |
+
:return:
|
| 1134 |
+
Singular values.
|
| 1135 |
+
:rtype: :class:`numpy.ndarray`
|
| 1136 |
+
"""
|
| 1137 |
+
B = np.asfortranarray(B)
|
| 1138 |
+
U, V, S, ier = _id.idz_id2svd(B, idx, proj)
|
| 1139 |
+
if ier:
|
| 1140 |
+
raise _RETCODE_ERROR
|
| 1141 |
+
return U, V, S
|
| 1142 |
+
|
| 1143 |
+
|
| 1144 |
+
#------------------------------------------------------------------------------
|
| 1145 |
+
# idz_snorm.f
|
| 1146 |
+
#------------------------------------------------------------------------------
|
| 1147 |
+
|
| 1148 |
+
def idz_snorm(m, n, matveca, matvec, its=20):
|
| 1149 |
+
"""
|
| 1150 |
+
Estimate spectral norm of a complex matrix by the randomized power method.
|
| 1151 |
+
|
| 1152 |
+
:param m:
|
| 1153 |
+
Matrix row dimension.
|
| 1154 |
+
:type m: int
|
| 1155 |
+
:param n:
|
| 1156 |
+
Matrix column dimension.
|
| 1157 |
+
:type n: int
|
| 1158 |
+
:param matveca:
|
| 1159 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1160 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1161 |
+
respectively.
|
| 1162 |
+
:type matveca: function
|
| 1163 |
+
:param matvec:
|
| 1164 |
+
Function to apply the matrix to a vector, with call signature
|
| 1165 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 1166 |
+
respectively.
|
| 1167 |
+
:type matvec: function
|
| 1168 |
+
:param its:
|
| 1169 |
+
Number of power method iterations.
|
| 1170 |
+
:type its: int
|
| 1171 |
+
|
| 1172 |
+
:return:
|
| 1173 |
+
Spectral norm estimate.
|
| 1174 |
+
:rtype: float
|
| 1175 |
+
"""
|
| 1176 |
+
snorm, v = _id.idz_snorm(m, n, matveca, matvec, its)
|
| 1177 |
+
return snorm
|
| 1178 |
+
|
| 1179 |
+
|
| 1180 |
+
def idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its=20):
|
| 1181 |
+
"""
|
| 1182 |
+
Estimate spectral norm of the difference of two complex matrices by the
|
| 1183 |
+
randomized power method.
|
| 1184 |
+
|
| 1185 |
+
:param m:
|
| 1186 |
+
Matrix row dimension.
|
| 1187 |
+
:type m: int
|
| 1188 |
+
:param n:
|
| 1189 |
+
Matrix column dimension.
|
| 1190 |
+
:type n: int
|
| 1191 |
+
:param matveca:
|
| 1192 |
+
Function to apply the adjoint of the first matrix to a vector, with
|
| 1193 |
+
call signature `y = matveca(x)`, where `x` and `y` are the input and
|
| 1194 |
+
output vectors, respectively.
|
| 1195 |
+
:type matveca: function
|
| 1196 |
+
:param matveca2:
|
| 1197 |
+
Function to apply the adjoint of the second matrix to a vector, with
|
| 1198 |
+
call signature `y = matveca2(x)`, where `x` and `y` are the input and
|
| 1199 |
+
output vectors, respectively.
|
| 1200 |
+
:type matveca2: function
|
| 1201 |
+
:param matvec:
|
| 1202 |
+
Function to apply the first matrix to a vector, with call signature
|
| 1203 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 1204 |
+
respectively.
|
| 1205 |
+
:type matvec: function
|
| 1206 |
+
:param matvec2:
|
| 1207 |
+
Function to apply the second matrix to a vector, with call signature
|
| 1208 |
+
`y = matvec2(x)`, where `x` and `y` are the input and output vectors,
|
| 1209 |
+
respectively.
|
| 1210 |
+
:type matvec2: function
|
| 1211 |
+
:param its:
|
| 1212 |
+
Number of power method iterations.
|
| 1213 |
+
:type its: int
|
| 1214 |
+
|
| 1215 |
+
:return:
|
| 1216 |
+
Spectral norm estimate of matrix difference.
|
| 1217 |
+
:rtype: float
|
| 1218 |
+
"""
|
| 1219 |
+
return _id.idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its)
|
| 1220 |
+
|
| 1221 |
+
|
| 1222 |
+
#------------------------------------------------------------------------------
|
| 1223 |
+
# idz_svd.f
|
| 1224 |
+
#------------------------------------------------------------------------------
|
| 1225 |
+
|
| 1226 |
+
def idzr_svd(A, k):
|
| 1227 |
+
"""
|
| 1228 |
+
Compute SVD of a complex matrix to a specified rank.
|
| 1229 |
+
|
| 1230 |
+
:param A:
|
| 1231 |
+
Matrix.
|
| 1232 |
+
:type A: :class:`numpy.ndarray`
|
| 1233 |
+
:param k:
|
| 1234 |
+
Rank of SVD.
|
| 1235 |
+
:type k: int
|
| 1236 |
+
|
| 1237 |
+
:return:
|
| 1238 |
+
Left singular vectors.
|
| 1239 |
+
:rtype: :class:`numpy.ndarray`
|
| 1240 |
+
:return:
|
| 1241 |
+
Right singular vectors.
|
| 1242 |
+
:rtype: :class:`numpy.ndarray`
|
| 1243 |
+
:return:
|
| 1244 |
+
Singular values.
|
| 1245 |
+
:rtype: :class:`numpy.ndarray`
|
| 1246 |
+
"""
|
| 1247 |
+
A = np.asfortranarray(A)
|
| 1248 |
+
U, V, S, ier = _id.idzr_svd(A, k)
|
| 1249 |
+
if ier:
|
| 1250 |
+
raise _RETCODE_ERROR
|
| 1251 |
+
return U, V, S
|
| 1252 |
+
|
| 1253 |
+
|
| 1254 |
+
def idzp_svd(eps, A):
|
| 1255 |
+
"""
|
| 1256 |
+
Compute SVD of a complex matrix to a specified relative precision.
|
| 1257 |
+
|
| 1258 |
+
:param eps:
|
| 1259 |
+
Relative precision.
|
| 1260 |
+
:type eps: float
|
| 1261 |
+
:param A:
|
| 1262 |
+
Matrix.
|
| 1263 |
+
:type A: :class:`numpy.ndarray`
|
| 1264 |
+
|
| 1265 |
+
:return:
|
| 1266 |
+
Left singular vectors.
|
| 1267 |
+
:rtype: :class:`numpy.ndarray`
|
| 1268 |
+
:return:
|
| 1269 |
+
Right singular vectors.
|
| 1270 |
+
:rtype: :class:`numpy.ndarray`
|
| 1271 |
+
:return:
|
| 1272 |
+
Singular values.
|
| 1273 |
+
:rtype: :class:`numpy.ndarray`
|
| 1274 |
+
"""
|
| 1275 |
+
A = np.asfortranarray(A)
|
| 1276 |
+
m, n = A.shape
|
| 1277 |
+
k, iU, iV, iS, w, ier = _id.idzp_svd(eps, A)
|
| 1278 |
+
if ier:
|
| 1279 |
+
raise _RETCODE_ERROR
|
| 1280 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 1281 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 1282 |
+
S = w[iS-1:iS+k-1]
|
| 1283 |
+
return U, V, S
|
| 1284 |
+
|
| 1285 |
+
|
| 1286 |
+
#------------------------------------------------------------------------------
|
| 1287 |
+
# idzp_aid.f
|
| 1288 |
+
#------------------------------------------------------------------------------
|
| 1289 |
+
|
| 1290 |
+
def idzp_aid(eps, A):
|
| 1291 |
+
"""
|
| 1292 |
+
Compute ID of a complex matrix to a specified relative precision using
|
| 1293 |
+
random sampling.
|
| 1294 |
+
|
| 1295 |
+
:param eps:
|
| 1296 |
+
Relative precision.
|
| 1297 |
+
:type eps: float
|
| 1298 |
+
:param A:
|
| 1299 |
+
Matrix.
|
| 1300 |
+
:type A: :class:`numpy.ndarray`
|
| 1301 |
+
|
| 1302 |
+
:return:
|
| 1303 |
+
Rank of ID.
|
| 1304 |
+
:rtype: int
|
| 1305 |
+
:return:
|
| 1306 |
+
Column index array.
|
| 1307 |
+
:rtype: :class:`numpy.ndarray`
|
| 1308 |
+
:return:
|
| 1309 |
+
Interpolation coefficients.
|
| 1310 |
+
:rtype: :class:`numpy.ndarray`
|
| 1311 |
+
"""
|
| 1312 |
+
A = np.asfortranarray(A)
|
| 1313 |
+
m, n = A.shape
|
| 1314 |
+
n2, w = idz_frmi(m)
|
| 1315 |
+
proj = np.empty(n*(2*n2 + 1) + n2 + 1, dtype='complex128', order='F')
|
| 1316 |
+
k, idx, proj = _id.idzp_aid(eps, A, w, proj)
|
| 1317 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 1318 |
+
return k, idx, proj
|
| 1319 |
+
|
| 1320 |
+
|
| 1321 |
+
def idz_estrank(eps, A):
|
| 1322 |
+
"""
|
| 1323 |
+
Estimate rank of a complex matrix to a specified relative precision using
|
| 1324 |
+
random sampling.
|
| 1325 |
+
|
| 1326 |
+
The output rank is typically about 8 higher than the actual rank.
|
| 1327 |
+
|
| 1328 |
+
:param eps:
|
| 1329 |
+
Relative precision.
|
| 1330 |
+
:type eps: float
|
| 1331 |
+
:param A:
|
| 1332 |
+
Matrix.
|
| 1333 |
+
:type A: :class:`numpy.ndarray`
|
| 1334 |
+
|
| 1335 |
+
:return:
|
| 1336 |
+
Rank estimate.
|
| 1337 |
+
:rtype: int
|
| 1338 |
+
"""
|
| 1339 |
+
A = np.asfortranarray(A)
|
| 1340 |
+
m, n = A.shape
|
| 1341 |
+
n2, w = idz_frmi(m)
|
| 1342 |
+
ra = np.empty(n*n2 + (n + 1)*(n2 + 1), dtype='complex128', order='F')
|
| 1343 |
+
k, ra = _id.idz_estrank(eps, A, w, ra)
|
| 1344 |
+
return k
|
| 1345 |
+
|
| 1346 |
+
|
| 1347 |
+
#------------------------------------------------------------------------------
|
| 1348 |
+
# idzp_asvd.f
|
| 1349 |
+
#------------------------------------------------------------------------------
|
| 1350 |
+
|
| 1351 |
+
def idzp_asvd(eps, A):
|
| 1352 |
+
"""
|
| 1353 |
+
Compute SVD of a complex matrix to a specified relative precision using
|
| 1354 |
+
random sampling.
|
| 1355 |
+
|
| 1356 |
+
:param eps:
|
| 1357 |
+
Relative precision.
|
| 1358 |
+
:type eps: float
|
| 1359 |
+
:param A:
|
| 1360 |
+
Matrix.
|
| 1361 |
+
:type A: :class:`numpy.ndarray`
|
| 1362 |
+
|
| 1363 |
+
:return:
|
| 1364 |
+
Left singular vectors.
|
| 1365 |
+
:rtype: :class:`numpy.ndarray`
|
| 1366 |
+
:return:
|
| 1367 |
+
Right singular vectors.
|
| 1368 |
+
:rtype: :class:`numpy.ndarray`
|
| 1369 |
+
:return:
|
| 1370 |
+
Singular values.
|
| 1371 |
+
:rtype: :class:`numpy.ndarray`
|
| 1372 |
+
"""
|
| 1373 |
+
A = np.asfortranarray(A)
|
| 1374 |
+
m, n = A.shape
|
| 1375 |
+
n2, winit = _id.idz_frmi(m)
|
| 1376 |
+
w = np.empty(
|
| 1377 |
+
max((min(m, n) + 1)*(3*m + 5*n + 11) + 8*min(m, n)**2,
|
| 1378 |
+
(2*n + 1)*(n2 + 1)),
|
| 1379 |
+
dtype=np.complex128, order='F')
|
| 1380 |
+
k, iU, iV, iS, w, ier = _id.idzp_asvd(eps, A, winit, w)
|
| 1381 |
+
if ier:
|
| 1382 |
+
raise _RETCODE_ERROR
|
| 1383 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 1384 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 1385 |
+
S = w[iS-1:iS+k-1]
|
| 1386 |
+
return U, V, S
|
| 1387 |
+
|
| 1388 |
+
|
| 1389 |
+
#------------------------------------------------------------------------------
|
| 1390 |
+
# idzp_rid.f
|
| 1391 |
+
#------------------------------------------------------------------------------
|
| 1392 |
+
|
| 1393 |
+
def idzp_rid(eps, m, n, matveca):
|
| 1394 |
+
"""
|
| 1395 |
+
Compute ID of a complex matrix to a specified relative precision using
|
| 1396 |
+
random matrix-vector multiplication.
|
| 1397 |
+
|
| 1398 |
+
:param eps:
|
| 1399 |
+
Relative precision.
|
| 1400 |
+
:type eps: float
|
| 1401 |
+
:param m:
|
| 1402 |
+
Matrix row dimension.
|
| 1403 |
+
:type m: int
|
| 1404 |
+
:param n:
|
| 1405 |
+
Matrix column dimension.
|
| 1406 |
+
:type n: int
|
| 1407 |
+
:param matveca:
|
| 1408 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1409 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1410 |
+
respectively.
|
| 1411 |
+
:type matveca: function
|
| 1412 |
+
|
| 1413 |
+
:return:
|
| 1414 |
+
Rank of ID.
|
| 1415 |
+
:rtype: int
|
| 1416 |
+
:return:
|
| 1417 |
+
Column index array.
|
| 1418 |
+
:rtype: :class:`numpy.ndarray`
|
| 1419 |
+
:return:
|
| 1420 |
+
Interpolation coefficients.
|
| 1421 |
+
:rtype: :class:`numpy.ndarray`
|
| 1422 |
+
"""
|
| 1423 |
+
proj = np.empty(
|
| 1424 |
+
m + 1 + 2*n*(min(m, n) + 1),
|
| 1425 |
+
dtype=np.complex128, order='F')
|
| 1426 |
+
k, idx, proj, ier = _id.idzp_rid(eps, m, n, matveca, proj)
|
| 1427 |
+
if ier:
|
| 1428 |
+
raise _RETCODE_ERROR
|
| 1429 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 1430 |
+
return k, idx, proj
|
| 1431 |
+
|
| 1432 |
+
|
| 1433 |
+
def idz_findrank(eps, m, n, matveca):
|
| 1434 |
+
"""
|
| 1435 |
+
Estimate rank of a complex matrix to a specified relative precision using
|
| 1436 |
+
random matrix-vector multiplication.
|
| 1437 |
+
|
| 1438 |
+
:param eps:
|
| 1439 |
+
Relative precision.
|
| 1440 |
+
:type eps: float
|
| 1441 |
+
:param m:
|
| 1442 |
+
Matrix row dimension.
|
| 1443 |
+
:type m: int
|
| 1444 |
+
:param n:
|
| 1445 |
+
Matrix column dimension.
|
| 1446 |
+
:type n: int
|
| 1447 |
+
:param matveca:
|
| 1448 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1449 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1450 |
+
respectively.
|
| 1451 |
+
:type matveca: function
|
| 1452 |
+
|
| 1453 |
+
:return:
|
| 1454 |
+
Rank estimate.
|
| 1455 |
+
:rtype: int
|
| 1456 |
+
"""
|
| 1457 |
+
k, ra, ier = _id.idz_findrank(eps, m, n, matveca)
|
| 1458 |
+
if ier:
|
| 1459 |
+
raise _RETCODE_ERROR
|
| 1460 |
+
return k
|
| 1461 |
+
|
| 1462 |
+
|
| 1463 |
+
#------------------------------------------------------------------------------
|
| 1464 |
+
# idzp_rsvd.f
|
| 1465 |
+
#------------------------------------------------------------------------------
|
| 1466 |
+
|
| 1467 |
+
def idzp_rsvd(eps, m, n, matveca, matvec):
|
| 1468 |
+
"""
|
| 1469 |
+
Compute SVD of a complex matrix to a specified relative precision using
|
| 1470 |
+
random matrix-vector multiplication.
|
| 1471 |
+
|
| 1472 |
+
:param eps:
|
| 1473 |
+
Relative precision.
|
| 1474 |
+
:type eps: float
|
| 1475 |
+
:param m:
|
| 1476 |
+
Matrix row dimension.
|
| 1477 |
+
:type m: int
|
| 1478 |
+
:param n:
|
| 1479 |
+
Matrix column dimension.
|
| 1480 |
+
:type n: int
|
| 1481 |
+
:param matveca:
|
| 1482 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1483 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1484 |
+
respectively.
|
| 1485 |
+
:type matveca: function
|
| 1486 |
+
:param matvec:
|
| 1487 |
+
Function to apply the matrix to a vector, with call signature
|
| 1488 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 1489 |
+
respectively.
|
| 1490 |
+
:type matvec: function
|
| 1491 |
+
|
| 1492 |
+
:return:
|
| 1493 |
+
Left singular vectors.
|
| 1494 |
+
:rtype: :class:`numpy.ndarray`
|
| 1495 |
+
:return:
|
| 1496 |
+
Right singular vectors.
|
| 1497 |
+
:rtype: :class:`numpy.ndarray`
|
| 1498 |
+
:return:
|
| 1499 |
+
Singular values.
|
| 1500 |
+
:rtype: :class:`numpy.ndarray`
|
| 1501 |
+
"""
|
| 1502 |
+
k, iU, iV, iS, w, ier = _id.idzp_rsvd(eps, m, n, matveca, matvec)
|
| 1503 |
+
if ier:
|
| 1504 |
+
raise _RETCODE_ERROR
|
| 1505 |
+
U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
|
| 1506 |
+
V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
|
| 1507 |
+
S = w[iS-1:iS+k-1]
|
| 1508 |
+
return U, V, S
|
| 1509 |
+
|
| 1510 |
+
|
| 1511 |
+
#------------------------------------------------------------------------------
|
| 1512 |
+
# idzr_aid.f
|
| 1513 |
+
#------------------------------------------------------------------------------
|
| 1514 |
+
|
| 1515 |
+
def idzr_aid(A, k):
|
| 1516 |
+
"""
|
| 1517 |
+
Compute ID of a complex matrix to a specified rank using random sampling.
|
| 1518 |
+
|
| 1519 |
+
:param A:
|
| 1520 |
+
Matrix.
|
| 1521 |
+
:type A: :class:`numpy.ndarray`
|
| 1522 |
+
:param k:
|
| 1523 |
+
Rank of ID.
|
| 1524 |
+
:type k: int
|
| 1525 |
+
|
| 1526 |
+
:return:
|
| 1527 |
+
Column index array.
|
| 1528 |
+
:rtype: :class:`numpy.ndarray`
|
| 1529 |
+
:return:
|
| 1530 |
+
Interpolation coefficients.
|
| 1531 |
+
:rtype: :class:`numpy.ndarray`
|
| 1532 |
+
"""
|
| 1533 |
+
A = np.asfortranarray(A)
|
| 1534 |
+
m, n = A.shape
|
| 1535 |
+
w = idzr_aidi(m, n, k)
|
| 1536 |
+
idx, proj = _id.idzr_aid(A, k, w)
|
| 1537 |
+
if k == n:
|
| 1538 |
+
proj = np.empty((k, n-k), dtype='complex128', order='F')
|
| 1539 |
+
else:
|
| 1540 |
+
proj = proj.reshape((k, n-k), order='F')
|
| 1541 |
+
return idx, proj
|
| 1542 |
+
|
| 1543 |
+
|
| 1544 |
+
def idzr_aidi(m, n, k):
|
| 1545 |
+
"""
|
| 1546 |
+
Initialize array for :func:`idzr_aid`.
|
| 1547 |
+
|
| 1548 |
+
:param m:
|
| 1549 |
+
Matrix row dimension.
|
| 1550 |
+
:type m: int
|
| 1551 |
+
:param n:
|
| 1552 |
+
Matrix column dimension.
|
| 1553 |
+
:type n: int
|
| 1554 |
+
:param k:
|
| 1555 |
+
Rank of ID.
|
| 1556 |
+
:type k: int
|
| 1557 |
+
|
| 1558 |
+
:return:
|
| 1559 |
+
Initialization array to be used by :func:`idzr_aid`.
|
| 1560 |
+
:rtype: :class:`numpy.ndarray`
|
| 1561 |
+
"""
|
| 1562 |
+
return _id.idzr_aidi(m, n, k)
|
| 1563 |
+
|
| 1564 |
+
|
| 1565 |
+
#------------------------------------------------------------------------------
|
| 1566 |
+
# idzr_asvd.f
|
| 1567 |
+
#------------------------------------------------------------------------------
|
| 1568 |
+
|
| 1569 |
+
def idzr_asvd(A, k):
|
| 1570 |
+
"""
|
| 1571 |
+
Compute SVD of a complex matrix to a specified rank using random sampling.
|
| 1572 |
+
|
| 1573 |
+
:param A:
|
| 1574 |
+
Matrix.
|
| 1575 |
+
:type A: :class:`numpy.ndarray`
|
| 1576 |
+
:param k:
|
| 1577 |
+
Rank of SVD.
|
| 1578 |
+
:type k: int
|
| 1579 |
+
|
| 1580 |
+
:return:
|
| 1581 |
+
Left singular vectors.
|
| 1582 |
+
:rtype: :class:`numpy.ndarray`
|
| 1583 |
+
:return:
|
| 1584 |
+
Right singular vectors.
|
| 1585 |
+
:rtype: :class:`numpy.ndarray`
|
| 1586 |
+
:return:
|
| 1587 |
+
Singular values.
|
| 1588 |
+
:rtype: :class:`numpy.ndarray`
|
| 1589 |
+
"""
|
| 1590 |
+
A = np.asfortranarray(A)
|
| 1591 |
+
m, n = A.shape
|
| 1592 |
+
w = np.empty(
|
| 1593 |
+
(2*k + 22)*m + (6*k + 21)*n + 8*k**2 + 10*k + 90,
|
| 1594 |
+
dtype='complex128', order='F')
|
| 1595 |
+
w_ = idzr_aidi(m, n, k)
|
| 1596 |
+
w[:w_.size] = w_
|
| 1597 |
+
U, V, S, ier = _id.idzr_asvd(A, k, w)
|
| 1598 |
+
if ier:
|
| 1599 |
+
raise _RETCODE_ERROR
|
| 1600 |
+
return U, V, S
|
| 1601 |
+
|
| 1602 |
+
|
| 1603 |
+
#------------------------------------------------------------------------------
|
| 1604 |
+
# idzr_rid.f
|
| 1605 |
+
#------------------------------------------------------------------------------
|
| 1606 |
+
|
| 1607 |
+
def idzr_rid(m, n, matveca, k):
|
| 1608 |
+
"""
|
| 1609 |
+
Compute ID of a complex matrix to a specified rank using random
|
| 1610 |
+
matrix-vector multiplication.
|
| 1611 |
+
|
| 1612 |
+
:param m:
|
| 1613 |
+
Matrix row dimension.
|
| 1614 |
+
:type m: int
|
| 1615 |
+
:param n:
|
| 1616 |
+
Matrix column dimension.
|
| 1617 |
+
:type n: int
|
| 1618 |
+
:param matveca:
|
| 1619 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1620 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1621 |
+
respectively.
|
| 1622 |
+
:type matveca: function
|
| 1623 |
+
:param k:
|
| 1624 |
+
Rank of ID.
|
| 1625 |
+
:type k: int
|
| 1626 |
+
|
| 1627 |
+
:return:
|
| 1628 |
+
Column index array.
|
| 1629 |
+
:rtype: :class:`numpy.ndarray`
|
| 1630 |
+
:return:
|
| 1631 |
+
Interpolation coefficients.
|
| 1632 |
+
:rtype: :class:`numpy.ndarray`
|
| 1633 |
+
"""
|
| 1634 |
+
idx, proj = _id.idzr_rid(m, n, matveca, k)
|
| 1635 |
+
proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
|
| 1636 |
+
return idx, proj
|
| 1637 |
+
|
| 1638 |
+
|
| 1639 |
+
#------------------------------------------------------------------------------
|
| 1640 |
+
# idzr_rsvd.f
|
| 1641 |
+
#------------------------------------------------------------------------------
|
| 1642 |
+
|
| 1643 |
+
def idzr_rsvd(m, n, matveca, matvec, k):
|
| 1644 |
+
"""
|
| 1645 |
+
Compute SVD of a complex matrix to a specified rank using random
|
| 1646 |
+
matrix-vector multiplication.
|
| 1647 |
+
|
| 1648 |
+
:param m:
|
| 1649 |
+
Matrix row dimension.
|
| 1650 |
+
:type m: int
|
| 1651 |
+
:param n:
|
| 1652 |
+
Matrix column dimension.
|
| 1653 |
+
:type n: int
|
| 1654 |
+
:param matveca:
|
| 1655 |
+
Function to apply the matrix adjoint to a vector, with call signature
|
| 1656 |
+
`y = matveca(x)`, where `x` and `y` are the input and output vectors,
|
| 1657 |
+
respectively.
|
| 1658 |
+
:type matveca: function
|
| 1659 |
+
:param matvec:
|
| 1660 |
+
Function to apply the matrix to a vector, with call signature
|
| 1661 |
+
`y = matvec(x)`, where `x` and `y` are the input and output vectors,
|
| 1662 |
+
respectively.
|
| 1663 |
+
:type matvec: function
|
| 1664 |
+
:param k:
|
| 1665 |
+
Rank of SVD.
|
| 1666 |
+
:type k: int
|
| 1667 |
+
|
| 1668 |
+
:return:
|
| 1669 |
+
Left singular vectors.
|
| 1670 |
+
:rtype: :class:`numpy.ndarray`
|
| 1671 |
+
:return:
|
| 1672 |
+
Right singular vectors.
|
| 1673 |
+
:rtype: :class:`numpy.ndarray`
|
| 1674 |
+
:return:
|
| 1675 |
+
Singular values.
|
| 1676 |
+
:rtype: :class:`numpy.ndarray`
|
| 1677 |
+
"""
|
| 1678 |
+
U, V, S, ier = _id.idzr_rsvd(m, n, matveca, matvec, k)
|
| 1679 |
+
if ier:
|
| 1680 |
+
raise _RETCODE_ERROR
|
| 1681 |
+
return U, V, S
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_lapack_subroutines.h
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs.py
ADDED
|
@@ -0,0 +1,861 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Author: Travis Oliphant, March 2002
|
| 3 |
+
#
|
| 4 |
+
from itertools import product
|
| 5 |
+
|
| 6 |
+
import numpy as np
|
| 7 |
+
from numpy import (dot, diag, prod, logical_not, ravel, transpose,
|
| 8 |
+
conjugate, absolute, amax, sign, isfinite, triu)
|
| 9 |
+
|
| 10 |
+
# Local imports
|
| 11 |
+
from scipy.linalg import LinAlgError, bandwidth
|
| 12 |
+
from ._misc import norm
|
| 13 |
+
from ._basic import solve, inv
|
| 14 |
+
from ._decomp_svd import svd
|
| 15 |
+
from ._decomp_schur import schur, rsf2csf
|
| 16 |
+
from ._expm_frechet import expm_frechet, expm_cond
|
| 17 |
+
from ._matfuncs_sqrtm import sqrtm
|
| 18 |
+
from ._matfuncs_expm import pick_pade_structure, pade_UV_calc
|
| 19 |
+
|
| 20 |
+
# deprecated imports to be removed in SciPy 1.13.0
|
| 21 |
+
from numpy import single # noqa: F401
|
| 22 |
+
|
| 23 |
+
__all__ = ['expm', 'cosm', 'sinm', 'tanm', 'coshm', 'sinhm', 'tanhm', 'logm',
|
| 24 |
+
'funm', 'signm', 'sqrtm', 'fractional_matrix_power', 'expm_frechet',
|
| 25 |
+
'expm_cond', 'khatri_rao']
|
| 26 |
+
|
| 27 |
+
eps = np.finfo('d').eps
|
| 28 |
+
feps = np.finfo('f').eps
|
| 29 |
+
|
| 30 |
+
_array_precision = {'i': 1, 'l': 1, 'f': 0, 'd': 1, 'F': 0, 'D': 1}
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
###############################################################################
|
| 34 |
+
# Utility functions.
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def _asarray_square(A):
|
| 38 |
+
"""
|
| 39 |
+
Wraps asarray with the extra requirement that the input be a square matrix.
|
| 40 |
+
|
| 41 |
+
The motivation is that the matfuncs module has real functions that have
|
| 42 |
+
been lifted to square matrix functions.
|
| 43 |
+
|
| 44 |
+
Parameters
|
| 45 |
+
----------
|
| 46 |
+
A : array_like
|
| 47 |
+
A square matrix.
|
| 48 |
+
|
| 49 |
+
Returns
|
| 50 |
+
-------
|
| 51 |
+
out : ndarray
|
| 52 |
+
An ndarray copy or view or other representation of A.
|
| 53 |
+
|
| 54 |
+
"""
|
| 55 |
+
A = np.asarray(A)
|
| 56 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 57 |
+
raise ValueError('expected square array_like input')
|
| 58 |
+
return A
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def _maybe_real(A, B, tol=None):
|
| 62 |
+
"""
|
| 63 |
+
Return either B or the real part of B, depending on properties of A and B.
|
| 64 |
+
|
| 65 |
+
The motivation is that B has been computed as a complicated function of A,
|
| 66 |
+
and B may be perturbed by negligible imaginary components.
|
| 67 |
+
If A is real and B is complex with small imaginary components,
|
| 68 |
+
then return a real copy of B. The assumption in that case would be that
|
| 69 |
+
the imaginary components of B are numerical artifacts.
|
| 70 |
+
|
| 71 |
+
Parameters
|
| 72 |
+
----------
|
| 73 |
+
A : ndarray
|
| 74 |
+
Input array whose type is to be checked as real vs. complex.
|
| 75 |
+
B : ndarray
|
| 76 |
+
Array to be returned, possibly without its imaginary part.
|
| 77 |
+
tol : float
|
| 78 |
+
Absolute tolerance.
|
| 79 |
+
|
| 80 |
+
Returns
|
| 81 |
+
-------
|
| 82 |
+
out : real or complex array
|
| 83 |
+
Either the input array B or only the real part of the input array B.
|
| 84 |
+
|
| 85 |
+
"""
|
| 86 |
+
# Note that booleans and integers compare as real.
|
| 87 |
+
if np.isrealobj(A) and np.iscomplexobj(B):
|
| 88 |
+
if tol is None:
|
| 89 |
+
tol = {0: feps*1e3, 1: eps*1e6}[_array_precision[B.dtype.char]]
|
| 90 |
+
if np.allclose(B.imag, 0.0, atol=tol):
|
| 91 |
+
B = B.real
|
| 92 |
+
return B
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
###############################################################################
|
| 96 |
+
# Matrix functions.
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def fractional_matrix_power(A, t):
|
| 100 |
+
"""
|
| 101 |
+
Compute the fractional power of a matrix.
|
| 102 |
+
|
| 103 |
+
Proceeds according to the discussion in section (6) of [1]_.
|
| 104 |
+
|
| 105 |
+
Parameters
|
| 106 |
+
----------
|
| 107 |
+
A : (N, N) array_like
|
| 108 |
+
Matrix whose fractional power to evaluate.
|
| 109 |
+
t : float
|
| 110 |
+
Fractional power.
|
| 111 |
+
|
| 112 |
+
Returns
|
| 113 |
+
-------
|
| 114 |
+
X : (N, N) array_like
|
| 115 |
+
The fractional power of the matrix.
|
| 116 |
+
|
| 117 |
+
References
|
| 118 |
+
----------
|
| 119 |
+
.. [1] Nicholas J. Higham and Lijing lin (2011)
|
| 120 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 121 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 122 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 123 |
+
|
| 124 |
+
Examples
|
| 125 |
+
--------
|
| 126 |
+
>>> import numpy as np
|
| 127 |
+
>>> from scipy.linalg import fractional_matrix_power
|
| 128 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 129 |
+
>>> b = fractional_matrix_power(a, 0.5)
|
| 130 |
+
>>> b
|
| 131 |
+
array([[ 0.75592895, 1.13389342],
|
| 132 |
+
[ 0.37796447, 1.88982237]])
|
| 133 |
+
>>> np.dot(b, b) # Verify square root
|
| 134 |
+
array([[ 1., 3.],
|
| 135 |
+
[ 1., 4.]])
|
| 136 |
+
|
| 137 |
+
"""
|
| 138 |
+
# This fixes some issue with imports;
|
| 139 |
+
# this function calls onenormest which is in scipy.sparse.
|
| 140 |
+
A = _asarray_square(A)
|
| 141 |
+
import scipy.linalg._matfuncs_inv_ssq
|
| 142 |
+
return scipy.linalg._matfuncs_inv_ssq._fractional_matrix_power(A, t)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def logm(A, disp=True):
|
| 146 |
+
"""
|
| 147 |
+
Compute matrix logarithm.
|
| 148 |
+
|
| 149 |
+
The matrix logarithm is the inverse of
|
| 150 |
+
expm: expm(logm(`A`)) == `A`
|
| 151 |
+
|
| 152 |
+
Parameters
|
| 153 |
+
----------
|
| 154 |
+
A : (N, N) array_like
|
| 155 |
+
Matrix whose logarithm to evaluate
|
| 156 |
+
disp : bool, optional
|
| 157 |
+
Print warning if error in the result is estimated large
|
| 158 |
+
instead of returning estimated error. (Default: True)
|
| 159 |
+
|
| 160 |
+
Returns
|
| 161 |
+
-------
|
| 162 |
+
logm : (N, N) ndarray
|
| 163 |
+
Matrix logarithm of `A`
|
| 164 |
+
errest : float
|
| 165 |
+
(if disp == False)
|
| 166 |
+
|
| 167 |
+
1-norm of the estimated error, ||err||_1 / ||A||_1
|
| 168 |
+
|
| 169 |
+
References
|
| 170 |
+
----------
|
| 171 |
+
.. [1] Awad H. Al-Mohy and Nicholas J. Higham (2012)
|
| 172 |
+
"Improved Inverse Scaling and Squaring Algorithms
|
| 173 |
+
for the Matrix Logarithm."
|
| 174 |
+
SIAM Journal on Scientific Computing, 34 (4). C152-C169.
|
| 175 |
+
ISSN 1095-7197
|
| 176 |
+
|
| 177 |
+
.. [2] Nicholas J. Higham (2008)
|
| 178 |
+
"Functions of Matrices: Theory and Computation"
|
| 179 |
+
ISBN 978-0-898716-46-7
|
| 180 |
+
|
| 181 |
+
.. [3] Nicholas J. Higham and Lijing lin (2011)
|
| 182 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 183 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 184 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 185 |
+
|
| 186 |
+
Examples
|
| 187 |
+
--------
|
| 188 |
+
>>> import numpy as np
|
| 189 |
+
>>> from scipy.linalg import logm, expm
|
| 190 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 191 |
+
>>> b = logm(a)
|
| 192 |
+
>>> b
|
| 193 |
+
array([[-1.02571087, 2.05142174],
|
| 194 |
+
[ 0.68380725, 1.02571087]])
|
| 195 |
+
>>> expm(b) # Verify expm(logm(a)) returns a
|
| 196 |
+
array([[ 1., 3.],
|
| 197 |
+
[ 1., 4.]])
|
| 198 |
+
|
| 199 |
+
"""
|
| 200 |
+
A = _asarray_square(A)
|
| 201 |
+
# Avoid circular import ... this is OK, right?
|
| 202 |
+
import scipy.linalg._matfuncs_inv_ssq
|
| 203 |
+
F = scipy.linalg._matfuncs_inv_ssq._logm(A)
|
| 204 |
+
F = _maybe_real(A, F)
|
| 205 |
+
errtol = 1000*eps
|
| 206 |
+
# TODO use a better error approximation
|
| 207 |
+
errest = norm(expm(F)-A, 1) / norm(A, 1)
|
| 208 |
+
if disp:
|
| 209 |
+
if not isfinite(errest) or errest >= errtol:
|
| 210 |
+
print("logm result may be inaccurate, approximate err =", errest)
|
| 211 |
+
return F
|
| 212 |
+
else:
|
| 213 |
+
return F, errest
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def expm(A):
|
| 217 |
+
"""Compute the matrix exponential of an array.
|
| 218 |
+
|
| 219 |
+
Parameters
|
| 220 |
+
----------
|
| 221 |
+
A : ndarray
|
| 222 |
+
Input with last two dimensions are square ``(..., n, n)``.
|
| 223 |
+
|
| 224 |
+
Returns
|
| 225 |
+
-------
|
| 226 |
+
eA : ndarray
|
| 227 |
+
The resulting matrix exponential with the same shape of ``A``
|
| 228 |
+
|
| 229 |
+
Notes
|
| 230 |
+
-----
|
| 231 |
+
Implements the algorithm given in [1], which is essentially a Pade
|
| 232 |
+
approximation with a variable order that is decided based on the array
|
| 233 |
+
data.
|
| 234 |
+
|
| 235 |
+
For input with size ``n``, the memory usage is in the worst case in the
|
| 236 |
+
order of ``8*(n**2)``. If the input data is not of single and double
|
| 237 |
+
precision of real and complex dtypes, it is copied to a new array.
|
| 238 |
+
|
| 239 |
+
For cases ``n >= 400``, the exact 1-norm computation cost, breaks even with
|
| 240 |
+
1-norm estimation and from that point on the estimation scheme given in
|
| 241 |
+
[2] is used to decide on the approximation order.
|
| 242 |
+
|
| 243 |
+
References
|
| 244 |
+
----------
|
| 245 |
+
.. [1] Awad H. Al-Mohy and Nicholas J. Higham, (2009), "A New Scaling
|
| 246 |
+
and Squaring Algorithm for the Matrix Exponential", SIAM J. Matrix
|
| 247 |
+
Anal. Appl. 31(3):970-989, :doi:`10.1137/09074721X`
|
| 248 |
+
|
| 249 |
+
.. [2] Nicholas J. Higham and Francoise Tisseur (2000), "A Block Algorithm
|
| 250 |
+
for Matrix 1-Norm Estimation, with an Application to 1-Norm
|
| 251 |
+
Pseudospectra." SIAM J. Matrix Anal. Appl. 21(4):1185-1201,
|
| 252 |
+
:doi:`10.1137/S0895479899356080`
|
| 253 |
+
|
| 254 |
+
Examples
|
| 255 |
+
--------
|
| 256 |
+
>>> import numpy as np
|
| 257 |
+
>>> from scipy.linalg import expm, sinm, cosm
|
| 258 |
+
|
| 259 |
+
Matrix version of the formula exp(0) = 1:
|
| 260 |
+
|
| 261 |
+
>>> expm(np.zeros((3, 2, 2)))
|
| 262 |
+
array([[[1., 0.],
|
| 263 |
+
[0., 1.]],
|
| 264 |
+
<BLANKLINE>
|
| 265 |
+
[[1., 0.],
|
| 266 |
+
[0., 1.]],
|
| 267 |
+
<BLANKLINE>
|
| 268 |
+
[[1., 0.],
|
| 269 |
+
[0., 1.]]])
|
| 270 |
+
|
| 271 |
+
Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
|
| 272 |
+
applied to a matrix:
|
| 273 |
+
|
| 274 |
+
>>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
|
| 275 |
+
>>> expm(1j*a)
|
| 276 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 277 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 278 |
+
>>> cosm(a) + 1j*sinm(a)
|
| 279 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 280 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 281 |
+
|
| 282 |
+
"""
|
| 283 |
+
a = np.asarray(A)
|
| 284 |
+
if a.size == 1 and a.ndim < 2:
|
| 285 |
+
return np.array([[np.exp(a.item())]])
|
| 286 |
+
|
| 287 |
+
if a.ndim < 2:
|
| 288 |
+
raise LinAlgError('The input array must be at least two-dimensional')
|
| 289 |
+
if a.shape[-1] != a.shape[-2]:
|
| 290 |
+
raise LinAlgError('Last 2 dimensions of the array must be square')
|
| 291 |
+
n = a.shape[-1]
|
| 292 |
+
# Empty array
|
| 293 |
+
if min(*a.shape) == 0:
|
| 294 |
+
return np.empty_like(a)
|
| 295 |
+
|
| 296 |
+
# Scalar case
|
| 297 |
+
if a.shape[-2:] == (1, 1):
|
| 298 |
+
return np.exp(a)
|
| 299 |
+
|
| 300 |
+
if not np.issubdtype(a.dtype, np.inexact):
|
| 301 |
+
a = a.astype(np.float64)
|
| 302 |
+
elif a.dtype == np.float16:
|
| 303 |
+
a = a.astype(np.float32)
|
| 304 |
+
|
| 305 |
+
# An explicit formula for 2x2 case exists (formula (2.2) in [1]). However, without
|
| 306 |
+
# Kahan's method, numerical instabilities can occur (See gh-19584). Hence removed
|
| 307 |
+
# here until we have a more stable implementation.
|
| 308 |
+
|
| 309 |
+
n = a.shape[-1]
|
| 310 |
+
eA = np.empty(a.shape, dtype=a.dtype)
|
| 311 |
+
# working memory to hold intermediate arrays
|
| 312 |
+
Am = np.empty((5, n, n), dtype=a.dtype)
|
| 313 |
+
|
| 314 |
+
# Main loop to go through the slices of an ndarray and passing to expm
|
| 315 |
+
for ind in product(*[range(x) for x in a.shape[:-2]]):
|
| 316 |
+
aw = a[ind]
|
| 317 |
+
|
| 318 |
+
lu = bandwidth(aw)
|
| 319 |
+
if not any(lu): # a is diagonal?
|
| 320 |
+
eA[ind] = np.diag(np.exp(np.diag(aw)))
|
| 321 |
+
continue
|
| 322 |
+
|
| 323 |
+
# Generic/triangular case; copy the slice into scratch and send.
|
| 324 |
+
# Am will be mutated by pick_pade_structure
|
| 325 |
+
Am[0, :, :] = aw
|
| 326 |
+
m, s = pick_pade_structure(Am)
|
| 327 |
+
|
| 328 |
+
if s != 0: # scaling needed
|
| 329 |
+
Am[:4] *= [[[2**(-s)]], [[4**(-s)]], [[16**(-s)]], [[64**(-s)]]]
|
| 330 |
+
|
| 331 |
+
pade_UV_calc(Am, n, m)
|
| 332 |
+
eAw = Am[0]
|
| 333 |
+
|
| 334 |
+
if s != 0: # squaring needed
|
| 335 |
+
|
| 336 |
+
if (lu[1] == 0) or (lu[0] == 0): # lower/upper triangular
|
| 337 |
+
# This branch implements Code Fragment 2.1 of [1]
|
| 338 |
+
|
| 339 |
+
diag_aw = np.diag(aw)
|
| 340 |
+
# einsum returns a writable view
|
| 341 |
+
np.einsum('ii->i', eAw)[:] = np.exp(diag_aw * 2**(-s))
|
| 342 |
+
# super/sub diagonal
|
| 343 |
+
sd = np.diag(aw, k=-1 if lu[1] == 0 else 1)
|
| 344 |
+
|
| 345 |
+
for i in range(s-1, -1, -1):
|
| 346 |
+
eAw = eAw @ eAw
|
| 347 |
+
|
| 348 |
+
# diagonal
|
| 349 |
+
np.einsum('ii->i', eAw)[:] = np.exp(diag_aw * 2.**(-i))
|
| 350 |
+
exp_sd = _exp_sinch(diag_aw * (2.**(-i))) * (sd * 2**(-i))
|
| 351 |
+
if lu[1] == 0: # lower
|
| 352 |
+
np.einsum('ii->i', eAw[1:, :-1])[:] = exp_sd
|
| 353 |
+
else: # upper
|
| 354 |
+
np.einsum('ii->i', eAw[:-1, 1:])[:] = exp_sd
|
| 355 |
+
|
| 356 |
+
else: # generic
|
| 357 |
+
for _ in range(s):
|
| 358 |
+
eAw = eAw @ eAw
|
| 359 |
+
|
| 360 |
+
# Zero out the entries from np.empty in case of triangular input
|
| 361 |
+
if (lu[0] == 0) or (lu[1] == 0):
|
| 362 |
+
eA[ind] = np.triu(eAw) if lu[0] == 0 else np.tril(eAw)
|
| 363 |
+
else:
|
| 364 |
+
eA[ind] = eAw
|
| 365 |
+
|
| 366 |
+
return eA
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
def _exp_sinch(x):
|
| 370 |
+
# Higham's formula (10.42), might overflow, see GH-11839
|
| 371 |
+
lexp_diff = np.diff(np.exp(x))
|
| 372 |
+
l_diff = np.diff(x)
|
| 373 |
+
mask_z = l_diff == 0.
|
| 374 |
+
lexp_diff[~mask_z] /= l_diff[~mask_z]
|
| 375 |
+
lexp_diff[mask_z] = np.exp(x[:-1][mask_z])
|
| 376 |
+
return lexp_diff
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
def cosm(A):
|
| 380 |
+
"""
|
| 381 |
+
Compute the matrix cosine.
|
| 382 |
+
|
| 383 |
+
This routine uses expm to compute the matrix exponentials.
|
| 384 |
+
|
| 385 |
+
Parameters
|
| 386 |
+
----------
|
| 387 |
+
A : (N, N) array_like
|
| 388 |
+
Input array
|
| 389 |
+
|
| 390 |
+
Returns
|
| 391 |
+
-------
|
| 392 |
+
cosm : (N, N) ndarray
|
| 393 |
+
Matrix cosine of A
|
| 394 |
+
|
| 395 |
+
Examples
|
| 396 |
+
--------
|
| 397 |
+
>>> import numpy as np
|
| 398 |
+
>>> from scipy.linalg import expm, sinm, cosm
|
| 399 |
+
|
| 400 |
+
Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
|
| 401 |
+
applied to a matrix:
|
| 402 |
+
|
| 403 |
+
>>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
|
| 404 |
+
>>> expm(1j*a)
|
| 405 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 406 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 407 |
+
>>> cosm(a) + 1j*sinm(a)
|
| 408 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 409 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 410 |
+
|
| 411 |
+
"""
|
| 412 |
+
A = _asarray_square(A)
|
| 413 |
+
if np.iscomplexobj(A):
|
| 414 |
+
return 0.5*(expm(1j*A) + expm(-1j*A))
|
| 415 |
+
else:
|
| 416 |
+
return expm(1j*A).real
|
| 417 |
+
|
| 418 |
+
|
| 419 |
+
def sinm(A):
|
| 420 |
+
"""
|
| 421 |
+
Compute the matrix sine.
|
| 422 |
+
|
| 423 |
+
This routine uses expm to compute the matrix exponentials.
|
| 424 |
+
|
| 425 |
+
Parameters
|
| 426 |
+
----------
|
| 427 |
+
A : (N, N) array_like
|
| 428 |
+
Input array.
|
| 429 |
+
|
| 430 |
+
Returns
|
| 431 |
+
-------
|
| 432 |
+
sinm : (N, N) ndarray
|
| 433 |
+
Matrix sine of `A`
|
| 434 |
+
|
| 435 |
+
Examples
|
| 436 |
+
--------
|
| 437 |
+
>>> import numpy as np
|
| 438 |
+
>>> from scipy.linalg import expm, sinm, cosm
|
| 439 |
+
|
| 440 |
+
Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
|
| 441 |
+
applied to a matrix:
|
| 442 |
+
|
| 443 |
+
>>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
|
| 444 |
+
>>> expm(1j*a)
|
| 445 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 446 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 447 |
+
>>> cosm(a) + 1j*sinm(a)
|
| 448 |
+
array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
|
| 449 |
+
[ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
|
| 450 |
+
|
| 451 |
+
"""
|
| 452 |
+
A = _asarray_square(A)
|
| 453 |
+
if np.iscomplexobj(A):
|
| 454 |
+
return -0.5j*(expm(1j*A) - expm(-1j*A))
|
| 455 |
+
else:
|
| 456 |
+
return expm(1j*A).imag
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
def tanm(A):
|
| 460 |
+
"""
|
| 461 |
+
Compute the matrix tangent.
|
| 462 |
+
|
| 463 |
+
This routine uses expm to compute the matrix exponentials.
|
| 464 |
+
|
| 465 |
+
Parameters
|
| 466 |
+
----------
|
| 467 |
+
A : (N, N) array_like
|
| 468 |
+
Input array.
|
| 469 |
+
|
| 470 |
+
Returns
|
| 471 |
+
-------
|
| 472 |
+
tanm : (N, N) ndarray
|
| 473 |
+
Matrix tangent of `A`
|
| 474 |
+
|
| 475 |
+
Examples
|
| 476 |
+
--------
|
| 477 |
+
>>> import numpy as np
|
| 478 |
+
>>> from scipy.linalg import tanm, sinm, cosm
|
| 479 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 480 |
+
>>> t = tanm(a)
|
| 481 |
+
>>> t
|
| 482 |
+
array([[ -2.00876993, -8.41880636],
|
| 483 |
+
[ -2.80626879, -10.42757629]])
|
| 484 |
+
|
| 485 |
+
Verify tanm(a) = sinm(a).dot(inv(cosm(a)))
|
| 486 |
+
|
| 487 |
+
>>> s = sinm(a)
|
| 488 |
+
>>> c = cosm(a)
|
| 489 |
+
>>> s.dot(np.linalg.inv(c))
|
| 490 |
+
array([[ -2.00876993, -8.41880636],
|
| 491 |
+
[ -2.80626879, -10.42757629]])
|
| 492 |
+
|
| 493 |
+
"""
|
| 494 |
+
A = _asarray_square(A)
|
| 495 |
+
return _maybe_real(A, solve(cosm(A), sinm(A)))
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
def coshm(A):
|
| 499 |
+
"""
|
| 500 |
+
Compute the hyperbolic matrix cosine.
|
| 501 |
+
|
| 502 |
+
This routine uses expm to compute the matrix exponentials.
|
| 503 |
+
|
| 504 |
+
Parameters
|
| 505 |
+
----------
|
| 506 |
+
A : (N, N) array_like
|
| 507 |
+
Input array.
|
| 508 |
+
|
| 509 |
+
Returns
|
| 510 |
+
-------
|
| 511 |
+
coshm : (N, N) ndarray
|
| 512 |
+
Hyperbolic matrix cosine of `A`
|
| 513 |
+
|
| 514 |
+
Examples
|
| 515 |
+
--------
|
| 516 |
+
>>> import numpy as np
|
| 517 |
+
>>> from scipy.linalg import tanhm, sinhm, coshm
|
| 518 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 519 |
+
>>> c = coshm(a)
|
| 520 |
+
>>> c
|
| 521 |
+
array([[ 11.24592233, 38.76236492],
|
| 522 |
+
[ 12.92078831, 50.00828725]])
|
| 523 |
+
|
| 524 |
+
Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
|
| 525 |
+
|
| 526 |
+
>>> t = tanhm(a)
|
| 527 |
+
>>> s = sinhm(a)
|
| 528 |
+
>>> t - s.dot(np.linalg.inv(c))
|
| 529 |
+
array([[ 2.72004641e-15, 4.55191440e-15],
|
| 530 |
+
[ 0.00000000e+00, -5.55111512e-16]])
|
| 531 |
+
|
| 532 |
+
"""
|
| 533 |
+
A = _asarray_square(A)
|
| 534 |
+
return _maybe_real(A, 0.5 * (expm(A) + expm(-A)))
|
| 535 |
+
|
| 536 |
+
|
| 537 |
+
def sinhm(A):
|
| 538 |
+
"""
|
| 539 |
+
Compute the hyperbolic matrix sine.
|
| 540 |
+
|
| 541 |
+
This routine uses expm to compute the matrix exponentials.
|
| 542 |
+
|
| 543 |
+
Parameters
|
| 544 |
+
----------
|
| 545 |
+
A : (N, N) array_like
|
| 546 |
+
Input array.
|
| 547 |
+
|
| 548 |
+
Returns
|
| 549 |
+
-------
|
| 550 |
+
sinhm : (N, N) ndarray
|
| 551 |
+
Hyperbolic matrix sine of `A`
|
| 552 |
+
|
| 553 |
+
Examples
|
| 554 |
+
--------
|
| 555 |
+
>>> import numpy as np
|
| 556 |
+
>>> from scipy.linalg import tanhm, sinhm, coshm
|
| 557 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 558 |
+
>>> s = sinhm(a)
|
| 559 |
+
>>> s
|
| 560 |
+
array([[ 10.57300653, 39.28826594],
|
| 561 |
+
[ 13.09608865, 49.86127247]])
|
| 562 |
+
|
| 563 |
+
Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
|
| 564 |
+
|
| 565 |
+
>>> t = tanhm(a)
|
| 566 |
+
>>> c = coshm(a)
|
| 567 |
+
>>> t - s.dot(np.linalg.inv(c))
|
| 568 |
+
array([[ 2.72004641e-15, 4.55191440e-15],
|
| 569 |
+
[ 0.00000000e+00, -5.55111512e-16]])
|
| 570 |
+
|
| 571 |
+
"""
|
| 572 |
+
A = _asarray_square(A)
|
| 573 |
+
return _maybe_real(A, 0.5 * (expm(A) - expm(-A)))
|
| 574 |
+
|
| 575 |
+
|
| 576 |
+
def tanhm(A):
|
| 577 |
+
"""
|
| 578 |
+
Compute the hyperbolic matrix tangent.
|
| 579 |
+
|
| 580 |
+
This routine uses expm to compute the matrix exponentials.
|
| 581 |
+
|
| 582 |
+
Parameters
|
| 583 |
+
----------
|
| 584 |
+
A : (N, N) array_like
|
| 585 |
+
Input array
|
| 586 |
+
|
| 587 |
+
Returns
|
| 588 |
+
-------
|
| 589 |
+
tanhm : (N, N) ndarray
|
| 590 |
+
Hyperbolic matrix tangent of `A`
|
| 591 |
+
|
| 592 |
+
Examples
|
| 593 |
+
--------
|
| 594 |
+
>>> import numpy as np
|
| 595 |
+
>>> from scipy.linalg import tanhm, sinhm, coshm
|
| 596 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 597 |
+
>>> t = tanhm(a)
|
| 598 |
+
>>> t
|
| 599 |
+
array([[ 0.3428582 , 0.51987926],
|
| 600 |
+
[ 0.17329309, 0.86273746]])
|
| 601 |
+
|
| 602 |
+
Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
|
| 603 |
+
|
| 604 |
+
>>> s = sinhm(a)
|
| 605 |
+
>>> c = coshm(a)
|
| 606 |
+
>>> t - s.dot(np.linalg.inv(c))
|
| 607 |
+
array([[ 2.72004641e-15, 4.55191440e-15],
|
| 608 |
+
[ 0.00000000e+00, -5.55111512e-16]])
|
| 609 |
+
|
| 610 |
+
"""
|
| 611 |
+
A = _asarray_square(A)
|
| 612 |
+
return _maybe_real(A, solve(coshm(A), sinhm(A)))
|
| 613 |
+
|
| 614 |
+
|
| 615 |
+
def funm(A, func, disp=True):
|
| 616 |
+
"""
|
| 617 |
+
Evaluate a matrix function specified by a callable.
|
| 618 |
+
|
| 619 |
+
Returns the value of matrix-valued function ``f`` at `A`. The
|
| 620 |
+
function ``f`` is an extension of the scalar-valued function `func`
|
| 621 |
+
to matrices.
|
| 622 |
+
|
| 623 |
+
Parameters
|
| 624 |
+
----------
|
| 625 |
+
A : (N, N) array_like
|
| 626 |
+
Matrix at which to evaluate the function
|
| 627 |
+
func : callable
|
| 628 |
+
Callable object that evaluates a scalar function f.
|
| 629 |
+
Must be vectorized (eg. using vectorize).
|
| 630 |
+
disp : bool, optional
|
| 631 |
+
Print warning if error in the result is estimated large
|
| 632 |
+
instead of returning estimated error. (Default: True)
|
| 633 |
+
|
| 634 |
+
Returns
|
| 635 |
+
-------
|
| 636 |
+
funm : (N, N) ndarray
|
| 637 |
+
Value of the matrix function specified by func evaluated at `A`
|
| 638 |
+
errest : float
|
| 639 |
+
(if disp == False)
|
| 640 |
+
|
| 641 |
+
1-norm of the estimated error, ||err||_1 / ||A||_1
|
| 642 |
+
|
| 643 |
+
Notes
|
| 644 |
+
-----
|
| 645 |
+
This function implements the general algorithm based on Schur decomposition
|
| 646 |
+
(Algorithm 9.1.1. in [1]_).
|
| 647 |
+
|
| 648 |
+
If the input matrix is known to be diagonalizable, then relying on the
|
| 649 |
+
eigendecomposition is likely to be faster. For example, if your matrix is
|
| 650 |
+
Hermitian, you can do
|
| 651 |
+
|
| 652 |
+
>>> from scipy.linalg import eigh
|
| 653 |
+
>>> def funm_herm(a, func, check_finite=False):
|
| 654 |
+
... w, v = eigh(a, check_finite=check_finite)
|
| 655 |
+
... ## if you further know that your matrix is positive semidefinite,
|
| 656 |
+
... ## you can optionally guard against precision errors by doing
|
| 657 |
+
... # w = np.maximum(w, 0)
|
| 658 |
+
... w = func(w)
|
| 659 |
+
... return (v * w).dot(v.conj().T)
|
| 660 |
+
|
| 661 |
+
References
|
| 662 |
+
----------
|
| 663 |
+
.. [1] Gene H. Golub, Charles F. van Loan, Matrix Computations 4th ed.
|
| 664 |
+
|
| 665 |
+
Examples
|
| 666 |
+
--------
|
| 667 |
+
>>> import numpy as np
|
| 668 |
+
>>> from scipy.linalg import funm
|
| 669 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 670 |
+
>>> funm(a, lambda x: x*x)
|
| 671 |
+
array([[ 4., 15.],
|
| 672 |
+
[ 5., 19.]])
|
| 673 |
+
>>> a.dot(a)
|
| 674 |
+
array([[ 4., 15.],
|
| 675 |
+
[ 5., 19.]])
|
| 676 |
+
|
| 677 |
+
"""
|
| 678 |
+
A = _asarray_square(A)
|
| 679 |
+
# Perform Shur decomposition (lapack ?gees)
|
| 680 |
+
T, Z = schur(A)
|
| 681 |
+
T, Z = rsf2csf(T, Z)
|
| 682 |
+
n, n = T.shape
|
| 683 |
+
F = diag(func(diag(T))) # apply function to diagonal elements
|
| 684 |
+
F = F.astype(T.dtype.char) # e.g., when F is real but T is complex
|
| 685 |
+
|
| 686 |
+
minden = abs(T[0, 0])
|
| 687 |
+
|
| 688 |
+
# implement Algorithm 11.1.1 from Golub and Van Loan
|
| 689 |
+
# "matrix Computations."
|
| 690 |
+
for p in range(1, n):
|
| 691 |
+
for i in range(1, n-p+1):
|
| 692 |
+
j = i + p
|
| 693 |
+
s = T[i-1, j-1] * (F[j-1, j-1] - F[i-1, i-1])
|
| 694 |
+
ksl = slice(i, j-1)
|
| 695 |
+
val = dot(T[i-1, ksl], F[ksl, j-1]) - dot(F[i-1, ksl], T[ksl, j-1])
|
| 696 |
+
s = s + val
|
| 697 |
+
den = T[j-1, j-1] - T[i-1, i-1]
|
| 698 |
+
if den != 0.0:
|
| 699 |
+
s = s / den
|
| 700 |
+
F[i-1, j-1] = s
|
| 701 |
+
minden = min(minden, abs(den))
|
| 702 |
+
|
| 703 |
+
F = dot(dot(Z, F), transpose(conjugate(Z)))
|
| 704 |
+
F = _maybe_real(A, F)
|
| 705 |
+
|
| 706 |
+
tol = {0: feps, 1: eps}[_array_precision[F.dtype.char]]
|
| 707 |
+
if minden == 0.0:
|
| 708 |
+
minden = tol
|
| 709 |
+
err = min(1, max(tol, (tol/minden)*norm(triu(T, 1), 1)))
|
| 710 |
+
if prod(ravel(logical_not(isfinite(F))), axis=0):
|
| 711 |
+
err = np.inf
|
| 712 |
+
if disp:
|
| 713 |
+
if err > 1000*tol:
|
| 714 |
+
print("funm result may be inaccurate, approximate err =", err)
|
| 715 |
+
return F
|
| 716 |
+
else:
|
| 717 |
+
return F, err
|
| 718 |
+
|
| 719 |
+
|
| 720 |
+
def signm(A, disp=True):
|
| 721 |
+
"""
|
| 722 |
+
Matrix sign function.
|
| 723 |
+
|
| 724 |
+
Extension of the scalar sign(x) to matrices.
|
| 725 |
+
|
| 726 |
+
Parameters
|
| 727 |
+
----------
|
| 728 |
+
A : (N, N) array_like
|
| 729 |
+
Matrix at which to evaluate the sign function
|
| 730 |
+
disp : bool, optional
|
| 731 |
+
Print warning if error in the result is estimated large
|
| 732 |
+
instead of returning estimated error. (Default: True)
|
| 733 |
+
|
| 734 |
+
Returns
|
| 735 |
+
-------
|
| 736 |
+
signm : (N, N) ndarray
|
| 737 |
+
Value of the sign function at `A`
|
| 738 |
+
errest : float
|
| 739 |
+
(if disp == False)
|
| 740 |
+
|
| 741 |
+
1-norm of the estimated error, ||err||_1 / ||A||_1
|
| 742 |
+
|
| 743 |
+
Examples
|
| 744 |
+
--------
|
| 745 |
+
>>> from scipy.linalg import signm, eigvals
|
| 746 |
+
>>> a = [[1,2,3], [1,2,1], [1,1,1]]
|
| 747 |
+
>>> eigvals(a)
|
| 748 |
+
array([ 4.12488542+0.j, -0.76155718+0.j, 0.63667176+0.j])
|
| 749 |
+
>>> eigvals(signm(a))
|
| 750 |
+
array([-1.+0.j, 1.+0.j, 1.+0.j])
|
| 751 |
+
|
| 752 |
+
"""
|
| 753 |
+
A = _asarray_square(A)
|
| 754 |
+
|
| 755 |
+
def rounded_sign(x):
|
| 756 |
+
rx = np.real(x)
|
| 757 |
+
if rx.dtype.char == 'f':
|
| 758 |
+
c = 1e3*feps*amax(x)
|
| 759 |
+
else:
|
| 760 |
+
c = 1e3*eps*amax(x)
|
| 761 |
+
return sign((absolute(rx) > c) * rx)
|
| 762 |
+
result, errest = funm(A, rounded_sign, disp=0)
|
| 763 |
+
errtol = {0: 1e3*feps, 1: 1e3*eps}[_array_precision[result.dtype.char]]
|
| 764 |
+
if errest < errtol:
|
| 765 |
+
return result
|
| 766 |
+
|
| 767 |
+
# Handle signm of defective matrices:
|
| 768 |
+
|
| 769 |
+
# See "E.D.Denman and J.Leyva-Ramos, Appl.Math.Comp.,
|
| 770 |
+
# 8:237-250,1981" for how to improve the following (currently a
|
| 771 |
+
# rather naive) iteration process:
|
| 772 |
+
|
| 773 |
+
# a = result # sometimes iteration converges faster but where??
|
| 774 |
+
|
| 775 |
+
# Shifting to avoid zero eigenvalues. How to ensure that shifting does
|
| 776 |
+
# not change the spectrum too much?
|
| 777 |
+
vals = svd(A, compute_uv=False)
|
| 778 |
+
max_sv = np.amax(vals)
|
| 779 |
+
# min_nonzero_sv = vals[(vals>max_sv*errtol).tolist().count(1)-1]
|
| 780 |
+
# c = 0.5/min_nonzero_sv
|
| 781 |
+
c = 0.5/max_sv
|
| 782 |
+
S0 = A + c*np.identity(A.shape[0])
|
| 783 |
+
prev_errest = errest
|
| 784 |
+
for i in range(100):
|
| 785 |
+
iS0 = inv(S0)
|
| 786 |
+
S0 = 0.5*(S0 + iS0)
|
| 787 |
+
Pp = 0.5*(dot(S0, S0)+S0)
|
| 788 |
+
errest = norm(dot(Pp, Pp)-Pp, 1)
|
| 789 |
+
if errest < errtol or prev_errest == errest:
|
| 790 |
+
break
|
| 791 |
+
prev_errest = errest
|
| 792 |
+
if disp:
|
| 793 |
+
if not isfinite(errest) or errest >= errtol:
|
| 794 |
+
print("signm result may be inaccurate, approximate err =", errest)
|
| 795 |
+
return S0
|
| 796 |
+
else:
|
| 797 |
+
return S0, errest
|
| 798 |
+
|
| 799 |
+
|
| 800 |
+
def khatri_rao(a, b):
|
| 801 |
+
r"""
|
| 802 |
+
Khatri-rao product
|
| 803 |
+
|
| 804 |
+
A column-wise Kronecker product of two matrices
|
| 805 |
+
|
| 806 |
+
Parameters
|
| 807 |
+
----------
|
| 808 |
+
a : (n, k) array_like
|
| 809 |
+
Input array
|
| 810 |
+
b : (m, k) array_like
|
| 811 |
+
Input array
|
| 812 |
+
|
| 813 |
+
Returns
|
| 814 |
+
-------
|
| 815 |
+
c: (n*m, k) ndarray
|
| 816 |
+
Khatri-rao product of `a` and `b`.
|
| 817 |
+
|
| 818 |
+
See Also
|
| 819 |
+
--------
|
| 820 |
+
kron : Kronecker product
|
| 821 |
+
|
| 822 |
+
Notes
|
| 823 |
+
-----
|
| 824 |
+
The mathematical definition of the Khatri-Rao product is:
|
| 825 |
+
|
| 826 |
+
.. math::
|
| 827 |
+
|
| 828 |
+
(A_{ij} \bigotimes B_{ij})_{ij}
|
| 829 |
+
|
| 830 |
+
which is the Kronecker product of every column of A and B, e.g.::
|
| 831 |
+
|
| 832 |
+
c = np.vstack([np.kron(a[:, k], b[:, k]) for k in range(b.shape[1])]).T
|
| 833 |
+
|
| 834 |
+
Examples
|
| 835 |
+
--------
|
| 836 |
+
>>> import numpy as np
|
| 837 |
+
>>> from scipy import linalg
|
| 838 |
+
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
|
| 839 |
+
>>> b = np.array([[3, 4, 5], [6, 7, 8], [2, 3, 9]])
|
| 840 |
+
>>> linalg.khatri_rao(a, b)
|
| 841 |
+
array([[ 3, 8, 15],
|
| 842 |
+
[ 6, 14, 24],
|
| 843 |
+
[ 2, 6, 27],
|
| 844 |
+
[12, 20, 30],
|
| 845 |
+
[24, 35, 48],
|
| 846 |
+
[ 8, 15, 54]])
|
| 847 |
+
|
| 848 |
+
"""
|
| 849 |
+
a = np.asarray(a)
|
| 850 |
+
b = np.asarray(b)
|
| 851 |
+
|
| 852 |
+
if not (a.ndim == 2 and b.ndim == 2):
|
| 853 |
+
raise ValueError("The both arrays should be 2-dimensional.")
|
| 854 |
+
|
| 855 |
+
if not a.shape[1] == b.shape[1]:
|
| 856 |
+
raise ValueError("The number of columns for both arrays "
|
| 857 |
+
"should be equal.")
|
| 858 |
+
|
| 859 |
+
# c = np.vstack([np.kron(a[:, k], b[:, k]) for k in range(b.shape[1])]).T
|
| 860 |
+
c = a[..., :, np.newaxis, :] * b[..., np.newaxis, :, :]
|
| 861 |
+
return c.reshape((-1,) + c.shape[2:])
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_expm.pyi
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from numpy.typing import NDArray
|
| 2 |
+
from typing import Any
|
| 3 |
+
|
| 4 |
+
def pick_pade_structure(a: NDArray[Any]) -> tuple[int, int]: ...
|
| 5 |
+
|
| 6 |
+
def pade_UV_calc(Am: NDArray[Any], n: int, m: int) -> None: ...
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_inv_ssq.py
ADDED
|
@@ -0,0 +1,886 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Matrix functions that use Pade approximation with inverse scaling and squaring.
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
import warnings
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
|
| 9 |
+
from scipy.linalg._matfuncs_sqrtm import SqrtmError, _sqrtm_triu
|
| 10 |
+
from scipy.linalg._decomp_schur import schur, rsf2csf
|
| 11 |
+
from scipy.linalg._matfuncs import funm
|
| 12 |
+
from scipy.linalg import svdvals, solve_triangular
|
| 13 |
+
from scipy.sparse.linalg._interface import LinearOperator
|
| 14 |
+
from scipy.sparse.linalg import onenormest
|
| 15 |
+
import scipy.special
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class LogmRankWarning(UserWarning):
|
| 19 |
+
pass
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class LogmExactlySingularWarning(LogmRankWarning):
|
| 23 |
+
pass
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class LogmNearlySingularWarning(LogmRankWarning):
|
| 27 |
+
pass
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class LogmError(np.linalg.LinAlgError):
|
| 31 |
+
pass
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class FractionalMatrixPowerError(np.linalg.LinAlgError):
|
| 35 |
+
pass
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
#TODO renovate or move this class when scipy operators are more mature
|
| 39 |
+
class _MatrixM1PowerOperator(LinearOperator):
|
| 40 |
+
"""
|
| 41 |
+
A representation of the linear operator (A - I)^p.
|
| 42 |
+
"""
|
| 43 |
+
|
| 44 |
+
def __init__(self, A, p):
|
| 45 |
+
if A.ndim != 2 or A.shape[0] != A.shape[1]:
|
| 46 |
+
raise ValueError('expected A to be like a square matrix')
|
| 47 |
+
if p < 0 or p != int(p):
|
| 48 |
+
raise ValueError('expected p to be a non-negative integer')
|
| 49 |
+
self._A = A
|
| 50 |
+
self._p = p
|
| 51 |
+
self.ndim = A.ndim
|
| 52 |
+
self.shape = A.shape
|
| 53 |
+
|
| 54 |
+
def _matvec(self, x):
|
| 55 |
+
for i in range(self._p):
|
| 56 |
+
x = self._A.dot(x) - x
|
| 57 |
+
return x
|
| 58 |
+
|
| 59 |
+
def _rmatvec(self, x):
|
| 60 |
+
for i in range(self._p):
|
| 61 |
+
x = x.dot(self._A) - x
|
| 62 |
+
return x
|
| 63 |
+
|
| 64 |
+
def _matmat(self, X):
|
| 65 |
+
for i in range(self._p):
|
| 66 |
+
X = self._A.dot(X) - X
|
| 67 |
+
return X
|
| 68 |
+
|
| 69 |
+
def _adjoint(self):
|
| 70 |
+
return _MatrixM1PowerOperator(self._A.T, self._p)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
#TODO renovate or move this function when SciPy operators are more mature
|
| 74 |
+
def _onenormest_m1_power(A, p,
|
| 75 |
+
t=2, itmax=5, compute_v=False, compute_w=False):
|
| 76 |
+
"""
|
| 77 |
+
Efficiently estimate the 1-norm of (A - I)^p.
|
| 78 |
+
|
| 79 |
+
Parameters
|
| 80 |
+
----------
|
| 81 |
+
A : ndarray
|
| 82 |
+
Matrix whose 1-norm of a power is to be computed.
|
| 83 |
+
p : int
|
| 84 |
+
Non-negative integer power.
|
| 85 |
+
t : int, optional
|
| 86 |
+
A positive parameter controlling the tradeoff between
|
| 87 |
+
accuracy versus time and memory usage.
|
| 88 |
+
Larger values take longer and use more memory
|
| 89 |
+
but give more accurate output.
|
| 90 |
+
itmax : int, optional
|
| 91 |
+
Use at most this many iterations.
|
| 92 |
+
compute_v : bool, optional
|
| 93 |
+
Request a norm-maximizing linear operator input vector if True.
|
| 94 |
+
compute_w : bool, optional
|
| 95 |
+
Request a norm-maximizing linear operator output vector if True.
|
| 96 |
+
|
| 97 |
+
Returns
|
| 98 |
+
-------
|
| 99 |
+
est : float
|
| 100 |
+
An underestimate of the 1-norm of the sparse matrix.
|
| 101 |
+
v : ndarray, optional
|
| 102 |
+
The vector such that ||Av||_1 == est*||v||_1.
|
| 103 |
+
It can be thought of as an input to the linear operator
|
| 104 |
+
that gives an output with particularly large norm.
|
| 105 |
+
w : ndarray, optional
|
| 106 |
+
The vector Av which has relatively large 1-norm.
|
| 107 |
+
It can be thought of as an output of the linear operator
|
| 108 |
+
that is relatively large in norm compared to the input.
|
| 109 |
+
|
| 110 |
+
"""
|
| 111 |
+
return onenormest(_MatrixM1PowerOperator(A, p),
|
| 112 |
+
t=t, itmax=itmax, compute_v=compute_v, compute_w=compute_w)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _unwindk(z):
|
| 116 |
+
"""
|
| 117 |
+
Compute the scalar unwinding number.
|
| 118 |
+
|
| 119 |
+
Uses Eq. (5.3) in [1]_, and should be equal to (z - log(exp(z)) / (2 pi i).
|
| 120 |
+
Note that this definition differs in sign from the original definition
|
| 121 |
+
in equations (5, 6) in [2]_. The sign convention is justified in [3]_.
|
| 122 |
+
|
| 123 |
+
Parameters
|
| 124 |
+
----------
|
| 125 |
+
z : complex
|
| 126 |
+
A complex number.
|
| 127 |
+
|
| 128 |
+
Returns
|
| 129 |
+
-------
|
| 130 |
+
unwinding_number : integer
|
| 131 |
+
The scalar unwinding number of z.
|
| 132 |
+
|
| 133 |
+
References
|
| 134 |
+
----------
|
| 135 |
+
.. [1] Nicholas J. Higham and Lijing lin (2011)
|
| 136 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 137 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 138 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 139 |
+
|
| 140 |
+
.. [2] Robert M. Corless and David J. Jeffrey,
|
| 141 |
+
"The unwinding number." Newsletter ACM SIGSAM Bulletin
|
| 142 |
+
Volume 30, Issue 2, June 1996, Pages 28-35.
|
| 143 |
+
|
| 144 |
+
.. [3] Russell Bradford and Robert M. Corless and James H. Davenport and
|
| 145 |
+
David J. Jeffrey and Stephen M. Watt,
|
| 146 |
+
"Reasoning about the elementary functions of complex analysis"
|
| 147 |
+
Annals of Mathematics and Artificial Intelligence,
|
| 148 |
+
36: 303-318, 2002.
|
| 149 |
+
|
| 150 |
+
"""
|
| 151 |
+
return int(np.ceil((z.imag - np.pi) / (2*np.pi)))
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def _briggs_helper_function(a, k):
|
| 155 |
+
"""
|
| 156 |
+
Computes r = a^(1 / (2^k)) - 1.
|
| 157 |
+
|
| 158 |
+
This is algorithm (2) of [1]_.
|
| 159 |
+
The purpose is to avoid a danger of subtractive cancellation.
|
| 160 |
+
For more computational efficiency it should probably be cythonized.
|
| 161 |
+
|
| 162 |
+
Parameters
|
| 163 |
+
----------
|
| 164 |
+
a : complex
|
| 165 |
+
A complex number.
|
| 166 |
+
k : integer
|
| 167 |
+
A nonnegative integer.
|
| 168 |
+
|
| 169 |
+
Returns
|
| 170 |
+
-------
|
| 171 |
+
r : complex
|
| 172 |
+
The value r = a^(1 / (2^k)) - 1 computed with less cancellation.
|
| 173 |
+
|
| 174 |
+
Notes
|
| 175 |
+
-----
|
| 176 |
+
The algorithm as formulated in the reference does not handle k=0 or k=1
|
| 177 |
+
correctly, so these are special-cased in this implementation.
|
| 178 |
+
This function is intended to not allow `a` to belong to the closed
|
| 179 |
+
negative real axis, but this constraint is relaxed.
|
| 180 |
+
|
| 181 |
+
References
|
| 182 |
+
----------
|
| 183 |
+
.. [1] Awad H. Al-Mohy (2012)
|
| 184 |
+
"A more accurate Briggs method for the logarithm",
|
| 185 |
+
Numerical Algorithms, 59 : 393--402.
|
| 186 |
+
|
| 187 |
+
"""
|
| 188 |
+
if k < 0 or int(k) != k:
|
| 189 |
+
raise ValueError('expected a nonnegative integer k')
|
| 190 |
+
if k == 0:
|
| 191 |
+
return a - 1
|
| 192 |
+
elif k == 1:
|
| 193 |
+
return np.sqrt(a) - 1
|
| 194 |
+
else:
|
| 195 |
+
k_hat = k
|
| 196 |
+
if np.angle(a) >= np.pi / 2:
|
| 197 |
+
a = np.sqrt(a)
|
| 198 |
+
k_hat = k - 1
|
| 199 |
+
z0 = a - 1
|
| 200 |
+
a = np.sqrt(a)
|
| 201 |
+
r = 1 + a
|
| 202 |
+
for j in range(1, k_hat):
|
| 203 |
+
a = np.sqrt(a)
|
| 204 |
+
r = r * (1 + a)
|
| 205 |
+
r = z0 / r
|
| 206 |
+
return r
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def _fractional_power_superdiag_entry(l1, l2, t12, p):
|
| 210 |
+
"""
|
| 211 |
+
Compute a superdiagonal entry of a fractional matrix power.
|
| 212 |
+
|
| 213 |
+
This is Eq. (5.6) in [1]_.
|
| 214 |
+
|
| 215 |
+
Parameters
|
| 216 |
+
----------
|
| 217 |
+
l1 : complex
|
| 218 |
+
A diagonal entry of the matrix.
|
| 219 |
+
l2 : complex
|
| 220 |
+
A diagonal entry of the matrix.
|
| 221 |
+
t12 : complex
|
| 222 |
+
A superdiagonal entry of the matrix.
|
| 223 |
+
p : float
|
| 224 |
+
A fractional power.
|
| 225 |
+
|
| 226 |
+
Returns
|
| 227 |
+
-------
|
| 228 |
+
f12 : complex
|
| 229 |
+
A superdiagonal entry of the fractional matrix power.
|
| 230 |
+
|
| 231 |
+
Notes
|
| 232 |
+
-----
|
| 233 |
+
Care has been taken to return a real number if possible when
|
| 234 |
+
all of the inputs are real numbers.
|
| 235 |
+
|
| 236 |
+
References
|
| 237 |
+
----------
|
| 238 |
+
.. [1] Nicholas J. Higham and Lijing lin (2011)
|
| 239 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 240 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 241 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 242 |
+
|
| 243 |
+
"""
|
| 244 |
+
if l1 == l2:
|
| 245 |
+
f12 = t12 * p * l1**(p-1)
|
| 246 |
+
elif abs(l2 - l1) > abs(l1 + l2) / 2:
|
| 247 |
+
f12 = t12 * ((l2**p) - (l1**p)) / (l2 - l1)
|
| 248 |
+
else:
|
| 249 |
+
# This is Eq. (5.5) in [1].
|
| 250 |
+
z = (l2 - l1) / (l2 + l1)
|
| 251 |
+
log_l1 = np.log(l1)
|
| 252 |
+
log_l2 = np.log(l2)
|
| 253 |
+
arctanh_z = np.arctanh(z)
|
| 254 |
+
tmp_a = t12 * np.exp((p/2)*(log_l2 + log_l1))
|
| 255 |
+
tmp_u = _unwindk(log_l2 - log_l1)
|
| 256 |
+
if tmp_u:
|
| 257 |
+
tmp_b = p * (arctanh_z + np.pi * 1j * tmp_u)
|
| 258 |
+
else:
|
| 259 |
+
tmp_b = p * arctanh_z
|
| 260 |
+
tmp_c = 2 * np.sinh(tmp_b) / (l2 - l1)
|
| 261 |
+
f12 = tmp_a * tmp_c
|
| 262 |
+
return f12
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def _logm_superdiag_entry(l1, l2, t12):
|
| 266 |
+
"""
|
| 267 |
+
Compute a superdiagonal entry of a matrix logarithm.
|
| 268 |
+
|
| 269 |
+
This is like Eq. (11.28) in [1]_, except the determination of whether
|
| 270 |
+
l1 and l2 are sufficiently far apart has been modified.
|
| 271 |
+
|
| 272 |
+
Parameters
|
| 273 |
+
----------
|
| 274 |
+
l1 : complex
|
| 275 |
+
A diagonal entry of the matrix.
|
| 276 |
+
l2 : complex
|
| 277 |
+
A diagonal entry of the matrix.
|
| 278 |
+
t12 : complex
|
| 279 |
+
A superdiagonal entry of the matrix.
|
| 280 |
+
|
| 281 |
+
Returns
|
| 282 |
+
-------
|
| 283 |
+
f12 : complex
|
| 284 |
+
A superdiagonal entry of the matrix logarithm.
|
| 285 |
+
|
| 286 |
+
Notes
|
| 287 |
+
-----
|
| 288 |
+
Care has been taken to return a real number if possible when
|
| 289 |
+
all of the inputs are real numbers.
|
| 290 |
+
|
| 291 |
+
References
|
| 292 |
+
----------
|
| 293 |
+
.. [1] Nicholas J. Higham (2008)
|
| 294 |
+
"Functions of Matrices: Theory and Computation"
|
| 295 |
+
ISBN 978-0-898716-46-7
|
| 296 |
+
|
| 297 |
+
"""
|
| 298 |
+
if l1 == l2:
|
| 299 |
+
f12 = t12 / l1
|
| 300 |
+
elif abs(l2 - l1) > abs(l1 + l2) / 2:
|
| 301 |
+
f12 = t12 * (np.log(l2) - np.log(l1)) / (l2 - l1)
|
| 302 |
+
else:
|
| 303 |
+
z = (l2 - l1) / (l2 + l1)
|
| 304 |
+
u = _unwindk(np.log(l2) - np.log(l1))
|
| 305 |
+
if u:
|
| 306 |
+
f12 = t12 * 2 * (np.arctanh(z) + np.pi*1j*u) / (l2 - l1)
|
| 307 |
+
else:
|
| 308 |
+
f12 = t12 * 2 * np.arctanh(z) / (l2 - l1)
|
| 309 |
+
return f12
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
def _inverse_squaring_helper(T0, theta):
|
| 313 |
+
"""
|
| 314 |
+
A helper function for inverse scaling and squaring for Pade approximation.
|
| 315 |
+
|
| 316 |
+
Parameters
|
| 317 |
+
----------
|
| 318 |
+
T0 : (N, N) array_like upper triangular
|
| 319 |
+
Matrix involved in inverse scaling and squaring.
|
| 320 |
+
theta : indexable
|
| 321 |
+
The values theta[1] .. theta[7] must be available.
|
| 322 |
+
They represent bounds related to Pade approximation, and they depend
|
| 323 |
+
on the matrix function which is being computed.
|
| 324 |
+
For example, different values of theta are required for
|
| 325 |
+
matrix logarithm than for fractional matrix power.
|
| 326 |
+
|
| 327 |
+
Returns
|
| 328 |
+
-------
|
| 329 |
+
R : (N, N) array_like upper triangular
|
| 330 |
+
Composition of zero or more matrix square roots of T0, minus I.
|
| 331 |
+
s : non-negative integer
|
| 332 |
+
Number of square roots taken.
|
| 333 |
+
m : positive integer
|
| 334 |
+
The degree of the Pade approximation.
|
| 335 |
+
|
| 336 |
+
Notes
|
| 337 |
+
-----
|
| 338 |
+
This subroutine appears as a chunk of lines within
|
| 339 |
+
a couple of published algorithms; for example it appears
|
| 340 |
+
as lines 4--35 in algorithm (3.1) of [1]_, and
|
| 341 |
+
as lines 3--34 in algorithm (4.1) of [2]_.
|
| 342 |
+
The instances of 'goto line 38' in algorithm (3.1) of [1]_
|
| 343 |
+
probably mean 'goto line 36' and have been interpreted accordingly.
|
| 344 |
+
|
| 345 |
+
References
|
| 346 |
+
----------
|
| 347 |
+
.. [1] Nicholas J. Higham and Lijing Lin (2013)
|
| 348 |
+
"An Improved Schur-Pade Algorithm for Fractional Powers
|
| 349 |
+
of a Matrix and their Frechet Derivatives."
|
| 350 |
+
|
| 351 |
+
.. [2] Awad H. Al-Mohy and Nicholas J. Higham (2012)
|
| 352 |
+
"Improved Inverse Scaling and Squaring Algorithms
|
| 353 |
+
for the Matrix Logarithm."
|
| 354 |
+
SIAM Journal on Scientific Computing, 34 (4). C152-C169.
|
| 355 |
+
ISSN 1095-7197
|
| 356 |
+
|
| 357 |
+
"""
|
| 358 |
+
if len(T0.shape) != 2 or T0.shape[0] != T0.shape[1]:
|
| 359 |
+
raise ValueError('expected an upper triangular square matrix')
|
| 360 |
+
n, n = T0.shape
|
| 361 |
+
T = T0
|
| 362 |
+
|
| 363 |
+
# Find s0, the smallest s such that the spectral radius
|
| 364 |
+
# of a certain diagonal matrix is at most theta[7].
|
| 365 |
+
# Note that because theta[7] < 1,
|
| 366 |
+
# this search will not terminate if any diagonal entry of T is zero.
|
| 367 |
+
s0 = 0
|
| 368 |
+
tmp_diag = np.diag(T)
|
| 369 |
+
if np.count_nonzero(tmp_diag) != n:
|
| 370 |
+
raise Exception('Diagonal entries of T must be nonzero')
|
| 371 |
+
while np.max(np.absolute(tmp_diag - 1)) > theta[7]:
|
| 372 |
+
tmp_diag = np.sqrt(tmp_diag)
|
| 373 |
+
s0 += 1
|
| 374 |
+
|
| 375 |
+
# Take matrix square roots of T.
|
| 376 |
+
for i in range(s0):
|
| 377 |
+
T = _sqrtm_triu(T)
|
| 378 |
+
|
| 379 |
+
# Flow control in this section is a little odd.
|
| 380 |
+
# This is because I am translating algorithm descriptions
|
| 381 |
+
# which have GOTOs in the publication.
|
| 382 |
+
s = s0
|
| 383 |
+
k = 0
|
| 384 |
+
d2 = _onenormest_m1_power(T, 2) ** (1/2)
|
| 385 |
+
d3 = _onenormest_m1_power(T, 3) ** (1/3)
|
| 386 |
+
a2 = max(d2, d3)
|
| 387 |
+
m = None
|
| 388 |
+
for i in (1, 2):
|
| 389 |
+
if a2 <= theta[i]:
|
| 390 |
+
m = i
|
| 391 |
+
break
|
| 392 |
+
while m is None:
|
| 393 |
+
if s > s0:
|
| 394 |
+
d3 = _onenormest_m1_power(T, 3) ** (1/3)
|
| 395 |
+
d4 = _onenormest_m1_power(T, 4) ** (1/4)
|
| 396 |
+
a3 = max(d3, d4)
|
| 397 |
+
if a3 <= theta[7]:
|
| 398 |
+
j1 = min(i for i in (3, 4, 5, 6, 7) if a3 <= theta[i])
|
| 399 |
+
if j1 <= 6:
|
| 400 |
+
m = j1
|
| 401 |
+
break
|
| 402 |
+
elif a3 / 2 <= theta[5] and k < 2:
|
| 403 |
+
k += 1
|
| 404 |
+
T = _sqrtm_triu(T)
|
| 405 |
+
s += 1
|
| 406 |
+
continue
|
| 407 |
+
d5 = _onenormest_m1_power(T, 5) ** (1/5)
|
| 408 |
+
a4 = max(d4, d5)
|
| 409 |
+
eta = min(a3, a4)
|
| 410 |
+
for i in (6, 7):
|
| 411 |
+
if eta <= theta[i]:
|
| 412 |
+
m = i
|
| 413 |
+
break
|
| 414 |
+
if m is not None:
|
| 415 |
+
break
|
| 416 |
+
T = _sqrtm_triu(T)
|
| 417 |
+
s += 1
|
| 418 |
+
|
| 419 |
+
# The subtraction of the identity is redundant here,
|
| 420 |
+
# because the diagonal will be replaced for improved numerical accuracy,
|
| 421 |
+
# but this formulation should help clarify the meaning of R.
|
| 422 |
+
R = T - np.identity(n)
|
| 423 |
+
|
| 424 |
+
# Replace the diagonal and first superdiagonal of T0^(1/(2^s)) - I
|
| 425 |
+
# using formulas that have less subtractive cancellation.
|
| 426 |
+
# Skip this step if the principal branch
|
| 427 |
+
# does not exist at T0; this happens when a diagonal entry of T0
|
| 428 |
+
# is negative with imaginary part 0.
|
| 429 |
+
has_principal_branch = all(x.real > 0 or x.imag != 0 for x in np.diag(T0))
|
| 430 |
+
if has_principal_branch:
|
| 431 |
+
for j in range(n):
|
| 432 |
+
a = T0[j, j]
|
| 433 |
+
r = _briggs_helper_function(a, s)
|
| 434 |
+
R[j, j] = r
|
| 435 |
+
p = np.exp2(-s)
|
| 436 |
+
for j in range(n-1):
|
| 437 |
+
l1 = T0[j, j]
|
| 438 |
+
l2 = T0[j+1, j+1]
|
| 439 |
+
t12 = T0[j, j+1]
|
| 440 |
+
f12 = _fractional_power_superdiag_entry(l1, l2, t12, p)
|
| 441 |
+
R[j, j+1] = f12
|
| 442 |
+
|
| 443 |
+
# Return the T-I matrix, the number of square roots, and the Pade degree.
|
| 444 |
+
if not np.array_equal(R, np.triu(R)):
|
| 445 |
+
raise Exception('R is not upper triangular')
|
| 446 |
+
return R, s, m
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
def _fractional_power_pade_constant(i, t):
|
| 450 |
+
# A helper function for matrix fractional power.
|
| 451 |
+
if i < 1:
|
| 452 |
+
raise ValueError('expected a positive integer i')
|
| 453 |
+
if not (-1 < t < 1):
|
| 454 |
+
raise ValueError('expected -1 < t < 1')
|
| 455 |
+
if i == 1:
|
| 456 |
+
return -t
|
| 457 |
+
elif i % 2 == 0:
|
| 458 |
+
j = i // 2
|
| 459 |
+
return (-j + t) / (2 * (2*j - 1))
|
| 460 |
+
elif i % 2 == 1:
|
| 461 |
+
j = (i - 1) // 2
|
| 462 |
+
return (-j - t) / (2 * (2*j + 1))
|
| 463 |
+
else:
|
| 464 |
+
raise Exception(f'unnexpected value of i, i = {i}')
|
| 465 |
+
|
| 466 |
+
|
| 467 |
+
def _fractional_power_pade(R, t, m):
|
| 468 |
+
"""
|
| 469 |
+
Evaluate the Pade approximation of a fractional matrix power.
|
| 470 |
+
|
| 471 |
+
Evaluate the degree-m Pade approximation of R
|
| 472 |
+
to the fractional matrix power t using the continued fraction
|
| 473 |
+
in bottom-up fashion using algorithm (4.1) in [1]_.
|
| 474 |
+
|
| 475 |
+
Parameters
|
| 476 |
+
----------
|
| 477 |
+
R : (N, N) array_like
|
| 478 |
+
Upper triangular matrix whose fractional power to evaluate.
|
| 479 |
+
t : float
|
| 480 |
+
Fractional power between -1 and 1 exclusive.
|
| 481 |
+
m : positive integer
|
| 482 |
+
Degree of Pade approximation.
|
| 483 |
+
|
| 484 |
+
Returns
|
| 485 |
+
-------
|
| 486 |
+
U : (N, N) array_like
|
| 487 |
+
The degree-m Pade approximation of R to the fractional power t.
|
| 488 |
+
This matrix will be upper triangular.
|
| 489 |
+
|
| 490 |
+
References
|
| 491 |
+
----------
|
| 492 |
+
.. [1] Nicholas J. Higham and Lijing lin (2011)
|
| 493 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 494 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 495 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 496 |
+
|
| 497 |
+
"""
|
| 498 |
+
if m < 1 or int(m) != m:
|
| 499 |
+
raise ValueError('expected a positive integer m')
|
| 500 |
+
if not (-1 < t < 1):
|
| 501 |
+
raise ValueError('expected -1 < t < 1')
|
| 502 |
+
R = np.asarray(R)
|
| 503 |
+
if len(R.shape) != 2 or R.shape[0] != R.shape[1]:
|
| 504 |
+
raise ValueError('expected an upper triangular square matrix')
|
| 505 |
+
n, n = R.shape
|
| 506 |
+
ident = np.identity(n)
|
| 507 |
+
Y = R * _fractional_power_pade_constant(2*m, t)
|
| 508 |
+
for j in range(2*m - 1, 0, -1):
|
| 509 |
+
rhs = R * _fractional_power_pade_constant(j, t)
|
| 510 |
+
Y = solve_triangular(ident + Y, rhs)
|
| 511 |
+
U = ident + Y
|
| 512 |
+
if not np.array_equal(U, np.triu(U)):
|
| 513 |
+
raise Exception('U is not upper triangular')
|
| 514 |
+
return U
|
| 515 |
+
|
| 516 |
+
|
| 517 |
+
def _remainder_matrix_power_triu(T, t):
|
| 518 |
+
"""
|
| 519 |
+
Compute a fractional power of an upper triangular matrix.
|
| 520 |
+
|
| 521 |
+
The fractional power is restricted to fractions -1 < t < 1.
|
| 522 |
+
This uses algorithm (3.1) of [1]_.
|
| 523 |
+
The Pade approximation itself uses algorithm (4.1) of [2]_.
|
| 524 |
+
|
| 525 |
+
Parameters
|
| 526 |
+
----------
|
| 527 |
+
T : (N, N) array_like
|
| 528 |
+
Upper triangular matrix whose fractional power to evaluate.
|
| 529 |
+
t : float
|
| 530 |
+
Fractional power between -1 and 1 exclusive.
|
| 531 |
+
|
| 532 |
+
Returns
|
| 533 |
+
-------
|
| 534 |
+
X : (N, N) array_like
|
| 535 |
+
The fractional power of the matrix.
|
| 536 |
+
|
| 537 |
+
References
|
| 538 |
+
----------
|
| 539 |
+
.. [1] Nicholas J. Higham and Lijing Lin (2013)
|
| 540 |
+
"An Improved Schur-Pade Algorithm for Fractional Powers
|
| 541 |
+
of a Matrix and their Frechet Derivatives."
|
| 542 |
+
|
| 543 |
+
.. [2] Nicholas J. Higham and Lijing lin (2011)
|
| 544 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 545 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 546 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 547 |
+
|
| 548 |
+
"""
|
| 549 |
+
m_to_theta = {
|
| 550 |
+
1: 1.51e-5,
|
| 551 |
+
2: 2.24e-3,
|
| 552 |
+
3: 1.88e-2,
|
| 553 |
+
4: 6.04e-2,
|
| 554 |
+
5: 1.24e-1,
|
| 555 |
+
6: 2.00e-1,
|
| 556 |
+
7: 2.79e-1,
|
| 557 |
+
}
|
| 558 |
+
n, n = T.shape
|
| 559 |
+
T0 = T
|
| 560 |
+
T0_diag = np.diag(T0)
|
| 561 |
+
if np.array_equal(T0, np.diag(T0_diag)):
|
| 562 |
+
U = np.diag(T0_diag ** t)
|
| 563 |
+
else:
|
| 564 |
+
R, s, m = _inverse_squaring_helper(T0, m_to_theta)
|
| 565 |
+
|
| 566 |
+
# Evaluate the Pade approximation.
|
| 567 |
+
# Note that this function expects the negative of the matrix
|
| 568 |
+
# returned by the inverse squaring helper.
|
| 569 |
+
U = _fractional_power_pade(-R, t, m)
|
| 570 |
+
|
| 571 |
+
# Undo the inverse scaling and squaring.
|
| 572 |
+
# Be less clever about this
|
| 573 |
+
# if the principal branch does not exist at T0;
|
| 574 |
+
# this happens when a diagonal entry of T0
|
| 575 |
+
# is negative with imaginary part 0.
|
| 576 |
+
eivals = np.diag(T0)
|
| 577 |
+
has_principal_branch = all(x.real > 0 or x.imag != 0 for x in eivals)
|
| 578 |
+
for i in range(s, -1, -1):
|
| 579 |
+
if i < s:
|
| 580 |
+
U = U.dot(U)
|
| 581 |
+
else:
|
| 582 |
+
if has_principal_branch:
|
| 583 |
+
p = t * np.exp2(-i)
|
| 584 |
+
U[np.diag_indices(n)] = T0_diag ** p
|
| 585 |
+
for j in range(n-1):
|
| 586 |
+
l1 = T0[j, j]
|
| 587 |
+
l2 = T0[j+1, j+1]
|
| 588 |
+
t12 = T0[j, j+1]
|
| 589 |
+
f12 = _fractional_power_superdiag_entry(l1, l2, t12, p)
|
| 590 |
+
U[j, j+1] = f12
|
| 591 |
+
if not np.array_equal(U, np.triu(U)):
|
| 592 |
+
raise Exception('U is not upper triangular')
|
| 593 |
+
return U
|
| 594 |
+
|
| 595 |
+
|
| 596 |
+
def _remainder_matrix_power(A, t):
|
| 597 |
+
"""
|
| 598 |
+
Compute the fractional power of a matrix, for fractions -1 < t < 1.
|
| 599 |
+
|
| 600 |
+
This uses algorithm (3.1) of [1]_.
|
| 601 |
+
The Pade approximation itself uses algorithm (4.1) of [2]_.
|
| 602 |
+
|
| 603 |
+
Parameters
|
| 604 |
+
----------
|
| 605 |
+
A : (N, N) array_like
|
| 606 |
+
Matrix whose fractional power to evaluate.
|
| 607 |
+
t : float
|
| 608 |
+
Fractional power between -1 and 1 exclusive.
|
| 609 |
+
|
| 610 |
+
Returns
|
| 611 |
+
-------
|
| 612 |
+
X : (N, N) array_like
|
| 613 |
+
The fractional power of the matrix.
|
| 614 |
+
|
| 615 |
+
References
|
| 616 |
+
----------
|
| 617 |
+
.. [1] Nicholas J. Higham and Lijing Lin (2013)
|
| 618 |
+
"An Improved Schur-Pade Algorithm for Fractional Powers
|
| 619 |
+
of a Matrix and their Frechet Derivatives."
|
| 620 |
+
|
| 621 |
+
.. [2] Nicholas J. Higham and Lijing lin (2011)
|
| 622 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 623 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 624 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 625 |
+
|
| 626 |
+
"""
|
| 627 |
+
# This code block is copied from numpy.matrix_power().
|
| 628 |
+
A = np.asarray(A)
|
| 629 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 630 |
+
raise ValueError('input must be a square array')
|
| 631 |
+
|
| 632 |
+
# Get the number of rows and columns.
|
| 633 |
+
n, n = A.shape
|
| 634 |
+
|
| 635 |
+
# Triangularize the matrix if necessary,
|
| 636 |
+
# attempting to preserve dtype if possible.
|
| 637 |
+
if np.array_equal(A, np.triu(A)):
|
| 638 |
+
Z = None
|
| 639 |
+
T = A
|
| 640 |
+
else:
|
| 641 |
+
if np.isrealobj(A):
|
| 642 |
+
T, Z = schur(A)
|
| 643 |
+
if not np.array_equal(T, np.triu(T)):
|
| 644 |
+
T, Z = rsf2csf(T, Z)
|
| 645 |
+
else:
|
| 646 |
+
T, Z = schur(A, output='complex')
|
| 647 |
+
|
| 648 |
+
# Zeros on the diagonal of the triangular matrix are forbidden,
|
| 649 |
+
# because the inverse scaling and squaring cannot deal with it.
|
| 650 |
+
T_diag = np.diag(T)
|
| 651 |
+
if np.count_nonzero(T_diag) != n:
|
| 652 |
+
raise FractionalMatrixPowerError(
|
| 653 |
+
'cannot use inverse scaling and squaring to find '
|
| 654 |
+
'the fractional matrix power of a singular matrix')
|
| 655 |
+
|
| 656 |
+
# If the triangular matrix is real and has a negative
|
| 657 |
+
# entry on the diagonal, then force the matrix to be complex.
|
| 658 |
+
if np.isrealobj(T) and np.min(T_diag) < 0:
|
| 659 |
+
T = T.astype(complex)
|
| 660 |
+
|
| 661 |
+
# Get the fractional power of the triangular matrix,
|
| 662 |
+
# and de-triangularize it if necessary.
|
| 663 |
+
U = _remainder_matrix_power_triu(T, t)
|
| 664 |
+
if Z is not None:
|
| 665 |
+
ZH = np.conjugate(Z).T
|
| 666 |
+
return Z.dot(U).dot(ZH)
|
| 667 |
+
else:
|
| 668 |
+
return U
|
| 669 |
+
|
| 670 |
+
|
| 671 |
+
def _fractional_matrix_power(A, p):
|
| 672 |
+
"""
|
| 673 |
+
Compute the fractional power of a matrix.
|
| 674 |
+
|
| 675 |
+
See the fractional_matrix_power docstring in matfuncs.py for more info.
|
| 676 |
+
|
| 677 |
+
"""
|
| 678 |
+
A = np.asarray(A)
|
| 679 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 680 |
+
raise ValueError('expected a square matrix')
|
| 681 |
+
if p == int(p):
|
| 682 |
+
return np.linalg.matrix_power(A, int(p))
|
| 683 |
+
# Compute singular values.
|
| 684 |
+
s = svdvals(A)
|
| 685 |
+
# Inverse scaling and squaring cannot deal with a singular matrix,
|
| 686 |
+
# because the process of repeatedly taking square roots
|
| 687 |
+
# would not converge to the identity matrix.
|
| 688 |
+
if s[-1]:
|
| 689 |
+
# Compute the condition number relative to matrix inversion,
|
| 690 |
+
# and use this to decide between floor(p) and ceil(p).
|
| 691 |
+
k2 = s[0] / s[-1]
|
| 692 |
+
p1 = p - np.floor(p)
|
| 693 |
+
p2 = p - np.ceil(p)
|
| 694 |
+
if p1 * k2 ** (1 - p1) <= -p2 * k2:
|
| 695 |
+
a = int(np.floor(p))
|
| 696 |
+
b = p1
|
| 697 |
+
else:
|
| 698 |
+
a = int(np.ceil(p))
|
| 699 |
+
b = p2
|
| 700 |
+
try:
|
| 701 |
+
R = _remainder_matrix_power(A, b)
|
| 702 |
+
Q = np.linalg.matrix_power(A, a)
|
| 703 |
+
return Q.dot(R)
|
| 704 |
+
except np.linalg.LinAlgError:
|
| 705 |
+
pass
|
| 706 |
+
# If p is negative then we are going to give up.
|
| 707 |
+
# If p is non-negative then we can fall back to generic funm.
|
| 708 |
+
if p < 0:
|
| 709 |
+
X = np.empty_like(A)
|
| 710 |
+
X.fill(np.nan)
|
| 711 |
+
return X
|
| 712 |
+
else:
|
| 713 |
+
p1 = p - np.floor(p)
|
| 714 |
+
a = int(np.floor(p))
|
| 715 |
+
b = p1
|
| 716 |
+
R, info = funm(A, lambda x: pow(x, b), disp=False)
|
| 717 |
+
Q = np.linalg.matrix_power(A, a)
|
| 718 |
+
return Q.dot(R)
|
| 719 |
+
|
| 720 |
+
|
| 721 |
+
def _logm_triu(T):
|
| 722 |
+
"""
|
| 723 |
+
Compute matrix logarithm of an upper triangular matrix.
|
| 724 |
+
|
| 725 |
+
The matrix logarithm is the inverse of
|
| 726 |
+
expm: expm(logm(`T`)) == `T`
|
| 727 |
+
|
| 728 |
+
Parameters
|
| 729 |
+
----------
|
| 730 |
+
T : (N, N) array_like
|
| 731 |
+
Upper triangular matrix whose logarithm to evaluate
|
| 732 |
+
|
| 733 |
+
Returns
|
| 734 |
+
-------
|
| 735 |
+
logm : (N, N) ndarray
|
| 736 |
+
Matrix logarithm of `T`
|
| 737 |
+
|
| 738 |
+
References
|
| 739 |
+
----------
|
| 740 |
+
.. [1] Awad H. Al-Mohy and Nicholas J. Higham (2012)
|
| 741 |
+
"Improved Inverse Scaling and Squaring Algorithms
|
| 742 |
+
for the Matrix Logarithm."
|
| 743 |
+
SIAM Journal on Scientific Computing, 34 (4). C152-C169.
|
| 744 |
+
ISSN 1095-7197
|
| 745 |
+
|
| 746 |
+
.. [2] Nicholas J. Higham (2008)
|
| 747 |
+
"Functions of Matrices: Theory and Computation"
|
| 748 |
+
ISBN 978-0-898716-46-7
|
| 749 |
+
|
| 750 |
+
.. [3] Nicholas J. Higham and Lijing lin (2011)
|
| 751 |
+
"A Schur-Pade Algorithm for Fractional Powers of a Matrix."
|
| 752 |
+
SIAM Journal on Matrix Analysis and Applications,
|
| 753 |
+
32 (3). pp. 1056-1078. ISSN 0895-4798
|
| 754 |
+
|
| 755 |
+
"""
|
| 756 |
+
T = np.asarray(T)
|
| 757 |
+
if len(T.shape) != 2 or T.shape[0] != T.shape[1]:
|
| 758 |
+
raise ValueError('expected an upper triangular square matrix')
|
| 759 |
+
n, n = T.shape
|
| 760 |
+
|
| 761 |
+
# Construct T0 with the appropriate type,
|
| 762 |
+
# depending on the dtype and the spectrum of T.
|
| 763 |
+
T_diag = np.diag(T)
|
| 764 |
+
keep_it_real = np.isrealobj(T) and np.min(T_diag) >= 0
|
| 765 |
+
if keep_it_real:
|
| 766 |
+
T0 = T
|
| 767 |
+
else:
|
| 768 |
+
T0 = T.astype(complex)
|
| 769 |
+
|
| 770 |
+
# Define bounds given in Table (2.1).
|
| 771 |
+
theta = (None,
|
| 772 |
+
1.59e-5, 2.31e-3, 1.94e-2, 6.21e-2,
|
| 773 |
+
1.28e-1, 2.06e-1, 2.88e-1, 3.67e-1,
|
| 774 |
+
4.39e-1, 5.03e-1, 5.60e-1, 6.09e-1,
|
| 775 |
+
6.52e-1, 6.89e-1, 7.21e-1, 7.49e-1)
|
| 776 |
+
|
| 777 |
+
R, s, m = _inverse_squaring_helper(T0, theta)
|
| 778 |
+
|
| 779 |
+
# Evaluate U = 2**s r_m(T - I) using the partial fraction expansion (1.1).
|
| 780 |
+
# This requires the nodes and weights
|
| 781 |
+
# corresponding to degree-m Gauss-Legendre quadrature.
|
| 782 |
+
# These quadrature arrays need to be transformed from the [-1, 1] interval
|
| 783 |
+
# to the [0, 1] interval.
|
| 784 |
+
nodes, weights = scipy.special.p_roots(m)
|
| 785 |
+
nodes = nodes.real
|
| 786 |
+
if nodes.shape != (m,) or weights.shape != (m,):
|
| 787 |
+
raise Exception('internal error')
|
| 788 |
+
nodes = 0.5 + 0.5 * nodes
|
| 789 |
+
weights = 0.5 * weights
|
| 790 |
+
ident = np.identity(n)
|
| 791 |
+
U = np.zeros_like(R)
|
| 792 |
+
for alpha, beta in zip(weights, nodes):
|
| 793 |
+
U += solve_triangular(ident + beta*R, alpha*R)
|
| 794 |
+
U *= np.exp2(s)
|
| 795 |
+
|
| 796 |
+
# Skip this step if the principal branch
|
| 797 |
+
# does not exist at T0; this happens when a diagonal entry of T0
|
| 798 |
+
# is negative with imaginary part 0.
|
| 799 |
+
has_principal_branch = all(x.real > 0 or x.imag != 0 for x in np.diag(T0))
|
| 800 |
+
if has_principal_branch:
|
| 801 |
+
|
| 802 |
+
# Recompute diagonal entries of U.
|
| 803 |
+
U[np.diag_indices(n)] = np.log(np.diag(T0))
|
| 804 |
+
|
| 805 |
+
# Recompute superdiagonal entries of U.
|
| 806 |
+
# This indexing of this code should be renovated
|
| 807 |
+
# when newer np.diagonal() becomes available.
|
| 808 |
+
for i in range(n-1):
|
| 809 |
+
l1 = T0[i, i]
|
| 810 |
+
l2 = T0[i+1, i+1]
|
| 811 |
+
t12 = T0[i, i+1]
|
| 812 |
+
U[i, i+1] = _logm_superdiag_entry(l1, l2, t12)
|
| 813 |
+
|
| 814 |
+
# Return the logm of the upper triangular matrix.
|
| 815 |
+
if not np.array_equal(U, np.triu(U)):
|
| 816 |
+
raise Exception('U is not upper triangular')
|
| 817 |
+
return U
|
| 818 |
+
|
| 819 |
+
|
| 820 |
+
def _logm_force_nonsingular_triangular_matrix(T, inplace=False):
|
| 821 |
+
# The input matrix should be upper triangular.
|
| 822 |
+
# The eps is ad hoc and is not meant to be machine precision.
|
| 823 |
+
tri_eps = 1e-20
|
| 824 |
+
abs_diag = np.absolute(np.diag(T))
|
| 825 |
+
if np.any(abs_diag == 0):
|
| 826 |
+
exact_singularity_msg = 'The logm input matrix is exactly singular.'
|
| 827 |
+
warnings.warn(exact_singularity_msg, LogmExactlySingularWarning, stacklevel=3)
|
| 828 |
+
if not inplace:
|
| 829 |
+
T = T.copy()
|
| 830 |
+
n = T.shape[0]
|
| 831 |
+
for i in range(n):
|
| 832 |
+
if not T[i, i]:
|
| 833 |
+
T[i, i] = tri_eps
|
| 834 |
+
elif np.any(abs_diag < tri_eps):
|
| 835 |
+
near_singularity_msg = 'The logm input matrix may be nearly singular.'
|
| 836 |
+
warnings.warn(near_singularity_msg, LogmNearlySingularWarning, stacklevel=3)
|
| 837 |
+
return T
|
| 838 |
+
|
| 839 |
+
|
| 840 |
+
def _logm(A):
|
| 841 |
+
"""
|
| 842 |
+
Compute the matrix logarithm.
|
| 843 |
+
|
| 844 |
+
See the logm docstring in matfuncs.py for more info.
|
| 845 |
+
|
| 846 |
+
Notes
|
| 847 |
+
-----
|
| 848 |
+
In this function we look at triangular matrices that are similar
|
| 849 |
+
to the input matrix. If any diagonal entry of such a triangular matrix
|
| 850 |
+
is exactly zero then the original matrix is singular.
|
| 851 |
+
The matrix logarithm does not exist for such matrices,
|
| 852 |
+
but in such cases we will pretend that the diagonal entries that are zero
|
| 853 |
+
are actually slightly positive by an ad-hoc amount, in the interest
|
| 854 |
+
of returning something more useful than NaN. This will cause a warning.
|
| 855 |
+
|
| 856 |
+
"""
|
| 857 |
+
A = np.asarray(A)
|
| 858 |
+
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
|
| 859 |
+
raise ValueError('expected a square matrix')
|
| 860 |
+
|
| 861 |
+
# If the input matrix dtype is integer then copy to a float dtype matrix.
|
| 862 |
+
if issubclass(A.dtype.type, np.integer):
|
| 863 |
+
A = np.asarray(A, dtype=float)
|
| 864 |
+
|
| 865 |
+
keep_it_real = np.isrealobj(A)
|
| 866 |
+
try:
|
| 867 |
+
if np.array_equal(A, np.triu(A)):
|
| 868 |
+
A = _logm_force_nonsingular_triangular_matrix(A)
|
| 869 |
+
if np.min(np.diag(A)) < 0:
|
| 870 |
+
A = A.astype(complex)
|
| 871 |
+
return _logm_triu(A)
|
| 872 |
+
else:
|
| 873 |
+
if keep_it_real:
|
| 874 |
+
T, Z = schur(A)
|
| 875 |
+
if not np.array_equal(T, np.triu(T)):
|
| 876 |
+
T, Z = rsf2csf(T, Z)
|
| 877 |
+
else:
|
| 878 |
+
T, Z = schur(A, output='complex')
|
| 879 |
+
T = _logm_force_nonsingular_triangular_matrix(T, inplace=True)
|
| 880 |
+
U = _logm_triu(T)
|
| 881 |
+
ZH = np.conjugate(Z).T
|
| 882 |
+
return Z.dot(U).dot(ZH)
|
| 883 |
+
except (SqrtmError, LogmError):
|
| 884 |
+
X = np.empty_like(A)
|
| 885 |
+
X.fill(np.nan)
|
| 886 |
+
return X
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_sqrtm.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Matrix square root for general matrices and for upper triangular matrices.
|
| 3 |
+
|
| 4 |
+
This module exists to avoid cyclic imports.
|
| 5 |
+
|
| 6 |
+
"""
|
| 7 |
+
__all__ = ['sqrtm']
|
| 8 |
+
|
| 9 |
+
import numpy as np
|
| 10 |
+
|
| 11 |
+
from scipy._lib._util import _asarray_validated
|
| 12 |
+
|
| 13 |
+
# Local imports
|
| 14 |
+
from ._misc import norm
|
| 15 |
+
from .lapack import ztrsyl, dtrsyl
|
| 16 |
+
from ._decomp_schur import schur, rsf2csf
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class SqrtmError(np.linalg.LinAlgError):
|
| 21 |
+
pass
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
from ._matfuncs_sqrtm_triu import within_block_loop # noqa: E402
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _sqrtm_triu(T, blocksize=64):
|
| 28 |
+
"""
|
| 29 |
+
Matrix square root of an upper triangular matrix.
|
| 30 |
+
|
| 31 |
+
This is a helper function for `sqrtm` and `logm`.
|
| 32 |
+
|
| 33 |
+
Parameters
|
| 34 |
+
----------
|
| 35 |
+
T : (N, N) array_like upper triangular
|
| 36 |
+
Matrix whose square root to evaluate
|
| 37 |
+
blocksize : int, optional
|
| 38 |
+
If the blocksize is not degenerate with respect to the
|
| 39 |
+
size of the input array, then use a blocked algorithm. (Default: 64)
|
| 40 |
+
|
| 41 |
+
Returns
|
| 42 |
+
-------
|
| 43 |
+
sqrtm : (N, N) ndarray
|
| 44 |
+
Value of the sqrt function at `T`
|
| 45 |
+
|
| 46 |
+
References
|
| 47 |
+
----------
|
| 48 |
+
.. [1] Edvin Deadman, Nicholas J. Higham, Rui Ralha (2013)
|
| 49 |
+
"Blocked Schur Algorithms for Computing the Matrix Square Root,
|
| 50 |
+
Lecture Notes in Computer Science, 7782. pp. 171-182.
|
| 51 |
+
|
| 52 |
+
"""
|
| 53 |
+
T_diag = np.diag(T)
|
| 54 |
+
keep_it_real = np.isrealobj(T) and np.min(T_diag) >= 0
|
| 55 |
+
|
| 56 |
+
# Cast to complex as necessary + ensure double precision
|
| 57 |
+
if not keep_it_real:
|
| 58 |
+
T = np.asarray(T, dtype=np.complex128, order="C")
|
| 59 |
+
T_diag = np.asarray(T_diag, dtype=np.complex128)
|
| 60 |
+
else:
|
| 61 |
+
T = np.asarray(T, dtype=np.float64, order="C")
|
| 62 |
+
T_diag = np.asarray(T_diag, dtype=np.float64)
|
| 63 |
+
|
| 64 |
+
R = np.diag(np.sqrt(T_diag))
|
| 65 |
+
|
| 66 |
+
# Compute the number of blocks to use; use at least one block.
|
| 67 |
+
n, n = T.shape
|
| 68 |
+
nblocks = max(n // blocksize, 1)
|
| 69 |
+
|
| 70 |
+
# Compute the smaller of the two sizes of blocks that
|
| 71 |
+
# we will actually use, and compute the number of large blocks.
|
| 72 |
+
bsmall, nlarge = divmod(n, nblocks)
|
| 73 |
+
blarge = bsmall + 1
|
| 74 |
+
nsmall = nblocks - nlarge
|
| 75 |
+
if nsmall * bsmall + nlarge * blarge != n:
|
| 76 |
+
raise Exception('internal inconsistency')
|
| 77 |
+
|
| 78 |
+
# Define the index range covered by each block.
|
| 79 |
+
start_stop_pairs = []
|
| 80 |
+
start = 0
|
| 81 |
+
for count, size in ((nsmall, bsmall), (nlarge, blarge)):
|
| 82 |
+
for i in range(count):
|
| 83 |
+
start_stop_pairs.append((start, start + size))
|
| 84 |
+
start += size
|
| 85 |
+
|
| 86 |
+
# Within-block interactions (Cythonized)
|
| 87 |
+
try:
|
| 88 |
+
within_block_loop(R, T, start_stop_pairs, nblocks)
|
| 89 |
+
except RuntimeError as e:
|
| 90 |
+
raise SqrtmError(*e.args) from e
|
| 91 |
+
|
| 92 |
+
# Between-block interactions (Cython would give no significant speedup)
|
| 93 |
+
for j in range(nblocks):
|
| 94 |
+
jstart, jstop = start_stop_pairs[j]
|
| 95 |
+
for i in range(j-1, -1, -1):
|
| 96 |
+
istart, istop = start_stop_pairs[i]
|
| 97 |
+
S = T[istart:istop, jstart:jstop]
|
| 98 |
+
if j - i > 1:
|
| 99 |
+
S = S - R[istart:istop, istop:jstart].dot(R[istop:jstart,
|
| 100 |
+
jstart:jstop])
|
| 101 |
+
|
| 102 |
+
# Invoke LAPACK.
|
| 103 |
+
# For more details, see the solve_sylvester implementation
|
| 104 |
+
# and the fortran dtrsyl and ztrsyl docs.
|
| 105 |
+
Rii = R[istart:istop, istart:istop]
|
| 106 |
+
Rjj = R[jstart:jstop, jstart:jstop]
|
| 107 |
+
if keep_it_real:
|
| 108 |
+
x, scale, info = dtrsyl(Rii, Rjj, S)
|
| 109 |
+
else:
|
| 110 |
+
x, scale, info = ztrsyl(Rii, Rjj, S)
|
| 111 |
+
R[istart:istop, jstart:jstop] = x * scale
|
| 112 |
+
|
| 113 |
+
# Return the matrix square root.
|
| 114 |
+
return R
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def sqrtm(A, disp=True, blocksize=64):
|
| 118 |
+
"""
|
| 119 |
+
Matrix square root.
|
| 120 |
+
|
| 121 |
+
Parameters
|
| 122 |
+
----------
|
| 123 |
+
A : (N, N) array_like
|
| 124 |
+
Matrix whose square root to evaluate
|
| 125 |
+
disp : bool, optional
|
| 126 |
+
Print warning if error in the result is estimated large
|
| 127 |
+
instead of returning estimated error. (Default: True)
|
| 128 |
+
blocksize : integer, optional
|
| 129 |
+
If the blocksize is not degenerate with respect to the
|
| 130 |
+
size of the input array, then use a blocked algorithm. (Default: 64)
|
| 131 |
+
|
| 132 |
+
Returns
|
| 133 |
+
-------
|
| 134 |
+
sqrtm : (N, N) ndarray
|
| 135 |
+
Value of the sqrt function at `A`. The dtype is float or complex.
|
| 136 |
+
The precision (data size) is determined based on the precision of
|
| 137 |
+
input `A`. When the dtype is float, the precision is the same as `A`.
|
| 138 |
+
When the dtype is complex, the precision is double that of `A`. The
|
| 139 |
+
precision might be clipped by each dtype precision range.
|
| 140 |
+
|
| 141 |
+
errest : float
|
| 142 |
+
(if disp == False)
|
| 143 |
+
|
| 144 |
+
Frobenius norm of the estimated error, ||err||_F / ||A||_F
|
| 145 |
+
|
| 146 |
+
References
|
| 147 |
+
----------
|
| 148 |
+
.. [1] Edvin Deadman, Nicholas J. Higham, Rui Ralha (2013)
|
| 149 |
+
"Blocked Schur Algorithms for Computing the Matrix Square Root,
|
| 150 |
+
Lecture Notes in Computer Science, 7782. pp. 171-182.
|
| 151 |
+
|
| 152 |
+
Examples
|
| 153 |
+
--------
|
| 154 |
+
>>> import numpy as np
|
| 155 |
+
>>> from scipy.linalg import sqrtm
|
| 156 |
+
>>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
|
| 157 |
+
>>> r = sqrtm(a)
|
| 158 |
+
>>> r
|
| 159 |
+
array([[ 0.75592895, 1.13389342],
|
| 160 |
+
[ 0.37796447, 1.88982237]])
|
| 161 |
+
>>> r.dot(r)
|
| 162 |
+
array([[ 1., 3.],
|
| 163 |
+
[ 1., 4.]])
|
| 164 |
+
|
| 165 |
+
"""
|
| 166 |
+
byte_size = np.asarray(A).dtype.itemsize
|
| 167 |
+
A = _asarray_validated(A, check_finite=True, as_inexact=True)
|
| 168 |
+
if len(A.shape) != 2:
|
| 169 |
+
raise ValueError("Non-matrix input to matrix function.")
|
| 170 |
+
if blocksize < 1:
|
| 171 |
+
raise ValueError("The blocksize should be at least 1.")
|
| 172 |
+
keep_it_real = np.isrealobj(A)
|
| 173 |
+
if keep_it_real:
|
| 174 |
+
T, Z = schur(A)
|
| 175 |
+
d0 = np.diagonal(T)
|
| 176 |
+
d1 = np.diagonal(T, -1)
|
| 177 |
+
eps = np.finfo(T.dtype).eps
|
| 178 |
+
needs_conversion = abs(d1) > eps * (abs(d0[1:]) + abs(d0[:-1]))
|
| 179 |
+
if needs_conversion.any():
|
| 180 |
+
T, Z = rsf2csf(T, Z)
|
| 181 |
+
else:
|
| 182 |
+
T, Z = schur(A, output='complex')
|
| 183 |
+
failflag = False
|
| 184 |
+
try:
|
| 185 |
+
R = _sqrtm_triu(T, blocksize=blocksize)
|
| 186 |
+
ZH = np.conjugate(Z).T
|
| 187 |
+
X = Z.dot(R).dot(ZH)
|
| 188 |
+
if not np.iscomplexobj(X):
|
| 189 |
+
# float byte size range: f2 ~ f16
|
| 190 |
+
X = X.astype(f"f{np.clip(byte_size, 2, 16)}", copy=False)
|
| 191 |
+
else:
|
| 192 |
+
# complex byte size range: c8 ~ c32.
|
| 193 |
+
# c32(complex256) might not be supported in some environments.
|
| 194 |
+
if hasattr(np, 'complex256'):
|
| 195 |
+
X = X.astype(f"c{np.clip(byte_size*2, 8, 32)}", copy=False)
|
| 196 |
+
else:
|
| 197 |
+
X = X.astype(f"c{np.clip(byte_size*2, 8, 16)}", copy=False)
|
| 198 |
+
except SqrtmError:
|
| 199 |
+
failflag = True
|
| 200 |
+
X = np.empty_like(A)
|
| 201 |
+
X.fill(np.nan)
|
| 202 |
+
|
| 203 |
+
if disp:
|
| 204 |
+
if failflag:
|
| 205 |
+
print("Failed to find a square root.")
|
| 206 |
+
return X
|
| 207 |
+
else:
|
| 208 |
+
try:
|
| 209 |
+
arg2 = norm(X.dot(X) - A, 'fro')**2 / norm(A, 'fro')
|
| 210 |
+
except ValueError:
|
| 211 |
+
# NaNs in matrix
|
| 212 |
+
arg2 = np.inf
|
| 213 |
+
|
| 214 |
+
return X, arg2
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_misc.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
from numpy.linalg import LinAlgError
|
| 3 |
+
from .blas import get_blas_funcs
|
| 4 |
+
from .lapack import get_lapack_funcs
|
| 5 |
+
|
| 6 |
+
__all__ = ['LinAlgError', 'LinAlgWarning', 'norm']
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class LinAlgWarning(RuntimeWarning):
|
| 10 |
+
"""
|
| 11 |
+
The warning emitted when a linear algebra related operation is close
|
| 12 |
+
to fail conditions of the algorithm or loss of accuracy is expected.
|
| 13 |
+
"""
|
| 14 |
+
pass
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def norm(a, ord=None, axis=None, keepdims=False, check_finite=True):
|
| 18 |
+
"""
|
| 19 |
+
Matrix or vector norm.
|
| 20 |
+
|
| 21 |
+
This function is able to return one of eight different matrix norms,
|
| 22 |
+
or one of an infinite number of vector norms (described below), depending
|
| 23 |
+
on the value of the ``ord`` parameter. For tensors with rank different from
|
| 24 |
+
1 or 2, only `ord=None` is supported.
|
| 25 |
+
|
| 26 |
+
Parameters
|
| 27 |
+
----------
|
| 28 |
+
a : array_like
|
| 29 |
+
Input array. If `axis` is None, `a` must be 1-D or 2-D, unless `ord`
|
| 30 |
+
is None. If both `axis` and `ord` are None, the 2-norm of
|
| 31 |
+
``a.ravel`` will be returned.
|
| 32 |
+
ord : {int, inf, -inf, 'fro', 'nuc', None}, optional
|
| 33 |
+
Order of the norm (see table under ``Notes``). inf means NumPy's
|
| 34 |
+
`inf` object.
|
| 35 |
+
axis : {int, 2-tuple of ints, None}, optional
|
| 36 |
+
If `axis` is an integer, it specifies the axis of `a` along which to
|
| 37 |
+
compute the vector norms. If `axis` is a 2-tuple, it specifies the
|
| 38 |
+
axes that hold 2-D matrices, and the matrix norms of these matrices
|
| 39 |
+
are computed. If `axis` is None then either a vector norm (when `a`
|
| 40 |
+
is 1-D) or a matrix norm (when `a` is 2-D) is returned.
|
| 41 |
+
keepdims : bool, optional
|
| 42 |
+
If this is set to True, the axes which are normed over are left in the
|
| 43 |
+
result as dimensions with size one. With this option the result will
|
| 44 |
+
broadcast correctly against the original `a`.
|
| 45 |
+
check_finite : bool, optional
|
| 46 |
+
Whether to check that the input matrix contains only finite numbers.
|
| 47 |
+
Disabling may give a performance gain, but may result in problems
|
| 48 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 49 |
+
|
| 50 |
+
Returns
|
| 51 |
+
-------
|
| 52 |
+
n : float or ndarray
|
| 53 |
+
Norm of the matrix or vector(s).
|
| 54 |
+
|
| 55 |
+
Notes
|
| 56 |
+
-----
|
| 57 |
+
For values of ``ord <= 0``, the result is, strictly speaking, not a
|
| 58 |
+
mathematical 'norm', but it may still be useful for various numerical
|
| 59 |
+
purposes.
|
| 60 |
+
|
| 61 |
+
The following norms can be calculated:
|
| 62 |
+
|
| 63 |
+
===== ============================ ==========================
|
| 64 |
+
ord norm for matrices norm for vectors
|
| 65 |
+
===== ============================ ==========================
|
| 66 |
+
None Frobenius norm 2-norm
|
| 67 |
+
'fro' Frobenius norm --
|
| 68 |
+
'nuc' nuclear norm --
|
| 69 |
+
inf max(sum(abs(a), axis=1)) max(abs(a))
|
| 70 |
+
-inf min(sum(abs(a), axis=1)) min(abs(a))
|
| 71 |
+
0 -- sum(a != 0)
|
| 72 |
+
1 max(sum(abs(a), axis=0)) as below
|
| 73 |
+
-1 min(sum(abs(a), axis=0)) as below
|
| 74 |
+
2 2-norm (largest sing. value) as below
|
| 75 |
+
-2 smallest singular value as below
|
| 76 |
+
other -- sum(abs(a)**ord)**(1./ord)
|
| 77 |
+
===== ============================ ==========================
|
| 78 |
+
|
| 79 |
+
The Frobenius norm is given by [1]_:
|
| 80 |
+
|
| 81 |
+
:math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}`
|
| 82 |
+
|
| 83 |
+
The nuclear norm is the sum of the singular values.
|
| 84 |
+
|
| 85 |
+
Both the Frobenius and nuclear norm orders are only defined for
|
| 86 |
+
matrices.
|
| 87 |
+
|
| 88 |
+
References
|
| 89 |
+
----------
|
| 90 |
+
.. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*,
|
| 91 |
+
Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15
|
| 92 |
+
|
| 93 |
+
Examples
|
| 94 |
+
--------
|
| 95 |
+
>>> import numpy as np
|
| 96 |
+
>>> from scipy.linalg import norm
|
| 97 |
+
>>> a = np.arange(9) - 4.0
|
| 98 |
+
>>> a
|
| 99 |
+
array([-4., -3., -2., -1., 0., 1., 2., 3., 4.])
|
| 100 |
+
>>> b = a.reshape((3, 3))
|
| 101 |
+
>>> b
|
| 102 |
+
array([[-4., -3., -2.],
|
| 103 |
+
[-1., 0., 1.],
|
| 104 |
+
[ 2., 3., 4.]])
|
| 105 |
+
|
| 106 |
+
>>> norm(a)
|
| 107 |
+
7.745966692414834
|
| 108 |
+
>>> norm(b)
|
| 109 |
+
7.745966692414834
|
| 110 |
+
>>> norm(b, 'fro')
|
| 111 |
+
7.745966692414834
|
| 112 |
+
>>> norm(a, np.inf)
|
| 113 |
+
4
|
| 114 |
+
>>> norm(b, np.inf)
|
| 115 |
+
9
|
| 116 |
+
>>> norm(a, -np.inf)
|
| 117 |
+
0
|
| 118 |
+
>>> norm(b, -np.inf)
|
| 119 |
+
2
|
| 120 |
+
|
| 121 |
+
>>> norm(a, 1)
|
| 122 |
+
20
|
| 123 |
+
>>> norm(b, 1)
|
| 124 |
+
7
|
| 125 |
+
>>> norm(a, -1)
|
| 126 |
+
-4.6566128774142013e-010
|
| 127 |
+
>>> norm(b, -1)
|
| 128 |
+
6
|
| 129 |
+
>>> norm(a, 2)
|
| 130 |
+
7.745966692414834
|
| 131 |
+
>>> norm(b, 2)
|
| 132 |
+
7.3484692283495345
|
| 133 |
+
|
| 134 |
+
>>> norm(a, -2)
|
| 135 |
+
0
|
| 136 |
+
>>> norm(b, -2)
|
| 137 |
+
1.8570331885190563e-016
|
| 138 |
+
>>> norm(a, 3)
|
| 139 |
+
5.8480354764257312
|
| 140 |
+
>>> norm(a, -3)
|
| 141 |
+
0
|
| 142 |
+
|
| 143 |
+
"""
|
| 144 |
+
# Differs from numpy only in non-finite handling and the use of blas.
|
| 145 |
+
if check_finite:
|
| 146 |
+
a = np.asarray_chkfinite(a)
|
| 147 |
+
else:
|
| 148 |
+
a = np.asarray(a)
|
| 149 |
+
|
| 150 |
+
if a.size and a.dtype.char in 'fdFD' and axis is None and not keepdims:
|
| 151 |
+
|
| 152 |
+
if ord in (None, 2) and (a.ndim == 1):
|
| 153 |
+
# use blas for fast and stable euclidean norm
|
| 154 |
+
nrm2 = get_blas_funcs('nrm2', dtype=a.dtype, ilp64='preferred')
|
| 155 |
+
return nrm2(a)
|
| 156 |
+
|
| 157 |
+
if a.ndim == 2:
|
| 158 |
+
# Use lapack for a couple fast matrix norms.
|
| 159 |
+
# For some reason the *lange frobenius norm is slow.
|
| 160 |
+
lange_args = None
|
| 161 |
+
# Make sure this works if the user uses the axis keywords
|
| 162 |
+
# to apply the norm to the transpose.
|
| 163 |
+
if ord == 1:
|
| 164 |
+
if np.isfortran(a):
|
| 165 |
+
lange_args = '1', a
|
| 166 |
+
elif np.isfortran(a.T):
|
| 167 |
+
lange_args = 'i', a.T
|
| 168 |
+
elif ord == np.inf:
|
| 169 |
+
if np.isfortran(a):
|
| 170 |
+
lange_args = 'i', a
|
| 171 |
+
elif np.isfortran(a.T):
|
| 172 |
+
lange_args = '1', a.T
|
| 173 |
+
if lange_args:
|
| 174 |
+
lange = get_lapack_funcs('lange', dtype=a.dtype, ilp64='preferred')
|
| 175 |
+
return lange(*lange_args)
|
| 176 |
+
|
| 177 |
+
# fall back to numpy in every other case
|
| 178 |
+
return np.linalg.norm(a, ord=ord, axis=axis, keepdims=keepdims)
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def _datacopied(arr, original):
|
| 182 |
+
"""
|
| 183 |
+
Strict check for `arr` not sharing any data with `original`,
|
| 184 |
+
under the assumption that arr = asarray(original)
|
| 185 |
+
|
| 186 |
+
"""
|
| 187 |
+
if arr is original:
|
| 188 |
+
return False
|
| 189 |
+
if not isinstance(original, np.ndarray) and hasattr(original, '__array__'):
|
| 190 |
+
return False
|
| 191 |
+
return arr.base is None
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_procrustes.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Solve the orthogonal Procrustes problem.
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
import numpy as np
|
| 6 |
+
from ._decomp_svd import svd
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
__all__ = ['orthogonal_procrustes']
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def orthogonal_procrustes(A, B, check_finite=True):
|
| 13 |
+
"""
|
| 14 |
+
Compute the matrix solution of the orthogonal Procrustes problem.
|
| 15 |
+
|
| 16 |
+
Given matrices A and B of equal shape, find an orthogonal matrix R
|
| 17 |
+
that most closely maps A to B using the algorithm given in [1]_.
|
| 18 |
+
|
| 19 |
+
Parameters
|
| 20 |
+
----------
|
| 21 |
+
A : (M, N) array_like
|
| 22 |
+
Matrix to be mapped.
|
| 23 |
+
B : (M, N) array_like
|
| 24 |
+
Target matrix.
|
| 25 |
+
check_finite : bool, optional
|
| 26 |
+
Whether to check that the input matrices contain only finite numbers.
|
| 27 |
+
Disabling may give a performance gain, but may result in problems
|
| 28 |
+
(crashes, non-termination) if the inputs do contain infinities or NaNs.
|
| 29 |
+
|
| 30 |
+
Returns
|
| 31 |
+
-------
|
| 32 |
+
R : (N, N) ndarray
|
| 33 |
+
The matrix solution of the orthogonal Procrustes problem.
|
| 34 |
+
Minimizes the Frobenius norm of ``(A @ R) - B``, subject to
|
| 35 |
+
``R.T @ R = I``.
|
| 36 |
+
scale : float
|
| 37 |
+
Sum of the singular values of ``A.T @ B``.
|
| 38 |
+
|
| 39 |
+
Raises
|
| 40 |
+
------
|
| 41 |
+
ValueError
|
| 42 |
+
If the input array shapes don't match or if check_finite is True and
|
| 43 |
+
the arrays contain Inf or NaN.
|
| 44 |
+
|
| 45 |
+
Notes
|
| 46 |
+
-----
|
| 47 |
+
Note that unlike higher level Procrustes analyses of spatial data, this
|
| 48 |
+
function only uses orthogonal transformations like rotations and
|
| 49 |
+
reflections, and it does not use scaling or translation.
|
| 50 |
+
|
| 51 |
+
.. versionadded:: 0.15.0
|
| 52 |
+
|
| 53 |
+
References
|
| 54 |
+
----------
|
| 55 |
+
.. [1] Peter H. Schonemann, "A generalized solution of the orthogonal
|
| 56 |
+
Procrustes problem", Psychometrica -- Vol. 31, No. 1, March, 1966.
|
| 57 |
+
:doi:`10.1007/BF02289451`
|
| 58 |
+
|
| 59 |
+
Examples
|
| 60 |
+
--------
|
| 61 |
+
>>> import numpy as np
|
| 62 |
+
>>> from scipy.linalg import orthogonal_procrustes
|
| 63 |
+
>>> A = np.array([[ 2, 0, 1], [-2, 0, 0]])
|
| 64 |
+
|
| 65 |
+
Flip the order of columns and check for the anti-diagonal mapping
|
| 66 |
+
|
| 67 |
+
>>> R, sca = orthogonal_procrustes(A, np.fliplr(A))
|
| 68 |
+
>>> R
|
| 69 |
+
array([[-5.34384992e-17, 0.00000000e+00, 1.00000000e+00],
|
| 70 |
+
[ 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
|
| 71 |
+
[ 1.00000000e+00, 0.00000000e+00, -7.85941422e-17]])
|
| 72 |
+
>>> sca
|
| 73 |
+
9.0
|
| 74 |
+
|
| 75 |
+
"""
|
| 76 |
+
if check_finite:
|
| 77 |
+
A = np.asarray_chkfinite(A)
|
| 78 |
+
B = np.asarray_chkfinite(B)
|
| 79 |
+
else:
|
| 80 |
+
A = np.asanyarray(A)
|
| 81 |
+
B = np.asanyarray(B)
|
| 82 |
+
if A.ndim != 2:
|
| 83 |
+
raise ValueError('expected ndim to be 2, but observed %s' % A.ndim)
|
| 84 |
+
if A.shape != B.shape:
|
| 85 |
+
raise ValueError(f'the shapes of A and B differ ({A.shape} vs {B.shape})')
|
| 86 |
+
# Be clever with transposes, with the intention to save memory.
|
| 87 |
+
u, w, vt = svd(B.T.dot(A).T)
|
| 88 |
+
R = u.dot(vt)
|
| 89 |
+
scale = w.sum()
|
| 90 |
+
return R, scale
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_sketches.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" Sketching-based Matrix Computations """
|
| 2 |
+
|
| 3 |
+
# Author: Jordi Montes <jomsdev@gmail.com>
|
| 4 |
+
# August 28, 2017
|
| 5 |
+
|
| 6 |
+
import numpy as np
|
| 7 |
+
|
| 8 |
+
from scipy._lib._util import check_random_state, rng_integers
|
| 9 |
+
from scipy.sparse import csc_matrix
|
| 10 |
+
|
| 11 |
+
__all__ = ['clarkson_woodruff_transform']
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def cwt_matrix(n_rows, n_columns, seed=None):
|
| 15 |
+
r"""
|
| 16 |
+
Generate a matrix S which represents a Clarkson-Woodruff transform.
|
| 17 |
+
|
| 18 |
+
Given the desired size of matrix, the method returns a matrix S of size
|
| 19 |
+
(n_rows, n_columns) where each column has all the entries set to 0
|
| 20 |
+
except for one position which has been randomly set to +1 or -1 with
|
| 21 |
+
equal probability.
|
| 22 |
+
|
| 23 |
+
Parameters
|
| 24 |
+
----------
|
| 25 |
+
n_rows : int
|
| 26 |
+
Number of rows of S
|
| 27 |
+
n_columns : int
|
| 28 |
+
Number of columns of S
|
| 29 |
+
seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
|
| 30 |
+
If `seed` is None (or `np.random`), the `numpy.random.RandomState`
|
| 31 |
+
singleton is used.
|
| 32 |
+
If `seed` is an int, a new ``RandomState`` instance is used,
|
| 33 |
+
seeded with `seed`.
|
| 34 |
+
If `seed` is already a ``Generator`` or ``RandomState`` instance then
|
| 35 |
+
that instance is used.
|
| 36 |
+
|
| 37 |
+
Returns
|
| 38 |
+
-------
|
| 39 |
+
S : (n_rows, n_columns) csc_matrix
|
| 40 |
+
The returned matrix has ``n_columns`` nonzero entries.
|
| 41 |
+
|
| 42 |
+
Notes
|
| 43 |
+
-----
|
| 44 |
+
Given a matrix A, with probability at least 9/10,
|
| 45 |
+
.. math:: \|SA\| = (1 \pm \epsilon)\|A\|
|
| 46 |
+
Where the error epsilon is related to the size of S.
|
| 47 |
+
"""
|
| 48 |
+
rng = check_random_state(seed)
|
| 49 |
+
rows = rng_integers(rng, 0, n_rows, n_columns)
|
| 50 |
+
cols = np.arange(n_columns+1)
|
| 51 |
+
signs = rng.choice([1, -1], n_columns)
|
| 52 |
+
S = csc_matrix((signs, rows, cols),shape=(n_rows, n_columns))
|
| 53 |
+
return S
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def clarkson_woodruff_transform(input_matrix, sketch_size, seed=None):
|
| 57 |
+
r"""
|
| 58 |
+
Applies a Clarkson-Woodruff Transform/sketch to the input matrix.
|
| 59 |
+
|
| 60 |
+
Given an input_matrix ``A`` of size ``(n, d)``, compute a matrix ``A'`` of
|
| 61 |
+
size (sketch_size, d) so that
|
| 62 |
+
|
| 63 |
+
.. math:: \|Ax\| \approx \|A'x\|
|
| 64 |
+
|
| 65 |
+
with high probability via the Clarkson-Woodruff Transform, otherwise
|
| 66 |
+
known as the CountSketch matrix.
|
| 67 |
+
|
| 68 |
+
Parameters
|
| 69 |
+
----------
|
| 70 |
+
input_matrix : array_like
|
| 71 |
+
Input matrix, of shape ``(n, d)``.
|
| 72 |
+
sketch_size : int
|
| 73 |
+
Number of rows for the sketch.
|
| 74 |
+
seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
|
| 75 |
+
If `seed` is None (or `np.random`), the `numpy.random.RandomState`
|
| 76 |
+
singleton is used.
|
| 77 |
+
If `seed` is an int, a new ``RandomState`` instance is used,
|
| 78 |
+
seeded with `seed`.
|
| 79 |
+
If `seed` is already a ``Generator`` or ``RandomState`` instance then
|
| 80 |
+
that instance is used.
|
| 81 |
+
|
| 82 |
+
Returns
|
| 83 |
+
-------
|
| 84 |
+
A' : array_like
|
| 85 |
+
Sketch of the input matrix ``A``, of size ``(sketch_size, d)``.
|
| 86 |
+
|
| 87 |
+
Notes
|
| 88 |
+
-----
|
| 89 |
+
To make the statement
|
| 90 |
+
|
| 91 |
+
.. math:: \|Ax\| \approx \|A'x\|
|
| 92 |
+
|
| 93 |
+
precise, observe the following result which is adapted from the
|
| 94 |
+
proof of Theorem 14 of [2]_ via Markov's Inequality. If we have
|
| 95 |
+
a sketch size ``sketch_size=k`` which is at least
|
| 96 |
+
|
| 97 |
+
.. math:: k \geq \frac{2}{\epsilon^2\delta}
|
| 98 |
+
|
| 99 |
+
Then for any fixed vector ``x``,
|
| 100 |
+
|
| 101 |
+
.. math:: \|Ax\| = (1\pm\epsilon)\|A'x\|
|
| 102 |
+
|
| 103 |
+
with probability at least one minus delta.
|
| 104 |
+
|
| 105 |
+
This implementation takes advantage of sparsity: computing
|
| 106 |
+
a sketch takes time proportional to ``A.nnz``. Data ``A`` which
|
| 107 |
+
is in ``scipy.sparse.csc_matrix`` format gives the quickest
|
| 108 |
+
computation time for sparse input.
|
| 109 |
+
|
| 110 |
+
>>> import numpy as np
|
| 111 |
+
>>> from scipy import linalg
|
| 112 |
+
>>> from scipy import sparse
|
| 113 |
+
>>> rng = np.random.default_rng()
|
| 114 |
+
>>> n_rows, n_columns, density, sketch_n_rows = 15000, 100, 0.01, 200
|
| 115 |
+
>>> A = sparse.rand(n_rows, n_columns, density=density, format='csc')
|
| 116 |
+
>>> B = sparse.rand(n_rows, n_columns, density=density, format='csr')
|
| 117 |
+
>>> C = sparse.rand(n_rows, n_columns, density=density, format='coo')
|
| 118 |
+
>>> D = rng.standard_normal((n_rows, n_columns))
|
| 119 |
+
>>> SA = linalg.clarkson_woodruff_transform(A, sketch_n_rows) # fastest
|
| 120 |
+
>>> SB = linalg.clarkson_woodruff_transform(B, sketch_n_rows) # fast
|
| 121 |
+
>>> SC = linalg.clarkson_woodruff_transform(C, sketch_n_rows) # slower
|
| 122 |
+
>>> SD = linalg.clarkson_woodruff_transform(D, sketch_n_rows) # slowest
|
| 123 |
+
|
| 124 |
+
That said, this method does perform well on dense inputs, just slower
|
| 125 |
+
on a relative scale.
|
| 126 |
+
|
| 127 |
+
References
|
| 128 |
+
----------
|
| 129 |
+
.. [1] Kenneth L. Clarkson and David P. Woodruff. Low rank approximation
|
| 130 |
+
and regression in input sparsity time. In STOC, 2013.
|
| 131 |
+
.. [2] David P. Woodruff. Sketching as a tool for numerical linear algebra.
|
| 132 |
+
In Foundations and Trends in Theoretical Computer Science, 2014.
|
| 133 |
+
|
| 134 |
+
Examples
|
| 135 |
+
--------
|
| 136 |
+
Create a big dense matrix ``A`` for the example:
|
| 137 |
+
|
| 138 |
+
>>> import numpy as np
|
| 139 |
+
>>> from scipy import linalg
|
| 140 |
+
>>> n_rows, n_columns = 15000, 100
|
| 141 |
+
>>> rng = np.random.default_rng()
|
| 142 |
+
>>> A = rng.standard_normal((n_rows, n_columns))
|
| 143 |
+
|
| 144 |
+
Apply the transform to create a new matrix with 200 rows:
|
| 145 |
+
|
| 146 |
+
>>> sketch_n_rows = 200
|
| 147 |
+
>>> sketch = linalg.clarkson_woodruff_transform(A, sketch_n_rows, seed=rng)
|
| 148 |
+
>>> sketch.shape
|
| 149 |
+
(200, 100)
|
| 150 |
+
|
| 151 |
+
Now with high probability, the true norm is close to the sketched norm
|
| 152 |
+
in absolute value.
|
| 153 |
+
|
| 154 |
+
>>> linalg.norm(A)
|
| 155 |
+
1224.2812927123198
|
| 156 |
+
>>> linalg.norm(sketch)
|
| 157 |
+
1226.518328407333
|
| 158 |
+
|
| 159 |
+
Similarly, applying our sketch preserves the solution to a linear
|
| 160 |
+
regression of :math:`\min \|Ax - b\|`.
|
| 161 |
+
|
| 162 |
+
>>> b = rng.standard_normal(n_rows)
|
| 163 |
+
>>> x = linalg.lstsq(A, b)[0]
|
| 164 |
+
>>> Ab = np.hstack((A, b.reshape(-1, 1)))
|
| 165 |
+
>>> SAb = linalg.clarkson_woodruff_transform(Ab, sketch_n_rows, seed=rng)
|
| 166 |
+
>>> SA, Sb = SAb[:, :-1], SAb[:, -1]
|
| 167 |
+
>>> x_sketched = linalg.lstsq(SA, Sb)[0]
|
| 168 |
+
|
| 169 |
+
As with the matrix norm example, ``linalg.norm(A @ x - b)`` is close
|
| 170 |
+
to ``linalg.norm(A @ x_sketched - b)`` with high probability.
|
| 171 |
+
|
| 172 |
+
>>> linalg.norm(A @ x - b)
|
| 173 |
+
122.83242365433877
|
| 174 |
+
>>> linalg.norm(A @ x_sketched - b)
|
| 175 |
+
166.58473879945151
|
| 176 |
+
|
| 177 |
+
"""
|
| 178 |
+
S = cwt_matrix(sketch_size, input_matrix.shape[0], seed)
|
| 179 |
+
return S.dot(input_matrix)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_solvers.py
ADDED
|
@@ -0,0 +1,846 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Matrix equation solver routines"""
|
| 2 |
+
# Author: Jeffrey Armstrong <jeff@approximatrix.com>
|
| 3 |
+
# February 24, 2012
|
| 4 |
+
|
| 5 |
+
# Modified: Chad Fulton <ChadFulton@gmail.com>
|
| 6 |
+
# June 19, 2014
|
| 7 |
+
|
| 8 |
+
# Modified: Ilhan Polat <ilhanpolat@gmail.com>
|
| 9 |
+
# September 13, 2016
|
| 10 |
+
|
| 11 |
+
import warnings
|
| 12 |
+
import numpy as np
|
| 13 |
+
from numpy.linalg import inv, LinAlgError, norm, cond, svd
|
| 14 |
+
|
| 15 |
+
from ._basic import solve, solve_triangular, matrix_balance
|
| 16 |
+
from .lapack import get_lapack_funcs
|
| 17 |
+
from ._decomp_schur import schur
|
| 18 |
+
from ._decomp_lu import lu
|
| 19 |
+
from ._decomp_qr import qr
|
| 20 |
+
from ._decomp_qz import ordqz
|
| 21 |
+
from ._decomp import _asarray_validated
|
| 22 |
+
from ._special_matrices import kron, block_diag
|
| 23 |
+
|
| 24 |
+
__all__ = ['solve_sylvester',
|
| 25 |
+
'solve_continuous_lyapunov', 'solve_discrete_lyapunov',
|
| 26 |
+
'solve_lyapunov',
|
| 27 |
+
'solve_continuous_are', 'solve_discrete_are']
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def solve_sylvester(a, b, q):
|
| 31 |
+
"""
|
| 32 |
+
Computes a solution (X) to the Sylvester equation :math:`AX + XB = Q`.
|
| 33 |
+
|
| 34 |
+
Parameters
|
| 35 |
+
----------
|
| 36 |
+
a : (M, M) array_like
|
| 37 |
+
Leading matrix of the Sylvester equation
|
| 38 |
+
b : (N, N) array_like
|
| 39 |
+
Trailing matrix of the Sylvester equation
|
| 40 |
+
q : (M, N) array_like
|
| 41 |
+
Right-hand side
|
| 42 |
+
|
| 43 |
+
Returns
|
| 44 |
+
-------
|
| 45 |
+
x : (M, N) ndarray
|
| 46 |
+
The solution to the Sylvester equation.
|
| 47 |
+
|
| 48 |
+
Raises
|
| 49 |
+
------
|
| 50 |
+
LinAlgError
|
| 51 |
+
If solution was not found
|
| 52 |
+
|
| 53 |
+
Notes
|
| 54 |
+
-----
|
| 55 |
+
Computes a solution to the Sylvester matrix equation via the Bartels-
|
| 56 |
+
Stewart algorithm. The A and B matrices first undergo Schur
|
| 57 |
+
decompositions. The resulting matrices are used to construct an
|
| 58 |
+
alternative Sylvester equation (``RY + YS^T = F``) where the R and S
|
| 59 |
+
matrices are in quasi-triangular form (or, when R, S or F are complex,
|
| 60 |
+
triangular form). The simplified equation is then solved using
|
| 61 |
+
``*TRSYL`` from LAPACK directly.
|
| 62 |
+
|
| 63 |
+
.. versionadded:: 0.11.0
|
| 64 |
+
|
| 65 |
+
Examples
|
| 66 |
+
--------
|
| 67 |
+
Given `a`, `b`, and `q` solve for `x`:
|
| 68 |
+
|
| 69 |
+
>>> import numpy as np
|
| 70 |
+
>>> from scipy import linalg
|
| 71 |
+
>>> a = np.array([[-3, -2, 0], [-1, -1, 3], [3, -5, -1]])
|
| 72 |
+
>>> b = np.array([[1]])
|
| 73 |
+
>>> q = np.array([[1],[2],[3]])
|
| 74 |
+
>>> x = linalg.solve_sylvester(a, b, q)
|
| 75 |
+
>>> x
|
| 76 |
+
array([[ 0.0625],
|
| 77 |
+
[-0.5625],
|
| 78 |
+
[ 0.6875]])
|
| 79 |
+
>>> np.allclose(a.dot(x) + x.dot(b), q)
|
| 80 |
+
True
|
| 81 |
+
|
| 82 |
+
"""
|
| 83 |
+
|
| 84 |
+
# Compute the Schur decomposition form of a
|
| 85 |
+
r, u = schur(a, output='real')
|
| 86 |
+
|
| 87 |
+
# Compute the Schur decomposition of b
|
| 88 |
+
s, v = schur(b.conj().transpose(), output='real')
|
| 89 |
+
|
| 90 |
+
# Construct f = u'*q*v
|
| 91 |
+
f = np.dot(np.dot(u.conj().transpose(), q), v)
|
| 92 |
+
|
| 93 |
+
# Call the Sylvester equation solver
|
| 94 |
+
trsyl, = get_lapack_funcs(('trsyl',), (r, s, f))
|
| 95 |
+
if trsyl is None:
|
| 96 |
+
raise RuntimeError('LAPACK implementation does not contain a proper '
|
| 97 |
+
'Sylvester equation solver (TRSYL)')
|
| 98 |
+
y, scale, info = trsyl(r, s, f, tranb='C')
|
| 99 |
+
|
| 100 |
+
y = scale*y
|
| 101 |
+
|
| 102 |
+
if info < 0:
|
| 103 |
+
raise LinAlgError("Illegal value encountered in "
|
| 104 |
+
"the %d term" % (-info,))
|
| 105 |
+
|
| 106 |
+
return np.dot(np.dot(u, y), v.conj().transpose())
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def solve_continuous_lyapunov(a, q):
|
| 110 |
+
"""
|
| 111 |
+
Solves the continuous Lyapunov equation :math:`AX + XA^H = Q`.
|
| 112 |
+
|
| 113 |
+
Uses the Bartels-Stewart algorithm to find :math:`X`.
|
| 114 |
+
|
| 115 |
+
Parameters
|
| 116 |
+
----------
|
| 117 |
+
a : array_like
|
| 118 |
+
A square matrix
|
| 119 |
+
|
| 120 |
+
q : array_like
|
| 121 |
+
Right-hand side square matrix
|
| 122 |
+
|
| 123 |
+
Returns
|
| 124 |
+
-------
|
| 125 |
+
x : ndarray
|
| 126 |
+
Solution to the continuous Lyapunov equation
|
| 127 |
+
|
| 128 |
+
See Also
|
| 129 |
+
--------
|
| 130 |
+
solve_discrete_lyapunov : computes the solution to the discrete-time
|
| 131 |
+
Lyapunov equation
|
| 132 |
+
solve_sylvester : computes the solution to the Sylvester equation
|
| 133 |
+
|
| 134 |
+
Notes
|
| 135 |
+
-----
|
| 136 |
+
The continuous Lyapunov equation is a special form of the Sylvester
|
| 137 |
+
equation, hence this solver relies on LAPACK routine ?TRSYL.
|
| 138 |
+
|
| 139 |
+
.. versionadded:: 0.11.0
|
| 140 |
+
|
| 141 |
+
Examples
|
| 142 |
+
--------
|
| 143 |
+
Given `a` and `q` solve for `x`:
|
| 144 |
+
|
| 145 |
+
>>> import numpy as np
|
| 146 |
+
>>> from scipy import linalg
|
| 147 |
+
>>> a = np.array([[-3, -2, 0], [-1, -1, 0], [0, -5, -1]])
|
| 148 |
+
>>> b = np.array([2, 4, -1])
|
| 149 |
+
>>> q = np.eye(3)
|
| 150 |
+
>>> x = linalg.solve_continuous_lyapunov(a, q)
|
| 151 |
+
>>> x
|
| 152 |
+
array([[ -0.75 , 0.875 , -3.75 ],
|
| 153 |
+
[ 0.875 , -1.375 , 5.3125],
|
| 154 |
+
[ -3.75 , 5.3125, -27.0625]])
|
| 155 |
+
>>> np.allclose(a.dot(x) + x.dot(a.T), q)
|
| 156 |
+
True
|
| 157 |
+
"""
|
| 158 |
+
|
| 159 |
+
a = np.atleast_2d(_asarray_validated(a, check_finite=True))
|
| 160 |
+
q = np.atleast_2d(_asarray_validated(q, check_finite=True))
|
| 161 |
+
|
| 162 |
+
r_or_c = float
|
| 163 |
+
|
| 164 |
+
for ind, _ in enumerate((a, q)):
|
| 165 |
+
if np.iscomplexobj(_):
|
| 166 |
+
r_or_c = complex
|
| 167 |
+
|
| 168 |
+
if not np.equal(*_.shape):
|
| 169 |
+
raise ValueError("Matrix {} should be square.".format("aq"[ind]))
|
| 170 |
+
|
| 171 |
+
# Shape consistency check
|
| 172 |
+
if a.shape != q.shape:
|
| 173 |
+
raise ValueError("Matrix a and q should have the same shape.")
|
| 174 |
+
|
| 175 |
+
# Compute the Schur decomposition form of a
|
| 176 |
+
r, u = schur(a, output='real')
|
| 177 |
+
|
| 178 |
+
# Construct f = u'*q*u
|
| 179 |
+
f = u.conj().T.dot(q.dot(u))
|
| 180 |
+
|
| 181 |
+
# Call the Sylvester equation solver
|
| 182 |
+
trsyl = get_lapack_funcs('trsyl', (r, f))
|
| 183 |
+
|
| 184 |
+
dtype_string = 'T' if r_or_c == float else 'C'
|
| 185 |
+
y, scale, info = trsyl(r, r, f, tranb=dtype_string)
|
| 186 |
+
|
| 187 |
+
if info < 0:
|
| 188 |
+
raise ValueError('?TRSYL exited with the internal error '
|
| 189 |
+
f'"illegal value in argument number {-info}.". See '
|
| 190 |
+
'LAPACK documentation for the ?TRSYL error codes.')
|
| 191 |
+
elif info == 1:
|
| 192 |
+
warnings.warn('Input "a" has an eigenvalue pair whose sum is '
|
| 193 |
+
'very close to or exactly zero. The solution is '
|
| 194 |
+
'obtained via perturbing the coefficients.',
|
| 195 |
+
RuntimeWarning, stacklevel=2)
|
| 196 |
+
y *= scale
|
| 197 |
+
|
| 198 |
+
return u.dot(y).dot(u.conj().T)
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
# For backwards compatibility, keep the old name
|
| 202 |
+
solve_lyapunov = solve_continuous_lyapunov
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def _solve_discrete_lyapunov_direct(a, q):
|
| 206 |
+
"""
|
| 207 |
+
Solves the discrete Lyapunov equation directly.
|
| 208 |
+
|
| 209 |
+
This function is called by the `solve_discrete_lyapunov` function with
|
| 210 |
+
`method=direct`. It is not supposed to be called directly.
|
| 211 |
+
"""
|
| 212 |
+
|
| 213 |
+
lhs = kron(a, a.conj())
|
| 214 |
+
lhs = np.eye(lhs.shape[0]) - lhs
|
| 215 |
+
x = solve(lhs, q.flatten())
|
| 216 |
+
|
| 217 |
+
return np.reshape(x, q.shape)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def _solve_discrete_lyapunov_bilinear(a, q):
|
| 221 |
+
"""
|
| 222 |
+
Solves the discrete Lyapunov equation using a bilinear transformation.
|
| 223 |
+
|
| 224 |
+
This function is called by the `solve_discrete_lyapunov` function with
|
| 225 |
+
`method=bilinear`. It is not supposed to be called directly.
|
| 226 |
+
"""
|
| 227 |
+
eye = np.eye(a.shape[0])
|
| 228 |
+
aH = a.conj().transpose()
|
| 229 |
+
aHI_inv = inv(aH + eye)
|
| 230 |
+
b = np.dot(aH - eye, aHI_inv)
|
| 231 |
+
c = 2*np.dot(np.dot(inv(a + eye), q), aHI_inv)
|
| 232 |
+
return solve_lyapunov(b.conj().transpose(), -c)
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def solve_discrete_lyapunov(a, q, method=None):
|
| 236 |
+
"""
|
| 237 |
+
Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0`.
|
| 238 |
+
|
| 239 |
+
Parameters
|
| 240 |
+
----------
|
| 241 |
+
a, q : (M, M) array_like
|
| 242 |
+
Square matrices corresponding to A and Q in the equation
|
| 243 |
+
above respectively. Must have the same shape.
|
| 244 |
+
|
| 245 |
+
method : {'direct', 'bilinear'}, optional
|
| 246 |
+
Type of solver.
|
| 247 |
+
|
| 248 |
+
If not given, chosen to be ``direct`` if ``M`` is less than 10 and
|
| 249 |
+
``bilinear`` otherwise.
|
| 250 |
+
|
| 251 |
+
Returns
|
| 252 |
+
-------
|
| 253 |
+
x : ndarray
|
| 254 |
+
Solution to the discrete Lyapunov equation
|
| 255 |
+
|
| 256 |
+
See Also
|
| 257 |
+
--------
|
| 258 |
+
solve_continuous_lyapunov : computes the solution to the continuous-time
|
| 259 |
+
Lyapunov equation
|
| 260 |
+
|
| 261 |
+
Notes
|
| 262 |
+
-----
|
| 263 |
+
This section describes the available solvers that can be selected by the
|
| 264 |
+
'method' parameter. The default method is *direct* if ``M`` is less than 10
|
| 265 |
+
and ``bilinear`` otherwise.
|
| 266 |
+
|
| 267 |
+
Method *direct* uses a direct analytical solution to the discrete Lyapunov
|
| 268 |
+
equation. The algorithm is given in, for example, [1]_. However, it requires
|
| 269 |
+
the linear solution of a system with dimension :math:`M^2` so that
|
| 270 |
+
performance degrades rapidly for even moderately sized matrices.
|
| 271 |
+
|
| 272 |
+
Method *bilinear* uses a bilinear transformation to convert the discrete
|
| 273 |
+
Lyapunov equation to a continuous Lyapunov equation :math:`(BX+XB'=-C)`
|
| 274 |
+
where :math:`B=(A-I)(A+I)^{-1}` and
|
| 275 |
+
:math:`C=2(A' + I)^{-1} Q (A + I)^{-1}`. The continuous equation can be
|
| 276 |
+
efficiently solved since it is a special case of a Sylvester equation.
|
| 277 |
+
The transformation algorithm is from Popov (1964) as described in [2]_.
|
| 278 |
+
|
| 279 |
+
.. versionadded:: 0.11.0
|
| 280 |
+
|
| 281 |
+
References
|
| 282 |
+
----------
|
| 283 |
+
.. [1] Hamilton, James D. Time Series Analysis, Princeton: Princeton
|
| 284 |
+
University Press, 1994. 265. Print.
|
| 285 |
+
http://doc1.lbfl.li/aca/FLMF037168.pdf
|
| 286 |
+
.. [2] Gajic, Z., and M.T.J. Qureshi. 2008.
|
| 287 |
+
Lyapunov Matrix Equation in System Stability and Control.
|
| 288 |
+
Dover Books on Engineering Series. Dover Publications.
|
| 289 |
+
|
| 290 |
+
Examples
|
| 291 |
+
--------
|
| 292 |
+
Given `a` and `q` solve for `x`:
|
| 293 |
+
|
| 294 |
+
>>> import numpy as np
|
| 295 |
+
>>> from scipy import linalg
|
| 296 |
+
>>> a = np.array([[0.2, 0.5],[0.7, -0.9]])
|
| 297 |
+
>>> q = np.eye(2)
|
| 298 |
+
>>> x = linalg.solve_discrete_lyapunov(a, q)
|
| 299 |
+
>>> x
|
| 300 |
+
array([[ 0.70872893, 1.43518822],
|
| 301 |
+
[ 1.43518822, -2.4266315 ]])
|
| 302 |
+
>>> np.allclose(a.dot(x).dot(a.T)-x, -q)
|
| 303 |
+
True
|
| 304 |
+
|
| 305 |
+
"""
|
| 306 |
+
a = np.asarray(a)
|
| 307 |
+
q = np.asarray(q)
|
| 308 |
+
if method is None:
|
| 309 |
+
# Select automatically based on size of matrices
|
| 310 |
+
if a.shape[0] >= 10:
|
| 311 |
+
method = 'bilinear'
|
| 312 |
+
else:
|
| 313 |
+
method = 'direct'
|
| 314 |
+
|
| 315 |
+
meth = method.lower()
|
| 316 |
+
|
| 317 |
+
if meth == 'direct':
|
| 318 |
+
x = _solve_discrete_lyapunov_direct(a, q)
|
| 319 |
+
elif meth == 'bilinear':
|
| 320 |
+
x = _solve_discrete_lyapunov_bilinear(a, q)
|
| 321 |
+
else:
|
| 322 |
+
raise ValueError('Unknown solver %s' % method)
|
| 323 |
+
|
| 324 |
+
return x
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
def solve_continuous_are(a, b, q, r, e=None, s=None, balanced=True):
|
| 328 |
+
r"""
|
| 329 |
+
Solves the continuous-time algebraic Riccati equation (CARE).
|
| 330 |
+
|
| 331 |
+
The CARE is defined as
|
| 332 |
+
|
| 333 |
+
.. math::
|
| 334 |
+
|
| 335 |
+
X A + A^H X - X B R^{-1} B^H X + Q = 0
|
| 336 |
+
|
| 337 |
+
The limitations for a solution to exist are :
|
| 338 |
+
|
| 339 |
+
* All eigenvalues of :math:`A` on the right half plane, should be
|
| 340 |
+
controllable.
|
| 341 |
+
|
| 342 |
+
* The associated hamiltonian pencil (See Notes), should have
|
| 343 |
+
eigenvalues sufficiently away from the imaginary axis.
|
| 344 |
+
|
| 345 |
+
Moreover, if ``e`` or ``s`` is not precisely ``None``, then the
|
| 346 |
+
generalized version of CARE
|
| 347 |
+
|
| 348 |
+
.. math::
|
| 349 |
+
|
| 350 |
+
E^HXA + A^HXE - (E^HXB + S) R^{-1} (B^HXE + S^H) + Q = 0
|
| 351 |
+
|
| 352 |
+
is solved. When omitted, ``e`` is assumed to be the identity and ``s``
|
| 353 |
+
is assumed to be the zero matrix with sizes compatible with ``a`` and
|
| 354 |
+
``b``, respectively.
|
| 355 |
+
|
| 356 |
+
Parameters
|
| 357 |
+
----------
|
| 358 |
+
a : (M, M) array_like
|
| 359 |
+
Square matrix
|
| 360 |
+
b : (M, N) array_like
|
| 361 |
+
Input
|
| 362 |
+
q : (M, M) array_like
|
| 363 |
+
Input
|
| 364 |
+
r : (N, N) array_like
|
| 365 |
+
Nonsingular square matrix
|
| 366 |
+
e : (M, M) array_like, optional
|
| 367 |
+
Nonsingular square matrix
|
| 368 |
+
s : (M, N) array_like, optional
|
| 369 |
+
Input
|
| 370 |
+
balanced : bool, optional
|
| 371 |
+
The boolean that indicates whether a balancing step is performed
|
| 372 |
+
on the data. The default is set to True.
|
| 373 |
+
|
| 374 |
+
Returns
|
| 375 |
+
-------
|
| 376 |
+
x : (M, M) ndarray
|
| 377 |
+
Solution to the continuous-time algebraic Riccati equation.
|
| 378 |
+
|
| 379 |
+
Raises
|
| 380 |
+
------
|
| 381 |
+
LinAlgError
|
| 382 |
+
For cases where the stable subspace of the pencil could not be
|
| 383 |
+
isolated. See Notes section and the references for details.
|
| 384 |
+
|
| 385 |
+
See Also
|
| 386 |
+
--------
|
| 387 |
+
solve_discrete_are : Solves the discrete-time algebraic Riccati equation
|
| 388 |
+
|
| 389 |
+
Notes
|
| 390 |
+
-----
|
| 391 |
+
The equation is solved by forming the extended hamiltonian matrix pencil,
|
| 392 |
+
as described in [1]_, :math:`H - \lambda J` given by the block matrices ::
|
| 393 |
+
|
| 394 |
+
[ A 0 B ] [ E 0 0 ]
|
| 395 |
+
[-Q -A^H -S ] - \lambda * [ 0 E^H 0 ]
|
| 396 |
+
[ S^H B^H R ] [ 0 0 0 ]
|
| 397 |
+
|
| 398 |
+
and using a QZ decomposition method.
|
| 399 |
+
|
| 400 |
+
In this algorithm, the fail conditions are linked to the symmetry
|
| 401 |
+
of the product :math:`U_2 U_1^{-1}` and condition number of
|
| 402 |
+
:math:`U_1`. Here, :math:`U` is the 2m-by-m matrix that holds the
|
| 403 |
+
eigenvectors spanning the stable subspace with 2-m rows and partitioned
|
| 404 |
+
into two m-row matrices. See [1]_ and [2]_ for more details.
|
| 405 |
+
|
| 406 |
+
In order to improve the QZ decomposition accuracy, the pencil goes
|
| 407 |
+
through a balancing step where the sum of absolute values of
|
| 408 |
+
:math:`H` and :math:`J` entries (after removing the diagonal entries of
|
| 409 |
+
the sum) is balanced following the recipe given in [3]_.
|
| 410 |
+
|
| 411 |
+
.. versionadded:: 0.11.0
|
| 412 |
+
|
| 413 |
+
References
|
| 414 |
+
----------
|
| 415 |
+
.. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving
|
| 416 |
+
Riccati Equations.", SIAM Journal on Scientific and Statistical
|
| 417 |
+
Computing, Vol.2(2), :doi:`10.1137/0902010`
|
| 418 |
+
|
| 419 |
+
.. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati
|
| 420 |
+
Equations.", Massachusetts Institute of Technology. Laboratory for
|
| 421 |
+
Information and Decision Systems. LIDS-R ; 859. Available online :
|
| 422 |
+
http://hdl.handle.net/1721.1/1301
|
| 423 |
+
|
| 424 |
+
.. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001,
|
| 425 |
+
SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993`
|
| 426 |
+
|
| 427 |
+
Examples
|
| 428 |
+
--------
|
| 429 |
+
Given `a`, `b`, `q`, and `r` solve for `x`:
|
| 430 |
+
|
| 431 |
+
>>> import numpy as np
|
| 432 |
+
>>> from scipy import linalg
|
| 433 |
+
>>> a = np.array([[4, 3], [-4.5, -3.5]])
|
| 434 |
+
>>> b = np.array([[1], [-1]])
|
| 435 |
+
>>> q = np.array([[9, 6], [6, 4.]])
|
| 436 |
+
>>> r = 1
|
| 437 |
+
>>> x = linalg.solve_continuous_are(a, b, q, r)
|
| 438 |
+
>>> x
|
| 439 |
+
array([[ 21.72792206, 14.48528137],
|
| 440 |
+
[ 14.48528137, 9.65685425]])
|
| 441 |
+
>>> np.allclose(a.T.dot(x) + x.dot(a)-x.dot(b).dot(b.T).dot(x), -q)
|
| 442 |
+
True
|
| 443 |
+
|
| 444 |
+
"""
|
| 445 |
+
|
| 446 |
+
# Validate input arguments
|
| 447 |
+
a, b, q, r, e, s, m, n, r_or_c, gen_are = _are_validate_args(
|
| 448 |
+
a, b, q, r, e, s, 'care')
|
| 449 |
+
|
| 450 |
+
H = np.empty((2*m+n, 2*m+n), dtype=r_or_c)
|
| 451 |
+
H[:m, :m] = a
|
| 452 |
+
H[:m, m:2*m] = 0.
|
| 453 |
+
H[:m, 2*m:] = b
|
| 454 |
+
H[m:2*m, :m] = -q
|
| 455 |
+
H[m:2*m, m:2*m] = -a.conj().T
|
| 456 |
+
H[m:2*m, 2*m:] = 0. if s is None else -s
|
| 457 |
+
H[2*m:, :m] = 0. if s is None else s.conj().T
|
| 458 |
+
H[2*m:, m:2*m] = b.conj().T
|
| 459 |
+
H[2*m:, 2*m:] = r
|
| 460 |
+
|
| 461 |
+
if gen_are and e is not None:
|
| 462 |
+
J = block_diag(e, e.conj().T, np.zeros_like(r, dtype=r_or_c))
|
| 463 |
+
else:
|
| 464 |
+
J = block_diag(np.eye(2*m), np.zeros_like(r, dtype=r_or_c))
|
| 465 |
+
|
| 466 |
+
if balanced:
|
| 467 |
+
# xGEBAL does not remove the diagonals before scaling. Also
|
| 468 |
+
# to avoid destroying the Symplectic structure, we follow Ref.3
|
| 469 |
+
M = np.abs(H) + np.abs(J)
|
| 470 |
+
np.fill_diagonal(M, 0.)
|
| 471 |
+
_, (sca, _) = matrix_balance(M, separate=1, permute=0)
|
| 472 |
+
# do we need to bother?
|
| 473 |
+
if not np.allclose(sca, np.ones_like(sca)):
|
| 474 |
+
# Now impose diag(D,inv(D)) from Benner where D is
|
| 475 |
+
# square root of s_i/s_(n+i) for i=0,....
|
| 476 |
+
sca = np.log2(sca)
|
| 477 |
+
# NOTE: Py3 uses "Bankers Rounding: round to the nearest even" !!
|
| 478 |
+
s = np.round((sca[m:2*m] - sca[:m])/2)
|
| 479 |
+
sca = 2 ** np.r_[s, -s, sca[2*m:]]
|
| 480 |
+
# Elementwise multiplication via broadcasting.
|
| 481 |
+
elwisescale = sca[:, None] * np.reciprocal(sca)
|
| 482 |
+
H *= elwisescale
|
| 483 |
+
J *= elwisescale
|
| 484 |
+
|
| 485 |
+
# Deflate the pencil to 2m x 2m ala Ref.1, eq.(55)
|
| 486 |
+
q, r = qr(H[:, -n:])
|
| 487 |
+
H = q[:, n:].conj().T.dot(H[:, :2*m])
|
| 488 |
+
J = q[:2*m, n:].conj().T.dot(J[:2*m, :2*m])
|
| 489 |
+
|
| 490 |
+
# Decide on which output type is needed for QZ
|
| 491 |
+
out_str = 'real' if r_or_c == float else 'complex'
|
| 492 |
+
|
| 493 |
+
_, _, _, _, _, u = ordqz(H, J, sort='lhp', overwrite_a=True,
|
| 494 |
+
overwrite_b=True, check_finite=False,
|
| 495 |
+
output=out_str)
|
| 496 |
+
|
| 497 |
+
# Get the relevant parts of the stable subspace basis
|
| 498 |
+
if e is not None:
|
| 499 |
+
u, _ = qr(np.vstack((e.dot(u[:m, :m]), u[m:, :m])))
|
| 500 |
+
u00 = u[:m, :m]
|
| 501 |
+
u10 = u[m:, :m]
|
| 502 |
+
|
| 503 |
+
# Solve via back-substituion after checking the condition of u00
|
| 504 |
+
up, ul, uu = lu(u00)
|
| 505 |
+
if 1/cond(uu) < np.spacing(1.):
|
| 506 |
+
raise LinAlgError('Failed to find a finite solution.')
|
| 507 |
+
|
| 508 |
+
# Exploit the triangular structure
|
| 509 |
+
x = solve_triangular(ul.conj().T,
|
| 510 |
+
solve_triangular(uu.conj().T,
|
| 511 |
+
u10.conj().T,
|
| 512 |
+
lower=True),
|
| 513 |
+
unit_diagonal=True,
|
| 514 |
+
).conj().T.dot(up.conj().T)
|
| 515 |
+
if balanced:
|
| 516 |
+
x *= sca[:m, None] * sca[:m]
|
| 517 |
+
|
| 518 |
+
# Check the deviation from symmetry for lack of success
|
| 519 |
+
# See proof of Thm.5 item 3 in [2]
|
| 520 |
+
u_sym = u00.conj().T.dot(u10)
|
| 521 |
+
n_u_sym = norm(u_sym, 1)
|
| 522 |
+
u_sym = u_sym - u_sym.conj().T
|
| 523 |
+
sym_threshold = np.max([np.spacing(1000.), 0.1*n_u_sym])
|
| 524 |
+
|
| 525 |
+
if norm(u_sym, 1) > sym_threshold:
|
| 526 |
+
raise LinAlgError('The associated Hamiltonian pencil has eigenvalues '
|
| 527 |
+
'too close to the imaginary axis')
|
| 528 |
+
|
| 529 |
+
return (x + x.conj().T)/2
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
def solve_discrete_are(a, b, q, r, e=None, s=None, balanced=True):
|
| 533 |
+
r"""
|
| 534 |
+
Solves the discrete-time algebraic Riccati equation (DARE).
|
| 535 |
+
|
| 536 |
+
The DARE is defined as
|
| 537 |
+
|
| 538 |
+
.. math::
|
| 539 |
+
|
| 540 |
+
A^HXA - X - (A^HXB) (R + B^HXB)^{-1} (B^HXA) + Q = 0
|
| 541 |
+
|
| 542 |
+
The limitations for a solution to exist are :
|
| 543 |
+
|
| 544 |
+
* All eigenvalues of :math:`A` outside the unit disc, should be
|
| 545 |
+
controllable.
|
| 546 |
+
|
| 547 |
+
* The associated symplectic pencil (See Notes), should have
|
| 548 |
+
eigenvalues sufficiently away from the unit circle.
|
| 549 |
+
|
| 550 |
+
Moreover, if ``e`` and ``s`` are not both precisely ``None``, then the
|
| 551 |
+
generalized version of DARE
|
| 552 |
+
|
| 553 |
+
.. math::
|
| 554 |
+
|
| 555 |
+
A^HXA - E^HXE - (A^HXB+S) (R+B^HXB)^{-1} (B^HXA+S^H) + Q = 0
|
| 556 |
+
|
| 557 |
+
is solved. When omitted, ``e`` is assumed to be the identity and ``s``
|
| 558 |
+
is assumed to be the zero matrix.
|
| 559 |
+
|
| 560 |
+
Parameters
|
| 561 |
+
----------
|
| 562 |
+
a : (M, M) array_like
|
| 563 |
+
Square matrix
|
| 564 |
+
b : (M, N) array_like
|
| 565 |
+
Input
|
| 566 |
+
q : (M, M) array_like
|
| 567 |
+
Input
|
| 568 |
+
r : (N, N) array_like
|
| 569 |
+
Square matrix
|
| 570 |
+
e : (M, M) array_like, optional
|
| 571 |
+
Nonsingular square matrix
|
| 572 |
+
s : (M, N) array_like, optional
|
| 573 |
+
Input
|
| 574 |
+
balanced : bool
|
| 575 |
+
The boolean that indicates whether a balancing step is performed
|
| 576 |
+
on the data. The default is set to True.
|
| 577 |
+
|
| 578 |
+
Returns
|
| 579 |
+
-------
|
| 580 |
+
x : (M, M) ndarray
|
| 581 |
+
Solution to the discrete algebraic Riccati equation.
|
| 582 |
+
|
| 583 |
+
Raises
|
| 584 |
+
------
|
| 585 |
+
LinAlgError
|
| 586 |
+
For cases where the stable subspace of the pencil could not be
|
| 587 |
+
isolated. See Notes section and the references for details.
|
| 588 |
+
|
| 589 |
+
See Also
|
| 590 |
+
--------
|
| 591 |
+
solve_continuous_are : Solves the continuous algebraic Riccati equation
|
| 592 |
+
|
| 593 |
+
Notes
|
| 594 |
+
-----
|
| 595 |
+
The equation is solved by forming the extended symplectic matrix pencil,
|
| 596 |
+
as described in [1]_, :math:`H - \lambda J` given by the block matrices ::
|
| 597 |
+
|
| 598 |
+
[ A 0 B ] [ E 0 B ]
|
| 599 |
+
[ -Q E^H -S ] - \lambda * [ 0 A^H 0 ]
|
| 600 |
+
[ S^H 0 R ] [ 0 -B^H 0 ]
|
| 601 |
+
|
| 602 |
+
and using a QZ decomposition method.
|
| 603 |
+
|
| 604 |
+
In this algorithm, the fail conditions are linked to the symmetry
|
| 605 |
+
of the product :math:`U_2 U_1^{-1}` and condition number of
|
| 606 |
+
:math:`U_1`. Here, :math:`U` is the 2m-by-m matrix that holds the
|
| 607 |
+
eigenvectors spanning the stable subspace with 2-m rows and partitioned
|
| 608 |
+
into two m-row matrices. See [1]_ and [2]_ for more details.
|
| 609 |
+
|
| 610 |
+
In order to improve the QZ decomposition accuracy, the pencil goes
|
| 611 |
+
through a balancing step where the sum of absolute values of
|
| 612 |
+
:math:`H` and :math:`J` rows/cols (after removing the diagonal entries)
|
| 613 |
+
is balanced following the recipe given in [3]_. If the data has small
|
| 614 |
+
numerical noise, balancing may amplify their effects and some clean up
|
| 615 |
+
is required.
|
| 616 |
+
|
| 617 |
+
.. versionadded:: 0.11.0
|
| 618 |
+
|
| 619 |
+
References
|
| 620 |
+
----------
|
| 621 |
+
.. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving
|
| 622 |
+
Riccati Equations.", SIAM Journal on Scientific and Statistical
|
| 623 |
+
Computing, Vol.2(2), :doi:`10.1137/0902010`
|
| 624 |
+
|
| 625 |
+
.. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati
|
| 626 |
+
Equations.", Massachusetts Institute of Technology. Laboratory for
|
| 627 |
+
Information and Decision Systems. LIDS-R ; 859. Available online :
|
| 628 |
+
http://hdl.handle.net/1721.1/1301
|
| 629 |
+
|
| 630 |
+
.. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001,
|
| 631 |
+
SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993`
|
| 632 |
+
|
| 633 |
+
Examples
|
| 634 |
+
--------
|
| 635 |
+
Given `a`, `b`, `q`, and `r` solve for `x`:
|
| 636 |
+
|
| 637 |
+
>>> import numpy as np
|
| 638 |
+
>>> from scipy import linalg as la
|
| 639 |
+
>>> a = np.array([[0, 1], [0, -1]])
|
| 640 |
+
>>> b = np.array([[1, 0], [2, 1]])
|
| 641 |
+
>>> q = np.array([[-4, -4], [-4, 7]])
|
| 642 |
+
>>> r = np.array([[9, 3], [3, 1]])
|
| 643 |
+
>>> x = la.solve_discrete_are(a, b, q, r)
|
| 644 |
+
>>> x
|
| 645 |
+
array([[-4., -4.],
|
| 646 |
+
[-4., 7.]])
|
| 647 |
+
>>> R = la.solve(r + b.T.dot(x).dot(b), b.T.dot(x).dot(a))
|
| 648 |
+
>>> np.allclose(a.T.dot(x).dot(a) - x - a.T.dot(x).dot(b).dot(R), -q)
|
| 649 |
+
True
|
| 650 |
+
|
| 651 |
+
"""
|
| 652 |
+
|
| 653 |
+
# Validate input arguments
|
| 654 |
+
a, b, q, r, e, s, m, n, r_or_c, gen_are = _are_validate_args(
|
| 655 |
+
a, b, q, r, e, s, 'dare')
|
| 656 |
+
|
| 657 |
+
# Form the matrix pencil
|
| 658 |
+
H = np.zeros((2*m+n, 2*m+n), dtype=r_or_c)
|
| 659 |
+
H[:m, :m] = a
|
| 660 |
+
H[:m, 2*m:] = b
|
| 661 |
+
H[m:2*m, :m] = -q
|
| 662 |
+
H[m:2*m, m:2*m] = np.eye(m) if e is None else e.conj().T
|
| 663 |
+
H[m:2*m, 2*m:] = 0. if s is None else -s
|
| 664 |
+
H[2*m:, :m] = 0. if s is None else s.conj().T
|
| 665 |
+
H[2*m:, 2*m:] = r
|
| 666 |
+
|
| 667 |
+
J = np.zeros_like(H, dtype=r_or_c)
|
| 668 |
+
J[:m, :m] = np.eye(m) if e is None else e
|
| 669 |
+
J[m:2*m, m:2*m] = a.conj().T
|
| 670 |
+
J[2*m:, m:2*m] = -b.conj().T
|
| 671 |
+
|
| 672 |
+
if balanced:
|
| 673 |
+
# xGEBAL does not remove the diagonals before scaling. Also
|
| 674 |
+
# to avoid destroying the Symplectic structure, we follow Ref.3
|
| 675 |
+
M = np.abs(H) + np.abs(J)
|
| 676 |
+
np.fill_diagonal(M, 0.)
|
| 677 |
+
_, (sca, _) = matrix_balance(M, separate=1, permute=0)
|
| 678 |
+
# do we need to bother?
|
| 679 |
+
if not np.allclose(sca, np.ones_like(sca)):
|
| 680 |
+
# Now impose diag(D,inv(D)) from Benner where D is
|
| 681 |
+
# square root of s_i/s_(n+i) for i=0,....
|
| 682 |
+
sca = np.log2(sca)
|
| 683 |
+
# NOTE: Py3 uses "Bankers Rounding: round to the nearest even" !!
|
| 684 |
+
s = np.round((sca[m:2*m] - sca[:m])/2)
|
| 685 |
+
sca = 2 ** np.r_[s, -s, sca[2*m:]]
|
| 686 |
+
# Elementwise multiplication via broadcasting.
|
| 687 |
+
elwisescale = sca[:, None] * np.reciprocal(sca)
|
| 688 |
+
H *= elwisescale
|
| 689 |
+
J *= elwisescale
|
| 690 |
+
|
| 691 |
+
# Deflate the pencil by the R column ala Ref.1
|
| 692 |
+
q_of_qr, _ = qr(H[:, -n:])
|
| 693 |
+
H = q_of_qr[:, n:].conj().T.dot(H[:, :2*m])
|
| 694 |
+
J = q_of_qr[:, n:].conj().T.dot(J[:, :2*m])
|
| 695 |
+
|
| 696 |
+
# Decide on which output type is needed for QZ
|
| 697 |
+
out_str = 'real' if r_or_c == float else 'complex'
|
| 698 |
+
|
| 699 |
+
_, _, _, _, _, u = ordqz(H, J, sort='iuc',
|
| 700 |
+
overwrite_a=True,
|
| 701 |
+
overwrite_b=True,
|
| 702 |
+
check_finite=False,
|
| 703 |
+
output=out_str)
|
| 704 |
+
|
| 705 |
+
# Get the relevant parts of the stable subspace basis
|
| 706 |
+
if e is not None:
|
| 707 |
+
u, _ = qr(np.vstack((e.dot(u[:m, :m]), u[m:, :m])))
|
| 708 |
+
u00 = u[:m, :m]
|
| 709 |
+
u10 = u[m:, :m]
|
| 710 |
+
|
| 711 |
+
# Solve via back-substituion after checking the condition of u00
|
| 712 |
+
up, ul, uu = lu(u00)
|
| 713 |
+
|
| 714 |
+
if 1/cond(uu) < np.spacing(1.):
|
| 715 |
+
raise LinAlgError('Failed to find a finite solution.')
|
| 716 |
+
|
| 717 |
+
# Exploit the triangular structure
|
| 718 |
+
x = solve_triangular(ul.conj().T,
|
| 719 |
+
solve_triangular(uu.conj().T,
|
| 720 |
+
u10.conj().T,
|
| 721 |
+
lower=True),
|
| 722 |
+
unit_diagonal=True,
|
| 723 |
+
).conj().T.dot(up.conj().T)
|
| 724 |
+
if balanced:
|
| 725 |
+
x *= sca[:m, None] * sca[:m]
|
| 726 |
+
|
| 727 |
+
# Check the deviation from symmetry for lack of success
|
| 728 |
+
# See proof of Thm.5 item 3 in [2]
|
| 729 |
+
u_sym = u00.conj().T.dot(u10)
|
| 730 |
+
n_u_sym = norm(u_sym, 1)
|
| 731 |
+
u_sym = u_sym - u_sym.conj().T
|
| 732 |
+
sym_threshold = np.max([np.spacing(1000.), 0.1*n_u_sym])
|
| 733 |
+
|
| 734 |
+
if norm(u_sym, 1) > sym_threshold:
|
| 735 |
+
raise LinAlgError('The associated symplectic pencil has eigenvalues '
|
| 736 |
+
'too close to the unit circle')
|
| 737 |
+
|
| 738 |
+
return (x + x.conj().T)/2
|
| 739 |
+
|
| 740 |
+
|
| 741 |
+
def _are_validate_args(a, b, q, r, e, s, eq_type='care'):
|
| 742 |
+
"""
|
| 743 |
+
A helper function to validate the arguments supplied to the
|
| 744 |
+
Riccati equation solvers. Any discrepancy found in the input
|
| 745 |
+
matrices leads to a ``ValueError`` exception.
|
| 746 |
+
|
| 747 |
+
Essentially, it performs:
|
| 748 |
+
|
| 749 |
+
- a check whether the input is free of NaN and Infs
|
| 750 |
+
- a pass for the data through ``numpy.atleast_2d()``
|
| 751 |
+
- squareness check of the relevant arrays
|
| 752 |
+
- shape consistency check of the arrays
|
| 753 |
+
- singularity check of the relevant arrays
|
| 754 |
+
- symmetricity check of the relevant matrices
|
| 755 |
+
- a check whether the regular or the generalized version is asked.
|
| 756 |
+
|
| 757 |
+
This function is used by ``solve_continuous_are`` and
|
| 758 |
+
``solve_discrete_are``.
|
| 759 |
+
|
| 760 |
+
Parameters
|
| 761 |
+
----------
|
| 762 |
+
a, b, q, r, e, s : array_like
|
| 763 |
+
Input data
|
| 764 |
+
eq_type : str
|
| 765 |
+
Accepted arguments are 'care' and 'dare'.
|
| 766 |
+
|
| 767 |
+
Returns
|
| 768 |
+
-------
|
| 769 |
+
a, b, q, r, e, s : ndarray
|
| 770 |
+
Regularized input data
|
| 771 |
+
m, n : int
|
| 772 |
+
shape of the problem
|
| 773 |
+
r_or_c : type
|
| 774 |
+
Data type of the problem, returns float or complex
|
| 775 |
+
gen_or_not : bool
|
| 776 |
+
Type of the equation, True for generalized and False for regular ARE.
|
| 777 |
+
|
| 778 |
+
"""
|
| 779 |
+
|
| 780 |
+
if eq_type.lower() not in ("dare", "care"):
|
| 781 |
+
raise ValueError("Equation type unknown. "
|
| 782 |
+
"Only 'care' and 'dare' is understood")
|
| 783 |
+
|
| 784 |
+
a = np.atleast_2d(_asarray_validated(a, check_finite=True))
|
| 785 |
+
b = np.atleast_2d(_asarray_validated(b, check_finite=True))
|
| 786 |
+
q = np.atleast_2d(_asarray_validated(q, check_finite=True))
|
| 787 |
+
r = np.atleast_2d(_asarray_validated(r, check_finite=True))
|
| 788 |
+
|
| 789 |
+
# Get the correct data types otherwise NumPy complains
|
| 790 |
+
# about pushing complex numbers into real arrays.
|
| 791 |
+
r_or_c = complex if np.iscomplexobj(b) else float
|
| 792 |
+
|
| 793 |
+
for ind, mat in enumerate((a, q, r)):
|
| 794 |
+
if np.iscomplexobj(mat):
|
| 795 |
+
r_or_c = complex
|
| 796 |
+
|
| 797 |
+
if not np.equal(*mat.shape):
|
| 798 |
+
raise ValueError("Matrix {} should be square.".format("aqr"[ind]))
|
| 799 |
+
|
| 800 |
+
# Shape consistency checks
|
| 801 |
+
m, n = b.shape
|
| 802 |
+
if m != a.shape[0]:
|
| 803 |
+
raise ValueError("Matrix a and b should have the same number of rows.")
|
| 804 |
+
if m != q.shape[0]:
|
| 805 |
+
raise ValueError("Matrix a and q should have the same shape.")
|
| 806 |
+
if n != r.shape[0]:
|
| 807 |
+
raise ValueError("Matrix b and r should have the same number of cols.")
|
| 808 |
+
|
| 809 |
+
# Check if the data matrices q, r are (sufficiently) hermitian
|
| 810 |
+
for ind, mat in enumerate((q, r)):
|
| 811 |
+
if norm(mat - mat.conj().T, 1) > np.spacing(norm(mat, 1))*100:
|
| 812 |
+
raise ValueError("Matrix {} should be symmetric/hermitian."
|
| 813 |
+
"".format("qr"[ind]))
|
| 814 |
+
|
| 815 |
+
# Continuous time ARE should have a nonsingular r matrix.
|
| 816 |
+
if eq_type == 'care':
|
| 817 |
+
min_sv = svd(r, compute_uv=False)[-1]
|
| 818 |
+
if min_sv == 0. or min_sv < np.spacing(1.)*norm(r, 1):
|
| 819 |
+
raise ValueError('Matrix r is numerically singular.')
|
| 820 |
+
|
| 821 |
+
# Check if the generalized case is required with omitted arguments
|
| 822 |
+
# perform late shape checking etc.
|
| 823 |
+
generalized_case = e is not None or s is not None
|
| 824 |
+
|
| 825 |
+
if generalized_case:
|
| 826 |
+
if e is not None:
|
| 827 |
+
e = np.atleast_2d(_asarray_validated(e, check_finite=True))
|
| 828 |
+
if not np.equal(*e.shape):
|
| 829 |
+
raise ValueError("Matrix e should be square.")
|
| 830 |
+
if m != e.shape[0]:
|
| 831 |
+
raise ValueError("Matrix a and e should have the same shape.")
|
| 832 |
+
# numpy.linalg.cond doesn't check for exact zeros and
|
| 833 |
+
# emits a runtime warning. Hence the following manual check.
|
| 834 |
+
min_sv = svd(e, compute_uv=False)[-1]
|
| 835 |
+
if min_sv == 0. or min_sv < np.spacing(1.) * norm(e, 1):
|
| 836 |
+
raise ValueError('Matrix e is numerically singular.')
|
| 837 |
+
if np.iscomplexobj(e):
|
| 838 |
+
r_or_c = complex
|
| 839 |
+
if s is not None:
|
| 840 |
+
s = np.atleast_2d(_asarray_validated(s, check_finite=True))
|
| 841 |
+
if s.shape != b.shape:
|
| 842 |
+
raise ValueError("Matrix b and s should have the same shape.")
|
| 843 |
+
if np.iscomplexobj(s):
|
| 844 |
+
r_or_c = complex
|
| 845 |
+
|
| 846 |
+
return a, b, q, r, e, s, m, n, r_or_c, generalized_case
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_special_matrices.py
ADDED
|
@@ -0,0 +1,1257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
from numpy.lib.stride_tricks import as_strided
|
| 5 |
+
|
| 6 |
+
__all__ = ['toeplitz', 'circulant', 'hankel',
|
| 7 |
+
'hadamard', 'leslie', 'kron', 'block_diag', 'companion',
|
| 8 |
+
'helmert', 'hilbert', 'invhilbert', 'pascal', 'invpascal', 'dft',
|
| 9 |
+
'fiedler', 'fiedler_companion', 'convolution_matrix']
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
# -----------------------------------------------------------------------------
|
| 13 |
+
# matrix construction functions
|
| 14 |
+
# -----------------------------------------------------------------------------
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def toeplitz(c, r=None):
|
| 18 |
+
"""
|
| 19 |
+
Construct a Toeplitz matrix.
|
| 20 |
+
|
| 21 |
+
The Toeplitz matrix has constant diagonals, with c as its first column
|
| 22 |
+
and r as its first row. If r is not given, ``r == conjugate(c)`` is
|
| 23 |
+
assumed.
|
| 24 |
+
|
| 25 |
+
Parameters
|
| 26 |
+
----------
|
| 27 |
+
c : array_like
|
| 28 |
+
First column of the matrix. Whatever the actual shape of `c`, it
|
| 29 |
+
will be converted to a 1-D array.
|
| 30 |
+
r : array_like, optional
|
| 31 |
+
First row of the matrix. If None, ``r = conjugate(c)`` is assumed;
|
| 32 |
+
in this case, if c[0] is real, the result is a Hermitian matrix.
|
| 33 |
+
r[0] is ignored; the first row of the returned matrix is
|
| 34 |
+
``[c[0], r[1:]]``. Whatever the actual shape of `r`, it will be
|
| 35 |
+
converted to a 1-D array.
|
| 36 |
+
|
| 37 |
+
Returns
|
| 38 |
+
-------
|
| 39 |
+
A : (len(c), len(r)) ndarray
|
| 40 |
+
The Toeplitz matrix. Dtype is the same as ``(c[0] + r[0]).dtype``.
|
| 41 |
+
|
| 42 |
+
See Also
|
| 43 |
+
--------
|
| 44 |
+
circulant : circulant matrix
|
| 45 |
+
hankel : Hankel matrix
|
| 46 |
+
solve_toeplitz : Solve a Toeplitz system.
|
| 47 |
+
|
| 48 |
+
Notes
|
| 49 |
+
-----
|
| 50 |
+
The behavior when `c` or `r` is a scalar, or when `c` is complex and
|
| 51 |
+
`r` is None, was changed in version 0.8.0. The behavior in previous
|
| 52 |
+
versions was undocumented and is no longer supported.
|
| 53 |
+
|
| 54 |
+
Examples
|
| 55 |
+
--------
|
| 56 |
+
>>> from scipy.linalg import toeplitz
|
| 57 |
+
>>> toeplitz([1,2,3], [1,4,5,6])
|
| 58 |
+
array([[1, 4, 5, 6],
|
| 59 |
+
[2, 1, 4, 5],
|
| 60 |
+
[3, 2, 1, 4]])
|
| 61 |
+
>>> toeplitz([1.0, 2+3j, 4-1j])
|
| 62 |
+
array([[ 1.+0.j, 2.-3.j, 4.+1.j],
|
| 63 |
+
[ 2.+3.j, 1.+0.j, 2.-3.j],
|
| 64 |
+
[ 4.-1.j, 2.+3.j, 1.+0.j]])
|
| 65 |
+
|
| 66 |
+
"""
|
| 67 |
+
c = np.asarray(c).ravel()
|
| 68 |
+
if r is None:
|
| 69 |
+
r = c.conjugate()
|
| 70 |
+
else:
|
| 71 |
+
r = np.asarray(r).ravel()
|
| 72 |
+
# Form a 1-D array containing a reversed c followed by r[1:] that could be
|
| 73 |
+
# strided to give us toeplitz matrix.
|
| 74 |
+
vals = np.concatenate((c[::-1], r[1:]))
|
| 75 |
+
out_shp = len(c), len(r)
|
| 76 |
+
n = vals.strides[0]
|
| 77 |
+
return as_strided(vals[len(c)-1:], shape=out_shp, strides=(-n, n)).copy()
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def circulant(c):
|
| 81 |
+
"""
|
| 82 |
+
Construct a circulant matrix.
|
| 83 |
+
|
| 84 |
+
Parameters
|
| 85 |
+
----------
|
| 86 |
+
c : (N,) array_like
|
| 87 |
+
1-D array, the first column of the matrix.
|
| 88 |
+
|
| 89 |
+
Returns
|
| 90 |
+
-------
|
| 91 |
+
A : (N, N) ndarray
|
| 92 |
+
A circulant matrix whose first column is `c`.
|
| 93 |
+
|
| 94 |
+
See Also
|
| 95 |
+
--------
|
| 96 |
+
toeplitz : Toeplitz matrix
|
| 97 |
+
hankel : Hankel matrix
|
| 98 |
+
solve_circulant : Solve a circulant system.
|
| 99 |
+
|
| 100 |
+
Notes
|
| 101 |
+
-----
|
| 102 |
+
.. versionadded:: 0.8.0
|
| 103 |
+
|
| 104 |
+
Examples
|
| 105 |
+
--------
|
| 106 |
+
>>> from scipy.linalg import circulant
|
| 107 |
+
>>> circulant([1, 2, 3])
|
| 108 |
+
array([[1, 3, 2],
|
| 109 |
+
[2, 1, 3],
|
| 110 |
+
[3, 2, 1]])
|
| 111 |
+
|
| 112 |
+
"""
|
| 113 |
+
c = np.asarray(c).ravel()
|
| 114 |
+
# Form an extended array that could be strided to give circulant version
|
| 115 |
+
c_ext = np.concatenate((c[::-1], c[:0:-1]))
|
| 116 |
+
L = len(c)
|
| 117 |
+
n = c_ext.strides[0]
|
| 118 |
+
return as_strided(c_ext[L-1:], shape=(L, L), strides=(-n, n)).copy()
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def hankel(c, r=None):
|
| 122 |
+
"""
|
| 123 |
+
Construct a Hankel matrix.
|
| 124 |
+
|
| 125 |
+
The Hankel matrix has constant anti-diagonals, with `c` as its
|
| 126 |
+
first column and `r` as its last row. If `r` is not given, then
|
| 127 |
+
`r = zeros_like(c)` is assumed.
|
| 128 |
+
|
| 129 |
+
Parameters
|
| 130 |
+
----------
|
| 131 |
+
c : array_like
|
| 132 |
+
First column of the matrix. Whatever the actual shape of `c`, it
|
| 133 |
+
will be converted to a 1-D array.
|
| 134 |
+
r : array_like, optional
|
| 135 |
+
Last row of the matrix. If None, ``r = zeros_like(c)`` is assumed.
|
| 136 |
+
r[0] is ignored; the last row of the returned matrix is
|
| 137 |
+
``[c[-1], r[1:]]``. Whatever the actual shape of `r`, it will be
|
| 138 |
+
converted to a 1-D array.
|
| 139 |
+
|
| 140 |
+
Returns
|
| 141 |
+
-------
|
| 142 |
+
A : (len(c), len(r)) ndarray
|
| 143 |
+
The Hankel matrix. Dtype is the same as ``(c[0] + r[0]).dtype``.
|
| 144 |
+
|
| 145 |
+
See Also
|
| 146 |
+
--------
|
| 147 |
+
toeplitz : Toeplitz matrix
|
| 148 |
+
circulant : circulant matrix
|
| 149 |
+
|
| 150 |
+
Examples
|
| 151 |
+
--------
|
| 152 |
+
>>> from scipy.linalg import hankel
|
| 153 |
+
>>> hankel([1, 17, 99])
|
| 154 |
+
array([[ 1, 17, 99],
|
| 155 |
+
[17, 99, 0],
|
| 156 |
+
[99, 0, 0]])
|
| 157 |
+
>>> hankel([1,2,3,4], [4,7,7,8,9])
|
| 158 |
+
array([[1, 2, 3, 4, 7],
|
| 159 |
+
[2, 3, 4, 7, 7],
|
| 160 |
+
[3, 4, 7, 7, 8],
|
| 161 |
+
[4, 7, 7, 8, 9]])
|
| 162 |
+
|
| 163 |
+
"""
|
| 164 |
+
c = np.asarray(c).ravel()
|
| 165 |
+
if r is None:
|
| 166 |
+
r = np.zeros_like(c)
|
| 167 |
+
else:
|
| 168 |
+
r = np.asarray(r).ravel()
|
| 169 |
+
# Form a 1-D array of values to be used in the matrix, containing `c`
|
| 170 |
+
# followed by r[1:].
|
| 171 |
+
vals = np.concatenate((c, r[1:]))
|
| 172 |
+
# Stride on concatenated array to get hankel matrix
|
| 173 |
+
out_shp = len(c), len(r)
|
| 174 |
+
n = vals.strides[0]
|
| 175 |
+
return as_strided(vals, shape=out_shp, strides=(n, n)).copy()
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def hadamard(n, dtype=int):
|
| 179 |
+
"""
|
| 180 |
+
Construct an Hadamard matrix.
|
| 181 |
+
|
| 182 |
+
Constructs an n-by-n Hadamard matrix, using Sylvester's
|
| 183 |
+
construction. `n` must be a power of 2.
|
| 184 |
+
|
| 185 |
+
Parameters
|
| 186 |
+
----------
|
| 187 |
+
n : int
|
| 188 |
+
The order of the matrix. `n` must be a power of 2.
|
| 189 |
+
dtype : dtype, optional
|
| 190 |
+
The data type of the array to be constructed.
|
| 191 |
+
|
| 192 |
+
Returns
|
| 193 |
+
-------
|
| 194 |
+
H : (n, n) ndarray
|
| 195 |
+
The Hadamard matrix.
|
| 196 |
+
|
| 197 |
+
Notes
|
| 198 |
+
-----
|
| 199 |
+
.. versionadded:: 0.8.0
|
| 200 |
+
|
| 201 |
+
Examples
|
| 202 |
+
--------
|
| 203 |
+
>>> from scipy.linalg import hadamard
|
| 204 |
+
>>> hadamard(2, dtype=complex)
|
| 205 |
+
array([[ 1.+0.j, 1.+0.j],
|
| 206 |
+
[ 1.+0.j, -1.-0.j]])
|
| 207 |
+
>>> hadamard(4)
|
| 208 |
+
array([[ 1, 1, 1, 1],
|
| 209 |
+
[ 1, -1, 1, -1],
|
| 210 |
+
[ 1, 1, -1, -1],
|
| 211 |
+
[ 1, -1, -1, 1]])
|
| 212 |
+
|
| 213 |
+
"""
|
| 214 |
+
|
| 215 |
+
# This function is a slightly modified version of the
|
| 216 |
+
# function contributed by Ivo in ticket #675.
|
| 217 |
+
|
| 218 |
+
if n < 1:
|
| 219 |
+
lg2 = 0
|
| 220 |
+
else:
|
| 221 |
+
lg2 = int(math.log(n, 2))
|
| 222 |
+
if 2 ** lg2 != n:
|
| 223 |
+
raise ValueError("n must be an positive integer, and n must be "
|
| 224 |
+
"a power of 2")
|
| 225 |
+
|
| 226 |
+
H = np.array([[1]], dtype=dtype)
|
| 227 |
+
|
| 228 |
+
# Sylvester's construction
|
| 229 |
+
for i in range(0, lg2):
|
| 230 |
+
H = np.vstack((np.hstack((H, H)), np.hstack((H, -H))))
|
| 231 |
+
|
| 232 |
+
return H
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def leslie(f, s):
|
| 236 |
+
"""
|
| 237 |
+
Create a Leslie matrix.
|
| 238 |
+
|
| 239 |
+
Given the length n array of fecundity coefficients `f` and the length
|
| 240 |
+
n-1 array of survival coefficients `s`, return the associated Leslie
|
| 241 |
+
matrix.
|
| 242 |
+
|
| 243 |
+
Parameters
|
| 244 |
+
----------
|
| 245 |
+
f : (N,) array_like
|
| 246 |
+
The "fecundity" coefficients.
|
| 247 |
+
s : (N-1,) array_like
|
| 248 |
+
The "survival" coefficients, has to be 1-D. The length of `s`
|
| 249 |
+
must be one less than the length of `f`, and it must be at least 1.
|
| 250 |
+
|
| 251 |
+
Returns
|
| 252 |
+
-------
|
| 253 |
+
L : (N, N) ndarray
|
| 254 |
+
The array is zero except for the first row,
|
| 255 |
+
which is `f`, and the first sub-diagonal, which is `s`.
|
| 256 |
+
The data-type of the array will be the data-type of ``f[0]+s[0]``.
|
| 257 |
+
|
| 258 |
+
Notes
|
| 259 |
+
-----
|
| 260 |
+
.. versionadded:: 0.8.0
|
| 261 |
+
|
| 262 |
+
The Leslie matrix is used to model discrete-time, age-structured
|
| 263 |
+
population growth [1]_ [2]_. In a population with `n` age classes, two sets
|
| 264 |
+
of parameters define a Leslie matrix: the `n` "fecundity coefficients",
|
| 265 |
+
which give the number of offspring per-capita produced by each age
|
| 266 |
+
class, and the `n` - 1 "survival coefficients", which give the
|
| 267 |
+
per-capita survival rate of each age class.
|
| 268 |
+
|
| 269 |
+
References
|
| 270 |
+
----------
|
| 271 |
+
.. [1] P. H. Leslie, On the use of matrices in certain population
|
| 272 |
+
mathematics, Biometrika, Vol. 33, No. 3, 183--212 (Nov. 1945)
|
| 273 |
+
.. [2] P. H. Leslie, Some further notes on the use of matrices in
|
| 274 |
+
population mathematics, Biometrika, Vol. 35, No. 3/4, 213--245
|
| 275 |
+
(Dec. 1948)
|
| 276 |
+
|
| 277 |
+
Examples
|
| 278 |
+
--------
|
| 279 |
+
>>> from scipy.linalg import leslie
|
| 280 |
+
>>> leslie([0.1, 2.0, 1.0, 0.1], [0.2, 0.8, 0.7])
|
| 281 |
+
array([[ 0.1, 2. , 1. , 0.1],
|
| 282 |
+
[ 0.2, 0. , 0. , 0. ],
|
| 283 |
+
[ 0. , 0.8, 0. , 0. ],
|
| 284 |
+
[ 0. , 0. , 0.7, 0. ]])
|
| 285 |
+
|
| 286 |
+
"""
|
| 287 |
+
f = np.atleast_1d(f)
|
| 288 |
+
s = np.atleast_1d(s)
|
| 289 |
+
if f.ndim != 1:
|
| 290 |
+
raise ValueError("Incorrect shape for f. f must be 1D")
|
| 291 |
+
if s.ndim != 1:
|
| 292 |
+
raise ValueError("Incorrect shape for s. s must be 1D")
|
| 293 |
+
if f.size != s.size + 1:
|
| 294 |
+
raise ValueError("Incorrect lengths for f and s. The length"
|
| 295 |
+
" of s must be one less than the length of f.")
|
| 296 |
+
if s.size == 0:
|
| 297 |
+
raise ValueError("The length of s must be at least 1.")
|
| 298 |
+
|
| 299 |
+
tmp = f[0] + s[0]
|
| 300 |
+
n = f.size
|
| 301 |
+
a = np.zeros((n, n), dtype=tmp.dtype)
|
| 302 |
+
a[0] = f
|
| 303 |
+
a[list(range(1, n)), list(range(0, n - 1))] = s
|
| 304 |
+
return a
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def kron(a, b):
|
| 308 |
+
"""
|
| 309 |
+
Kronecker product.
|
| 310 |
+
|
| 311 |
+
The result is the block matrix::
|
| 312 |
+
|
| 313 |
+
a[0,0]*b a[0,1]*b ... a[0,-1]*b
|
| 314 |
+
a[1,0]*b a[1,1]*b ... a[1,-1]*b
|
| 315 |
+
...
|
| 316 |
+
a[-1,0]*b a[-1,1]*b ... a[-1,-1]*b
|
| 317 |
+
|
| 318 |
+
Parameters
|
| 319 |
+
----------
|
| 320 |
+
a : (M, N) ndarray
|
| 321 |
+
Input array
|
| 322 |
+
b : (P, Q) ndarray
|
| 323 |
+
Input array
|
| 324 |
+
|
| 325 |
+
Returns
|
| 326 |
+
-------
|
| 327 |
+
A : (M*P, N*Q) ndarray
|
| 328 |
+
Kronecker product of `a` and `b`.
|
| 329 |
+
|
| 330 |
+
Examples
|
| 331 |
+
--------
|
| 332 |
+
>>> from numpy import array
|
| 333 |
+
>>> from scipy.linalg import kron
|
| 334 |
+
>>> kron(array([[1,2],[3,4]]), array([[1,1,1]]))
|
| 335 |
+
array([[1, 1, 1, 2, 2, 2],
|
| 336 |
+
[3, 3, 3, 4, 4, 4]])
|
| 337 |
+
|
| 338 |
+
"""
|
| 339 |
+
if not a.flags['CONTIGUOUS']:
|
| 340 |
+
a = np.reshape(a, a.shape)
|
| 341 |
+
if not b.flags['CONTIGUOUS']:
|
| 342 |
+
b = np.reshape(b, b.shape)
|
| 343 |
+
o = np.outer(a, b)
|
| 344 |
+
o = o.reshape(a.shape + b.shape)
|
| 345 |
+
return np.concatenate(np.concatenate(o, axis=1), axis=1)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def block_diag(*arrs):
|
| 349 |
+
"""
|
| 350 |
+
Create a block diagonal matrix from provided arrays.
|
| 351 |
+
|
| 352 |
+
Given the inputs `A`, `B` and `C`, the output will have these
|
| 353 |
+
arrays arranged on the diagonal::
|
| 354 |
+
|
| 355 |
+
[[A, 0, 0],
|
| 356 |
+
[0, B, 0],
|
| 357 |
+
[0, 0, C]]
|
| 358 |
+
|
| 359 |
+
Parameters
|
| 360 |
+
----------
|
| 361 |
+
A, B, C, ... : array_like, up to 2-D
|
| 362 |
+
Input arrays. A 1-D array or array_like sequence of length `n` is
|
| 363 |
+
treated as a 2-D array with shape ``(1,n)``.
|
| 364 |
+
|
| 365 |
+
Returns
|
| 366 |
+
-------
|
| 367 |
+
D : ndarray
|
| 368 |
+
Array with `A`, `B`, `C`, ... on the diagonal. `D` has the
|
| 369 |
+
same dtype as `A`.
|
| 370 |
+
|
| 371 |
+
Notes
|
| 372 |
+
-----
|
| 373 |
+
If all the input arrays are square, the output is known as a
|
| 374 |
+
block diagonal matrix.
|
| 375 |
+
|
| 376 |
+
Empty sequences (i.e., array-likes of zero size) will not be ignored.
|
| 377 |
+
Noteworthy, both [] and [[]] are treated as matrices with shape ``(1,0)``.
|
| 378 |
+
|
| 379 |
+
Examples
|
| 380 |
+
--------
|
| 381 |
+
>>> import numpy as np
|
| 382 |
+
>>> from scipy.linalg import block_diag
|
| 383 |
+
>>> A = [[1, 0],
|
| 384 |
+
... [0, 1]]
|
| 385 |
+
>>> B = [[3, 4, 5],
|
| 386 |
+
... [6, 7, 8]]
|
| 387 |
+
>>> C = [[7]]
|
| 388 |
+
>>> P = np.zeros((2, 0), dtype='int32')
|
| 389 |
+
>>> block_diag(A, B, C)
|
| 390 |
+
array([[1, 0, 0, 0, 0, 0],
|
| 391 |
+
[0, 1, 0, 0, 0, 0],
|
| 392 |
+
[0, 0, 3, 4, 5, 0],
|
| 393 |
+
[0, 0, 6, 7, 8, 0],
|
| 394 |
+
[0, 0, 0, 0, 0, 7]])
|
| 395 |
+
>>> block_diag(A, P, B, C)
|
| 396 |
+
array([[1, 0, 0, 0, 0, 0],
|
| 397 |
+
[0, 1, 0, 0, 0, 0],
|
| 398 |
+
[0, 0, 0, 0, 0, 0],
|
| 399 |
+
[0, 0, 0, 0, 0, 0],
|
| 400 |
+
[0, 0, 3, 4, 5, 0],
|
| 401 |
+
[0, 0, 6, 7, 8, 0],
|
| 402 |
+
[0, 0, 0, 0, 0, 7]])
|
| 403 |
+
>>> block_diag(1.0, [2, 3], [[4, 5], [6, 7]])
|
| 404 |
+
array([[ 1., 0., 0., 0., 0.],
|
| 405 |
+
[ 0., 2., 3., 0., 0.],
|
| 406 |
+
[ 0., 0., 0., 4., 5.],
|
| 407 |
+
[ 0., 0., 0., 6., 7.]])
|
| 408 |
+
|
| 409 |
+
"""
|
| 410 |
+
if arrs == ():
|
| 411 |
+
arrs = ([],)
|
| 412 |
+
arrs = [np.atleast_2d(a) for a in arrs]
|
| 413 |
+
|
| 414 |
+
bad_args = [k for k in range(len(arrs)) if arrs[k].ndim > 2]
|
| 415 |
+
if bad_args:
|
| 416 |
+
raise ValueError("arguments in the following positions have dimension "
|
| 417 |
+
"greater than 2: %s" % bad_args)
|
| 418 |
+
|
| 419 |
+
shapes = np.array([a.shape for a in arrs])
|
| 420 |
+
out_dtype = np.result_type(*[arr.dtype for arr in arrs])
|
| 421 |
+
out = np.zeros(np.sum(shapes, axis=0), dtype=out_dtype)
|
| 422 |
+
|
| 423 |
+
r, c = 0, 0
|
| 424 |
+
for i, (rr, cc) in enumerate(shapes):
|
| 425 |
+
out[r:r + rr, c:c + cc] = arrs[i]
|
| 426 |
+
r += rr
|
| 427 |
+
c += cc
|
| 428 |
+
return out
|
| 429 |
+
|
| 430 |
+
|
| 431 |
+
def companion(a):
|
| 432 |
+
"""
|
| 433 |
+
Create a companion matrix.
|
| 434 |
+
|
| 435 |
+
Create the companion matrix [1]_ associated with the polynomial whose
|
| 436 |
+
coefficients are given in `a`.
|
| 437 |
+
|
| 438 |
+
Parameters
|
| 439 |
+
----------
|
| 440 |
+
a : (N,) array_like
|
| 441 |
+
1-D array of polynomial coefficients. The length of `a` must be
|
| 442 |
+
at least two, and ``a[0]`` must not be zero.
|
| 443 |
+
|
| 444 |
+
Returns
|
| 445 |
+
-------
|
| 446 |
+
c : (N-1, N-1) ndarray
|
| 447 |
+
The first row of `c` is ``-a[1:]/a[0]``, and the first
|
| 448 |
+
sub-diagonal is all ones. The data-type of the array is the same
|
| 449 |
+
as the data-type of ``1.0*a[0]``.
|
| 450 |
+
|
| 451 |
+
Raises
|
| 452 |
+
------
|
| 453 |
+
ValueError
|
| 454 |
+
If any of the following are true: a) ``a.ndim != 1``;
|
| 455 |
+
b) ``a.size < 2``; c) ``a[0] == 0``.
|
| 456 |
+
|
| 457 |
+
Notes
|
| 458 |
+
-----
|
| 459 |
+
.. versionadded:: 0.8.0
|
| 460 |
+
|
| 461 |
+
References
|
| 462 |
+
----------
|
| 463 |
+
.. [1] R. A. Horn & C. R. Johnson, *Matrix Analysis*. Cambridge, UK:
|
| 464 |
+
Cambridge University Press, 1999, pp. 146-7.
|
| 465 |
+
|
| 466 |
+
Examples
|
| 467 |
+
--------
|
| 468 |
+
>>> from scipy.linalg import companion
|
| 469 |
+
>>> companion([1, -10, 31, -30])
|
| 470 |
+
array([[ 10., -31., 30.],
|
| 471 |
+
[ 1., 0., 0.],
|
| 472 |
+
[ 0., 1., 0.]])
|
| 473 |
+
|
| 474 |
+
"""
|
| 475 |
+
a = np.atleast_1d(a)
|
| 476 |
+
|
| 477 |
+
if a.ndim != 1:
|
| 478 |
+
raise ValueError("Incorrect shape for `a`. `a` must be "
|
| 479 |
+
"one-dimensional.")
|
| 480 |
+
|
| 481 |
+
if a.size < 2:
|
| 482 |
+
raise ValueError("The length of `a` must be at least 2.")
|
| 483 |
+
|
| 484 |
+
if a[0] == 0:
|
| 485 |
+
raise ValueError("The first coefficient in `a` must not be zero.")
|
| 486 |
+
|
| 487 |
+
first_row = -a[1:] / (1.0 * a[0])
|
| 488 |
+
n = a.size
|
| 489 |
+
c = np.zeros((n - 1, n - 1), dtype=first_row.dtype)
|
| 490 |
+
c[0] = first_row
|
| 491 |
+
c[list(range(1, n - 1)), list(range(0, n - 2))] = 1
|
| 492 |
+
return c
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
def helmert(n, full=False):
|
| 496 |
+
"""
|
| 497 |
+
Create an Helmert matrix of order `n`.
|
| 498 |
+
|
| 499 |
+
This has applications in statistics, compositional or simplicial analysis,
|
| 500 |
+
and in Aitchison geometry.
|
| 501 |
+
|
| 502 |
+
Parameters
|
| 503 |
+
----------
|
| 504 |
+
n : int
|
| 505 |
+
The size of the array to create.
|
| 506 |
+
full : bool, optional
|
| 507 |
+
If True the (n, n) ndarray will be returned.
|
| 508 |
+
Otherwise the submatrix that does not include the first
|
| 509 |
+
row will be returned.
|
| 510 |
+
Default: False.
|
| 511 |
+
|
| 512 |
+
Returns
|
| 513 |
+
-------
|
| 514 |
+
M : ndarray
|
| 515 |
+
The Helmert matrix.
|
| 516 |
+
The shape is (n, n) or (n-1, n) depending on the `full` argument.
|
| 517 |
+
|
| 518 |
+
Examples
|
| 519 |
+
--------
|
| 520 |
+
>>> from scipy.linalg import helmert
|
| 521 |
+
>>> helmert(5, full=True)
|
| 522 |
+
array([[ 0.4472136 , 0.4472136 , 0.4472136 , 0.4472136 , 0.4472136 ],
|
| 523 |
+
[ 0.70710678, -0.70710678, 0. , 0. , 0. ],
|
| 524 |
+
[ 0.40824829, 0.40824829, -0.81649658, 0. , 0. ],
|
| 525 |
+
[ 0.28867513, 0.28867513, 0.28867513, -0.8660254 , 0. ],
|
| 526 |
+
[ 0.2236068 , 0.2236068 , 0.2236068 , 0.2236068 , -0.89442719]])
|
| 527 |
+
|
| 528 |
+
"""
|
| 529 |
+
H = np.tril(np.ones((n, n)), -1) - np.diag(np.arange(n))
|
| 530 |
+
d = np.arange(n) * np.arange(1, n+1)
|
| 531 |
+
H[0] = 1
|
| 532 |
+
d[0] = n
|
| 533 |
+
H_full = H / np.sqrt(d)[:, np.newaxis]
|
| 534 |
+
if full:
|
| 535 |
+
return H_full
|
| 536 |
+
else:
|
| 537 |
+
return H_full[1:]
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
def hilbert(n):
|
| 541 |
+
"""
|
| 542 |
+
Create a Hilbert matrix of order `n`.
|
| 543 |
+
|
| 544 |
+
Returns the `n` by `n` array with entries `h[i,j] = 1 / (i + j + 1)`.
|
| 545 |
+
|
| 546 |
+
Parameters
|
| 547 |
+
----------
|
| 548 |
+
n : int
|
| 549 |
+
The size of the array to create.
|
| 550 |
+
|
| 551 |
+
Returns
|
| 552 |
+
-------
|
| 553 |
+
h : (n, n) ndarray
|
| 554 |
+
The Hilbert matrix.
|
| 555 |
+
|
| 556 |
+
See Also
|
| 557 |
+
--------
|
| 558 |
+
invhilbert : Compute the inverse of a Hilbert matrix.
|
| 559 |
+
|
| 560 |
+
Notes
|
| 561 |
+
-----
|
| 562 |
+
.. versionadded:: 0.10.0
|
| 563 |
+
|
| 564 |
+
Examples
|
| 565 |
+
--------
|
| 566 |
+
>>> from scipy.linalg import hilbert
|
| 567 |
+
>>> hilbert(3)
|
| 568 |
+
array([[ 1. , 0.5 , 0.33333333],
|
| 569 |
+
[ 0.5 , 0.33333333, 0.25 ],
|
| 570 |
+
[ 0.33333333, 0.25 , 0.2 ]])
|
| 571 |
+
|
| 572 |
+
"""
|
| 573 |
+
values = 1.0 / (1.0 + np.arange(2 * n - 1))
|
| 574 |
+
h = hankel(values[:n], r=values[n - 1:])
|
| 575 |
+
return h
|
| 576 |
+
|
| 577 |
+
|
| 578 |
+
def invhilbert(n, exact=False):
|
| 579 |
+
"""
|
| 580 |
+
Compute the inverse of the Hilbert matrix of order `n`.
|
| 581 |
+
|
| 582 |
+
The entries in the inverse of a Hilbert matrix are integers. When `n`
|
| 583 |
+
is greater than 14, some entries in the inverse exceed the upper limit
|
| 584 |
+
of 64 bit integers. The `exact` argument provides two options for
|
| 585 |
+
dealing with these large integers.
|
| 586 |
+
|
| 587 |
+
Parameters
|
| 588 |
+
----------
|
| 589 |
+
n : int
|
| 590 |
+
The order of the Hilbert matrix.
|
| 591 |
+
exact : bool, optional
|
| 592 |
+
If False, the data type of the array that is returned is np.float64,
|
| 593 |
+
and the array is an approximation of the inverse.
|
| 594 |
+
If True, the array is the exact integer inverse array. To represent
|
| 595 |
+
the exact inverse when n > 14, the returned array is an object array
|
| 596 |
+
of long integers. For n <= 14, the exact inverse is returned as an
|
| 597 |
+
array with data type np.int64.
|
| 598 |
+
|
| 599 |
+
Returns
|
| 600 |
+
-------
|
| 601 |
+
invh : (n, n) ndarray
|
| 602 |
+
The data type of the array is np.float64 if `exact` is False.
|
| 603 |
+
If `exact` is True, the data type is either np.int64 (for n <= 14)
|
| 604 |
+
or object (for n > 14). In the latter case, the objects in the
|
| 605 |
+
array will be long integers.
|
| 606 |
+
|
| 607 |
+
See Also
|
| 608 |
+
--------
|
| 609 |
+
hilbert : Create a Hilbert matrix.
|
| 610 |
+
|
| 611 |
+
Notes
|
| 612 |
+
-----
|
| 613 |
+
.. versionadded:: 0.10.0
|
| 614 |
+
|
| 615 |
+
Examples
|
| 616 |
+
--------
|
| 617 |
+
>>> from scipy.linalg import invhilbert
|
| 618 |
+
>>> invhilbert(4)
|
| 619 |
+
array([[ 16., -120., 240., -140.],
|
| 620 |
+
[ -120., 1200., -2700., 1680.],
|
| 621 |
+
[ 240., -2700., 6480., -4200.],
|
| 622 |
+
[ -140., 1680., -4200., 2800.]])
|
| 623 |
+
>>> invhilbert(4, exact=True)
|
| 624 |
+
array([[ 16, -120, 240, -140],
|
| 625 |
+
[ -120, 1200, -2700, 1680],
|
| 626 |
+
[ 240, -2700, 6480, -4200],
|
| 627 |
+
[ -140, 1680, -4200, 2800]], dtype=int64)
|
| 628 |
+
>>> invhilbert(16)[7,7]
|
| 629 |
+
4.2475099528537506e+19
|
| 630 |
+
>>> invhilbert(16, exact=True)[7,7]
|
| 631 |
+
42475099528537378560
|
| 632 |
+
|
| 633 |
+
"""
|
| 634 |
+
from scipy.special import comb
|
| 635 |
+
if exact:
|
| 636 |
+
if n > 14:
|
| 637 |
+
dtype = object
|
| 638 |
+
else:
|
| 639 |
+
dtype = np.int64
|
| 640 |
+
else:
|
| 641 |
+
dtype = np.float64
|
| 642 |
+
invh = np.empty((n, n), dtype=dtype)
|
| 643 |
+
for i in range(n):
|
| 644 |
+
for j in range(0, i + 1):
|
| 645 |
+
s = i + j
|
| 646 |
+
invh[i, j] = ((-1) ** s * (s + 1) *
|
| 647 |
+
comb(n + i, n - j - 1, exact=exact) *
|
| 648 |
+
comb(n + j, n - i - 1, exact=exact) *
|
| 649 |
+
comb(s, i, exact=exact) ** 2)
|
| 650 |
+
if i != j:
|
| 651 |
+
invh[j, i] = invh[i, j]
|
| 652 |
+
return invh
|
| 653 |
+
|
| 654 |
+
|
| 655 |
+
def pascal(n, kind='symmetric', exact=True):
|
| 656 |
+
"""
|
| 657 |
+
Returns the n x n Pascal matrix.
|
| 658 |
+
|
| 659 |
+
The Pascal matrix is a matrix containing the binomial coefficients as
|
| 660 |
+
its elements.
|
| 661 |
+
|
| 662 |
+
Parameters
|
| 663 |
+
----------
|
| 664 |
+
n : int
|
| 665 |
+
The size of the matrix to create; that is, the result is an n x n
|
| 666 |
+
matrix.
|
| 667 |
+
kind : str, optional
|
| 668 |
+
Must be one of 'symmetric', 'lower', or 'upper'.
|
| 669 |
+
Default is 'symmetric'.
|
| 670 |
+
exact : bool, optional
|
| 671 |
+
If `exact` is True, the result is either an array of type
|
| 672 |
+
numpy.uint64 (if n < 35) or an object array of Python long integers.
|
| 673 |
+
If `exact` is False, the coefficients in the matrix are computed using
|
| 674 |
+
`scipy.special.comb` with `exact=False`. The result will be a floating
|
| 675 |
+
point array, and the values in the array will not be the exact
|
| 676 |
+
coefficients, but this version is much faster than `exact=True`.
|
| 677 |
+
|
| 678 |
+
Returns
|
| 679 |
+
-------
|
| 680 |
+
p : (n, n) ndarray
|
| 681 |
+
The Pascal matrix.
|
| 682 |
+
|
| 683 |
+
See Also
|
| 684 |
+
--------
|
| 685 |
+
invpascal
|
| 686 |
+
|
| 687 |
+
Notes
|
| 688 |
+
-----
|
| 689 |
+
See https://en.wikipedia.org/wiki/Pascal_matrix for more information
|
| 690 |
+
about Pascal matrices.
|
| 691 |
+
|
| 692 |
+
.. versionadded:: 0.11.0
|
| 693 |
+
|
| 694 |
+
Examples
|
| 695 |
+
--------
|
| 696 |
+
>>> from scipy.linalg import pascal
|
| 697 |
+
>>> pascal(4)
|
| 698 |
+
array([[ 1, 1, 1, 1],
|
| 699 |
+
[ 1, 2, 3, 4],
|
| 700 |
+
[ 1, 3, 6, 10],
|
| 701 |
+
[ 1, 4, 10, 20]], dtype=uint64)
|
| 702 |
+
>>> pascal(4, kind='lower')
|
| 703 |
+
array([[1, 0, 0, 0],
|
| 704 |
+
[1, 1, 0, 0],
|
| 705 |
+
[1, 2, 1, 0],
|
| 706 |
+
[1, 3, 3, 1]], dtype=uint64)
|
| 707 |
+
>>> pascal(50)[-1, -1]
|
| 708 |
+
25477612258980856902730428600
|
| 709 |
+
>>> from scipy.special import comb
|
| 710 |
+
>>> comb(98, 49, exact=True)
|
| 711 |
+
25477612258980856902730428600
|
| 712 |
+
|
| 713 |
+
"""
|
| 714 |
+
|
| 715 |
+
from scipy.special import comb
|
| 716 |
+
if kind not in ['symmetric', 'lower', 'upper']:
|
| 717 |
+
raise ValueError("kind must be 'symmetric', 'lower', or 'upper'")
|
| 718 |
+
|
| 719 |
+
if exact:
|
| 720 |
+
if n >= 35:
|
| 721 |
+
L_n = np.empty((n, n), dtype=object)
|
| 722 |
+
L_n.fill(0)
|
| 723 |
+
else:
|
| 724 |
+
L_n = np.zeros((n, n), dtype=np.uint64)
|
| 725 |
+
for i in range(n):
|
| 726 |
+
for j in range(i + 1):
|
| 727 |
+
L_n[i, j] = comb(i, j, exact=True)
|
| 728 |
+
else:
|
| 729 |
+
L_n = comb(*np.ogrid[:n, :n])
|
| 730 |
+
|
| 731 |
+
if kind == 'lower':
|
| 732 |
+
p = L_n
|
| 733 |
+
elif kind == 'upper':
|
| 734 |
+
p = L_n.T
|
| 735 |
+
else:
|
| 736 |
+
p = np.dot(L_n, L_n.T)
|
| 737 |
+
|
| 738 |
+
return p
|
| 739 |
+
|
| 740 |
+
|
| 741 |
+
def invpascal(n, kind='symmetric', exact=True):
|
| 742 |
+
"""
|
| 743 |
+
Returns the inverse of the n x n Pascal matrix.
|
| 744 |
+
|
| 745 |
+
The Pascal matrix is a matrix containing the binomial coefficients as
|
| 746 |
+
its elements.
|
| 747 |
+
|
| 748 |
+
Parameters
|
| 749 |
+
----------
|
| 750 |
+
n : int
|
| 751 |
+
The size of the matrix to create; that is, the result is an n x n
|
| 752 |
+
matrix.
|
| 753 |
+
kind : str, optional
|
| 754 |
+
Must be one of 'symmetric', 'lower', or 'upper'.
|
| 755 |
+
Default is 'symmetric'.
|
| 756 |
+
exact : bool, optional
|
| 757 |
+
If `exact` is True, the result is either an array of type
|
| 758 |
+
``numpy.int64`` (if `n` <= 35) or an object array of Python integers.
|
| 759 |
+
If `exact` is False, the coefficients in the matrix are computed using
|
| 760 |
+
`scipy.special.comb` with `exact=False`. The result will be a floating
|
| 761 |
+
point array, and for large `n`, the values in the array will not be the
|
| 762 |
+
exact coefficients.
|
| 763 |
+
|
| 764 |
+
Returns
|
| 765 |
+
-------
|
| 766 |
+
invp : (n, n) ndarray
|
| 767 |
+
The inverse of the Pascal matrix.
|
| 768 |
+
|
| 769 |
+
See Also
|
| 770 |
+
--------
|
| 771 |
+
pascal
|
| 772 |
+
|
| 773 |
+
Notes
|
| 774 |
+
-----
|
| 775 |
+
|
| 776 |
+
.. versionadded:: 0.16.0
|
| 777 |
+
|
| 778 |
+
References
|
| 779 |
+
----------
|
| 780 |
+
.. [1] "Pascal matrix", https://en.wikipedia.org/wiki/Pascal_matrix
|
| 781 |
+
.. [2] Cohen, A. M., "The inverse of a Pascal matrix", Mathematical
|
| 782 |
+
Gazette, 59(408), pp. 111-112, 1975.
|
| 783 |
+
|
| 784 |
+
Examples
|
| 785 |
+
--------
|
| 786 |
+
>>> from scipy.linalg import invpascal, pascal
|
| 787 |
+
>>> invp = invpascal(5)
|
| 788 |
+
>>> invp
|
| 789 |
+
array([[ 5, -10, 10, -5, 1],
|
| 790 |
+
[-10, 30, -35, 19, -4],
|
| 791 |
+
[ 10, -35, 46, -27, 6],
|
| 792 |
+
[ -5, 19, -27, 17, -4],
|
| 793 |
+
[ 1, -4, 6, -4, 1]])
|
| 794 |
+
|
| 795 |
+
>>> p = pascal(5)
|
| 796 |
+
>>> p.dot(invp)
|
| 797 |
+
array([[ 1., 0., 0., 0., 0.],
|
| 798 |
+
[ 0., 1., 0., 0., 0.],
|
| 799 |
+
[ 0., 0., 1., 0., 0.],
|
| 800 |
+
[ 0., 0., 0., 1., 0.],
|
| 801 |
+
[ 0., 0., 0., 0., 1.]])
|
| 802 |
+
|
| 803 |
+
An example of the use of `kind` and `exact`:
|
| 804 |
+
|
| 805 |
+
>>> invpascal(5, kind='lower', exact=False)
|
| 806 |
+
array([[ 1., -0., 0., -0., 0.],
|
| 807 |
+
[-1., 1., -0., 0., -0.],
|
| 808 |
+
[ 1., -2., 1., -0., 0.],
|
| 809 |
+
[-1., 3., -3., 1., -0.],
|
| 810 |
+
[ 1., -4., 6., -4., 1.]])
|
| 811 |
+
|
| 812 |
+
"""
|
| 813 |
+
from scipy.special import comb
|
| 814 |
+
|
| 815 |
+
if kind not in ['symmetric', 'lower', 'upper']:
|
| 816 |
+
raise ValueError("'kind' must be 'symmetric', 'lower' or 'upper'.")
|
| 817 |
+
|
| 818 |
+
if kind == 'symmetric':
|
| 819 |
+
if exact:
|
| 820 |
+
if n > 34:
|
| 821 |
+
dt = object
|
| 822 |
+
else:
|
| 823 |
+
dt = np.int64
|
| 824 |
+
else:
|
| 825 |
+
dt = np.float64
|
| 826 |
+
invp = np.empty((n, n), dtype=dt)
|
| 827 |
+
for i in range(n):
|
| 828 |
+
for j in range(0, i + 1):
|
| 829 |
+
v = 0
|
| 830 |
+
for k in range(n - i):
|
| 831 |
+
v += comb(i + k, k, exact=exact) * comb(i + k, i + k - j,
|
| 832 |
+
exact=exact)
|
| 833 |
+
invp[i, j] = (-1)**(i - j) * v
|
| 834 |
+
if i != j:
|
| 835 |
+
invp[j, i] = invp[i, j]
|
| 836 |
+
else:
|
| 837 |
+
# For the 'lower' and 'upper' cases, we computer the inverse by
|
| 838 |
+
# changing the sign of every other diagonal of the pascal matrix.
|
| 839 |
+
invp = pascal(n, kind=kind, exact=exact)
|
| 840 |
+
if invp.dtype == np.uint64:
|
| 841 |
+
# This cast from np.uint64 to int64 OK, because if `kind` is not
|
| 842 |
+
# "symmetric", the values in invp are all much less than 2**63.
|
| 843 |
+
invp = invp.view(np.int64)
|
| 844 |
+
|
| 845 |
+
# The toeplitz matrix has alternating bands of 1 and -1.
|
| 846 |
+
invp *= toeplitz((-1)**np.arange(n)).astype(invp.dtype)
|
| 847 |
+
|
| 848 |
+
return invp
|
| 849 |
+
|
| 850 |
+
|
| 851 |
+
def dft(n, scale=None):
|
| 852 |
+
"""
|
| 853 |
+
Discrete Fourier transform matrix.
|
| 854 |
+
|
| 855 |
+
Create the matrix that computes the discrete Fourier transform of a
|
| 856 |
+
sequence [1]_. The nth primitive root of unity used to generate the
|
| 857 |
+
matrix is exp(-2*pi*i/n), where i = sqrt(-1).
|
| 858 |
+
|
| 859 |
+
Parameters
|
| 860 |
+
----------
|
| 861 |
+
n : int
|
| 862 |
+
Size the matrix to create.
|
| 863 |
+
scale : str, optional
|
| 864 |
+
Must be None, 'sqrtn', or 'n'.
|
| 865 |
+
If `scale` is 'sqrtn', the matrix is divided by `sqrt(n)`.
|
| 866 |
+
If `scale` is 'n', the matrix is divided by `n`.
|
| 867 |
+
If `scale` is None (the default), the matrix is not normalized, and the
|
| 868 |
+
return value is simply the Vandermonde matrix of the roots of unity.
|
| 869 |
+
|
| 870 |
+
Returns
|
| 871 |
+
-------
|
| 872 |
+
m : (n, n) ndarray
|
| 873 |
+
The DFT matrix.
|
| 874 |
+
|
| 875 |
+
Notes
|
| 876 |
+
-----
|
| 877 |
+
When `scale` is None, multiplying a vector by the matrix returned by
|
| 878 |
+
`dft` is mathematically equivalent to (but much less efficient than)
|
| 879 |
+
the calculation performed by `scipy.fft.fft`.
|
| 880 |
+
|
| 881 |
+
.. versionadded:: 0.14.0
|
| 882 |
+
|
| 883 |
+
References
|
| 884 |
+
----------
|
| 885 |
+
.. [1] "DFT matrix", https://en.wikipedia.org/wiki/DFT_matrix
|
| 886 |
+
|
| 887 |
+
Examples
|
| 888 |
+
--------
|
| 889 |
+
>>> import numpy as np
|
| 890 |
+
>>> from scipy.linalg import dft
|
| 891 |
+
>>> np.set_printoptions(precision=2, suppress=True) # for compact output
|
| 892 |
+
>>> m = dft(5)
|
| 893 |
+
>>> m
|
| 894 |
+
array([[ 1. +0.j , 1. +0.j , 1. +0.j , 1. +0.j , 1. +0.j ],
|
| 895 |
+
[ 1. +0.j , 0.31-0.95j, -0.81-0.59j, -0.81+0.59j, 0.31+0.95j],
|
| 896 |
+
[ 1. +0.j , -0.81-0.59j, 0.31+0.95j, 0.31-0.95j, -0.81+0.59j],
|
| 897 |
+
[ 1. +0.j , -0.81+0.59j, 0.31-0.95j, 0.31+0.95j, -0.81-0.59j],
|
| 898 |
+
[ 1. +0.j , 0.31+0.95j, -0.81+0.59j, -0.81-0.59j, 0.31-0.95j]])
|
| 899 |
+
>>> x = np.array([1, 2, 3, 0, 3])
|
| 900 |
+
>>> m @ x # Compute the DFT of x
|
| 901 |
+
array([ 9. +0.j , 0.12-0.81j, -2.12+3.44j, -2.12-3.44j, 0.12+0.81j])
|
| 902 |
+
|
| 903 |
+
Verify that ``m @ x`` is the same as ``fft(x)``.
|
| 904 |
+
|
| 905 |
+
>>> from scipy.fft import fft
|
| 906 |
+
>>> fft(x) # Same result as m @ x
|
| 907 |
+
array([ 9. +0.j , 0.12-0.81j, -2.12+3.44j, -2.12-3.44j, 0.12+0.81j])
|
| 908 |
+
"""
|
| 909 |
+
if scale not in [None, 'sqrtn', 'n']:
|
| 910 |
+
raise ValueError("scale must be None, 'sqrtn', or 'n'; "
|
| 911 |
+
f"{scale!r} is not valid.")
|
| 912 |
+
|
| 913 |
+
omegas = np.exp(-2j * np.pi * np.arange(n) / n).reshape(-1, 1)
|
| 914 |
+
m = omegas ** np.arange(n)
|
| 915 |
+
if scale == 'sqrtn':
|
| 916 |
+
m /= math.sqrt(n)
|
| 917 |
+
elif scale == 'n':
|
| 918 |
+
m /= n
|
| 919 |
+
return m
|
| 920 |
+
|
| 921 |
+
|
| 922 |
+
def fiedler(a):
|
| 923 |
+
"""Returns a symmetric Fiedler matrix
|
| 924 |
+
|
| 925 |
+
Given an sequence of numbers `a`, Fiedler matrices have the structure
|
| 926 |
+
``F[i, j] = np.abs(a[i] - a[j])``, and hence zero diagonals and nonnegative
|
| 927 |
+
entries. A Fiedler matrix has a dominant positive eigenvalue and other
|
| 928 |
+
eigenvalues are negative. Although not valid generally, for certain inputs,
|
| 929 |
+
the inverse and the determinant can be derived explicitly as given in [1]_.
|
| 930 |
+
|
| 931 |
+
Parameters
|
| 932 |
+
----------
|
| 933 |
+
a : (n,) array_like
|
| 934 |
+
coefficient array
|
| 935 |
+
|
| 936 |
+
Returns
|
| 937 |
+
-------
|
| 938 |
+
F : (n, n) ndarray
|
| 939 |
+
|
| 940 |
+
See Also
|
| 941 |
+
--------
|
| 942 |
+
circulant, toeplitz
|
| 943 |
+
|
| 944 |
+
Notes
|
| 945 |
+
-----
|
| 946 |
+
|
| 947 |
+
.. versionadded:: 1.3.0
|
| 948 |
+
|
| 949 |
+
References
|
| 950 |
+
----------
|
| 951 |
+
.. [1] J. Todd, "Basic Numerical Mathematics: Vol.2 : Numerical Algebra",
|
| 952 |
+
1977, Birkhauser, :doi:`10.1007/978-3-0348-7286-7`
|
| 953 |
+
|
| 954 |
+
Examples
|
| 955 |
+
--------
|
| 956 |
+
>>> import numpy as np
|
| 957 |
+
>>> from scipy.linalg import det, inv, fiedler
|
| 958 |
+
>>> a = [1, 4, 12, 45, 77]
|
| 959 |
+
>>> n = len(a)
|
| 960 |
+
>>> A = fiedler(a)
|
| 961 |
+
>>> A
|
| 962 |
+
array([[ 0, 3, 11, 44, 76],
|
| 963 |
+
[ 3, 0, 8, 41, 73],
|
| 964 |
+
[11, 8, 0, 33, 65],
|
| 965 |
+
[44, 41, 33, 0, 32],
|
| 966 |
+
[76, 73, 65, 32, 0]])
|
| 967 |
+
|
| 968 |
+
The explicit formulas for determinant and inverse seem to hold only for
|
| 969 |
+
monotonically increasing/decreasing arrays. Note the tridiagonal structure
|
| 970 |
+
and the corners.
|
| 971 |
+
|
| 972 |
+
>>> Ai = inv(A)
|
| 973 |
+
>>> Ai[np.abs(Ai) < 1e-12] = 0. # cleanup the numerical noise for display
|
| 974 |
+
>>> Ai
|
| 975 |
+
array([[-0.16008772, 0.16666667, 0. , 0. , 0.00657895],
|
| 976 |
+
[ 0.16666667, -0.22916667, 0.0625 , 0. , 0. ],
|
| 977 |
+
[ 0. , 0.0625 , -0.07765152, 0.01515152, 0. ],
|
| 978 |
+
[ 0. , 0. , 0.01515152, -0.03077652, 0.015625 ],
|
| 979 |
+
[ 0.00657895, 0. , 0. , 0.015625 , -0.00904605]])
|
| 980 |
+
>>> det(A)
|
| 981 |
+
15409151.999999998
|
| 982 |
+
>>> (-1)**(n-1) * 2**(n-2) * np.diff(a).prod() * (a[-1] - a[0])
|
| 983 |
+
15409152
|
| 984 |
+
|
| 985 |
+
"""
|
| 986 |
+
a = np.atleast_1d(a)
|
| 987 |
+
|
| 988 |
+
if a.ndim != 1:
|
| 989 |
+
raise ValueError("Input 'a' must be a 1D array.")
|
| 990 |
+
|
| 991 |
+
if a.size == 0:
|
| 992 |
+
return np.array([], dtype=float)
|
| 993 |
+
elif a.size == 1:
|
| 994 |
+
return np.array([[0.]])
|
| 995 |
+
else:
|
| 996 |
+
return np.abs(a[:, None] - a)
|
| 997 |
+
|
| 998 |
+
|
| 999 |
+
def fiedler_companion(a):
|
| 1000 |
+
""" Returns a Fiedler companion matrix
|
| 1001 |
+
|
| 1002 |
+
Given a polynomial coefficient array ``a``, this function forms a
|
| 1003 |
+
pentadiagonal matrix with a special structure whose eigenvalues coincides
|
| 1004 |
+
with the roots of ``a``.
|
| 1005 |
+
|
| 1006 |
+
Parameters
|
| 1007 |
+
----------
|
| 1008 |
+
a : (N,) array_like
|
| 1009 |
+
1-D array of polynomial coefficients in descending order with a nonzero
|
| 1010 |
+
leading coefficient. For ``N < 2``, an empty array is returned.
|
| 1011 |
+
|
| 1012 |
+
Returns
|
| 1013 |
+
-------
|
| 1014 |
+
c : (N-1, N-1) ndarray
|
| 1015 |
+
Resulting companion matrix
|
| 1016 |
+
|
| 1017 |
+
See Also
|
| 1018 |
+
--------
|
| 1019 |
+
companion
|
| 1020 |
+
|
| 1021 |
+
Notes
|
| 1022 |
+
-----
|
| 1023 |
+
Similar to `companion` the leading coefficient should be nonzero. In the case
|
| 1024 |
+
the leading coefficient is not 1, other coefficients are rescaled before
|
| 1025 |
+
the array generation. To avoid numerical issues, it is best to provide a
|
| 1026 |
+
monic polynomial.
|
| 1027 |
+
|
| 1028 |
+
.. versionadded:: 1.3.0
|
| 1029 |
+
|
| 1030 |
+
References
|
| 1031 |
+
----------
|
| 1032 |
+
.. [1] M. Fiedler, " A note on companion matrices", Linear Algebra and its
|
| 1033 |
+
Applications, 2003, :doi:`10.1016/S0024-3795(03)00548-2`
|
| 1034 |
+
|
| 1035 |
+
Examples
|
| 1036 |
+
--------
|
| 1037 |
+
>>> import numpy as np
|
| 1038 |
+
>>> from scipy.linalg import fiedler_companion, eigvals
|
| 1039 |
+
>>> p = np.poly(np.arange(1, 9, 2)) # [1., -16., 86., -176., 105.]
|
| 1040 |
+
>>> fc = fiedler_companion(p)
|
| 1041 |
+
>>> fc
|
| 1042 |
+
array([[ 16., -86., 1., 0.],
|
| 1043 |
+
[ 1., 0., 0., 0.],
|
| 1044 |
+
[ 0., 176., 0., -105.],
|
| 1045 |
+
[ 0., 1., 0., 0.]])
|
| 1046 |
+
>>> eigvals(fc)
|
| 1047 |
+
array([7.+0.j, 5.+0.j, 3.+0.j, 1.+0.j])
|
| 1048 |
+
|
| 1049 |
+
"""
|
| 1050 |
+
a = np.atleast_1d(a)
|
| 1051 |
+
|
| 1052 |
+
if a.ndim != 1:
|
| 1053 |
+
raise ValueError("Input 'a' must be a 1-D array.")
|
| 1054 |
+
|
| 1055 |
+
if a.size <= 2:
|
| 1056 |
+
if a.size == 2:
|
| 1057 |
+
return np.array([[-(a/a[0])[-1]]])
|
| 1058 |
+
return np.array([], dtype=a.dtype)
|
| 1059 |
+
|
| 1060 |
+
if a[0] == 0.:
|
| 1061 |
+
raise ValueError('Leading coefficient is zero.')
|
| 1062 |
+
|
| 1063 |
+
a = a/a[0]
|
| 1064 |
+
n = a.size - 1
|
| 1065 |
+
c = np.zeros((n, n), dtype=a.dtype)
|
| 1066 |
+
# subdiagonals
|
| 1067 |
+
c[range(3, n, 2), range(1, n-2, 2)] = 1.
|
| 1068 |
+
c[range(2, n, 2), range(1, n-1, 2)] = -a[3::2]
|
| 1069 |
+
# superdiagonals
|
| 1070 |
+
c[range(0, n-2, 2), range(2, n, 2)] = 1.
|
| 1071 |
+
c[range(0, n-1, 2), range(1, n, 2)] = -a[2::2]
|
| 1072 |
+
c[[0, 1], 0] = [-a[1], 1]
|
| 1073 |
+
|
| 1074 |
+
return c
|
| 1075 |
+
|
| 1076 |
+
|
| 1077 |
+
def convolution_matrix(a, n, mode='full'):
|
| 1078 |
+
"""
|
| 1079 |
+
Construct a convolution matrix.
|
| 1080 |
+
|
| 1081 |
+
Constructs the Toeplitz matrix representing one-dimensional
|
| 1082 |
+
convolution [1]_. See the notes below for details.
|
| 1083 |
+
|
| 1084 |
+
Parameters
|
| 1085 |
+
----------
|
| 1086 |
+
a : (m,) array_like
|
| 1087 |
+
The 1-D array to convolve.
|
| 1088 |
+
n : int
|
| 1089 |
+
The number of columns in the resulting matrix. It gives the length
|
| 1090 |
+
of the input to be convolved with `a`. This is analogous to the
|
| 1091 |
+
length of `v` in ``numpy.convolve(a, v)``.
|
| 1092 |
+
mode : str
|
| 1093 |
+
This is analogous to `mode` in ``numpy.convolve(v, a, mode)``.
|
| 1094 |
+
It must be one of ('full', 'valid', 'same').
|
| 1095 |
+
See below for how `mode` determines the shape of the result.
|
| 1096 |
+
|
| 1097 |
+
Returns
|
| 1098 |
+
-------
|
| 1099 |
+
A : (k, n) ndarray
|
| 1100 |
+
The convolution matrix whose row count `k` depends on `mode`::
|
| 1101 |
+
|
| 1102 |
+
======= =========================
|
| 1103 |
+
mode k
|
| 1104 |
+
======= =========================
|
| 1105 |
+
'full' m + n -1
|
| 1106 |
+
'same' max(m, n)
|
| 1107 |
+
'valid' max(m, n) - min(m, n) + 1
|
| 1108 |
+
======= =========================
|
| 1109 |
+
|
| 1110 |
+
See Also
|
| 1111 |
+
--------
|
| 1112 |
+
toeplitz : Toeplitz matrix
|
| 1113 |
+
|
| 1114 |
+
Notes
|
| 1115 |
+
-----
|
| 1116 |
+
The code::
|
| 1117 |
+
|
| 1118 |
+
A = convolution_matrix(a, n, mode)
|
| 1119 |
+
|
| 1120 |
+
creates a Toeplitz matrix `A` such that ``A @ v`` is equivalent to
|
| 1121 |
+
using ``convolve(a, v, mode)``. The returned array always has `n`
|
| 1122 |
+
columns. The number of rows depends on the specified `mode`, as
|
| 1123 |
+
explained above.
|
| 1124 |
+
|
| 1125 |
+
In the default 'full' mode, the entries of `A` are given by::
|
| 1126 |
+
|
| 1127 |
+
A[i, j] == (a[i-j] if (0 <= (i-j) < m) else 0)
|
| 1128 |
+
|
| 1129 |
+
where ``m = len(a)``. Suppose, for example, the input array is
|
| 1130 |
+
``[x, y, z]``. The convolution matrix has the form::
|
| 1131 |
+
|
| 1132 |
+
[x, 0, 0, ..., 0, 0]
|
| 1133 |
+
[y, x, 0, ..., 0, 0]
|
| 1134 |
+
[z, y, x, ..., 0, 0]
|
| 1135 |
+
...
|
| 1136 |
+
[0, 0, 0, ..., x, 0]
|
| 1137 |
+
[0, 0, 0, ..., y, x]
|
| 1138 |
+
[0, 0, 0, ..., z, y]
|
| 1139 |
+
[0, 0, 0, ..., 0, z]
|
| 1140 |
+
|
| 1141 |
+
In 'valid' mode, the entries of `A` are given by::
|
| 1142 |
+
|
| 1143 |
+
A[i, j] == (a[i-j+m-1] if (0 <= (i-j+m-1) < m) else 0)
|
| 1144 |
+
|
| 1145 |
+
This corresponds to a matrix whose rows are the subset of those from
|
| 1146 |
+
the 'full' case where all the coefficients in `a` are contained in the
|
| 1147 |
+
row. For input ``[x, y, z]``, this array looks like::
|
| 1148 |
+
|
| 1149 |
+
[z, y, x, 0, 0, ..., 0, 0, 0]
|
| 1150 |
+
[0, z, y, x, 0, ..., 0, 0, 0]
|
| 1151 |
+
[0, 0, z, y, x, ..., 0, 0, 0]
|
| 1152 |
+
...
|
| 1153 |
+
[0, 0, 0, 0, 0, ..., x, 0, 0]
|
| 1154 |
+
[0, 0, 0, 0, 0, ..., y, x, 0]
|
| 1155 |
+
[0, 0, 0, 0, 0, ..., z, y, x]
|
| 1156 |
+
|
| 1157 |
+
In the 'same' mode, the entries of `A` are given by::
|
| 1158 |
+
|
| 1159 |
+
d = (m - 1) // 2
|
| 1160 |
+
A[i, j] == (a[i-j+d] if (0 <= (i-j+d) < m) else 0)
|
| 1161 |
+
|
| 1162 |
+
The typical application of the 'same' mode is when one has a signal of
|
| 1163 |
+
length `n` (with `n` greater than ``len(a)``), and the desired output
|
| 1164 |
+
is a filtered signal that is still of length `n`.
|
| 1165 |
+
|
| 1166 |
+
For input ``[x, y, z]``, this array looks like::
|
| 1167 |
+
|
| 1168 |
+
[y, x, 0, 0, ..., 0, 0, 0]
|
| 1169 |
+
[z, y, x, 0, ..., 0, 0, 0]
|
| 1170 |
+
[0, z, y, x, ..., 0, 0, 0]
|
| 1171 |
+
[0, 0, z, y, ..., 0, 0, 0]
|
| 1172 |
+
...
|
| 1173 |
+
[0, 0, 0, 0, ..., y, x, 0]
|
| 1174 |
+
[0, 0, 0, 0, ..., z, y, x]
|
| 1175 |
+
[0, 0, 0, 0, ..., 0, z, y]
|
| 1176 |
+
|
| 1177 |
+
.. versionadded:: 1.5.0
|
| 1178 |
+
|
| 1179 |
+
References
|
| 1180 |
+
----------
|
| 1181 |
+
.. [1] "Convolution", https://en.wikipedia.org/wiki/Convolution
|
| 1182 |
+
|
| 1183 |
+
Examples
|
| 1184 |
+
--------
|
| 1185 |
+
>>> import numpy as np
|
| 1186 |
+
>>> from scipy.linalg import convolution_matrix
|
| 1187 |
+
>>> A = convolution_matrix([-1, 4, -2], 5, mode='same')
|
| 1188 |
+
>>> A
|
| 1189 |
+
array([[ 4, -1, 0, 0, 0],
|
| 1190 |
+
[-2, 4, -1, 0, 0],
|
| 1191 |
+
[ 0, -2, 4, -1, 0],
|
| 1192 |
+
[ 0, 0, -2, 4, -1],
|
| 1193 |
+
[ 0, 0, 0, -2, 4]])
|
| 1194 |
+
|
| 1195 |
+
Compare multiplication by `A` with the use of `numpy.convolve`.
|
| 1196 |
+
|
| 1197 |
+
>>> x = np.array([1, 2, 0, -3, 0.5])
|
| 1198 |
+
>>> A @ x
|
| 1199 |
+
array([ 2. , 6. , -1. , -12.5, 8. ])
|
| 1200 |
+
|
| 1201 |
+
Verify that ``A @ x`` produced the same result as applying the
|
| 1202 |
+
convolution function.
|
| 1203 |
+
|
| 1204 |
+
>>> np.convolve([-1, 4, -2], x, mode='same')
|
| 1205 |
+
array([ 2. , 6. , -1. , -12.5, 8. ])
|
| 1206 |
+
|
| 1207 |
+
For comparison to the case ``mode='same'`` shown above, here are the
|
| 1208 |
+
matrices produced by ``mode='full'`` and ``mode='valid'`` for the
|
| 1209 |
+
same coefficients and size.
|
| 1210 |
+
|
| 1211 |
+
>>> convolution_matrix([-1, 4, -2], 5, mode='full')
|
| 1212 |
+
array([[-1, 0, 0, 0, 0],
|
| 1213 |
+
[ 4, -1, 0, 0, 0],
|
| 1214 |
+
[-2, 4, -1, 0, 0],
|
| 1215 |
+
[ 0, -2, 4, -1, 0],
|
| 1216 |
+
[ 0, 0, -2, 4, -1],
|
| 1217 |
+
[ 0, 0, 0, -2, 4],
|
| 1218 |
+
[ 0, 0, 0, 0, -2]])
|
| 1219 |
+
|
| 1220 |
+
>>> convolution_matrix([-1, 4, -2], 5, mode='valid')
|
| 1221 |
+
array([[-2, 4, -1, 0, 0],
|
| 1222 |
+
[ 0, -2, 4, -1, 0],
|
| 1223 |
+
[ 0, 0, -2, 4, -1]])
|
| 1224 |
+
"""
|
| 1225 |
+
if n <= 0:
|
| 1226 |
+
raise ValueError('n must be a positive integer.')
|
| 1227 |
+
|
| 1228 |
+
a = np.asarray(a)
|
| 1229 |
+
if a.ndim != 1:
|
| 1230 |
+
raise ValueError('convolution_matrix expects a one-dimensional '
|
| 1231 |
+
'array as input')
|
| 1232 |
+
if a.size == 0:
|
| 1233 |
+
raise ValueError('len(a) must be at least 1.')
|
| 1234 |
+
|
| 1235 |
+
if mode not in ('full', 'valid', 'same'):
|
| 1236 |
+
raise ValueError(
|
| 1237 |
+
"'mode' argument must be one of ('full', 'valid', 'same')")
|
| 1238 |
+
|
| 1239 |
+
# create zero padded versions of the array
|
| 1240 |
+
az = np.pad(a, (0, n-1), 'constant')
|
| 1241 |
+
raz = np.pad(a[::-1], (0, n-1), 'constant')
|
| 1242 |
+
|
| 1243 |
+
if mode == 'same':
|
| 1244 |
+
trim = min(n, len(a)) - 1
|
| 1245 |
+
tb = trim//2
|
| 1246 |
+
te = trim - tb
|
| 1247 |
+
col0 = az[tb:len(az)-te]
|
| 1248 |
+
row0 = raz[-n-tb:len(raz)-tb]
|
| 1249 |
+
elif mode == 'valid':
|
| 1250 |
+
tb = min(n, len(a)) - 1
|
| 1251 |
+
te = tb
|
| 1252 |
+
col0 = az[tb:len(az)-te]
|
| 1253 |
+
row0 = raz[-n-tb:len(raz)-tb]
|
| 1254 |
+
else: # 'full'
|
| 1255 |
+
col0 = az
|
| 1256 |
+
row0 = raz[-n:]
|
| 1257 |
+
return toeplitz(col0, row0)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_testutils.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class _FakeMatrix:
|
| 5 |
+
def __init__(self, data):
|
| 6 |
+
self._data = data
|
| 7 |
+
self.__array_interface__ = data.__array_interface__
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class _FakeMatrix2:
|
| 11 |
+
def __init__(self, data):
|
| 12 |
+
self._data = data
|
| 13 |
+
|
| 14 |
+
def __array__(self, dtype=None, copy=None):
|
| 15 |
+
if copy:
|
| 16 |
+
return self._data.copy()
|
| 17 |
+
return self._data
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def _get_array(shape, dtype):
|
| 21 |
+
"""
|
| 22 |
+
Get a test array of given shape and data type.
|
| 23 |
+
Returned NxN matrices are posdef, and 2xN are banded-posdef.
|
| 24 |
+
|
| 25 |
+
"""
|
| 26 |
+
if len(shape) == 2 and shape[0] == 2:
|
| 27 |
+
# yield a banded positive definite one
|
| 28 |
+
x = np.zeros(shape, dtype=dtype)
|
| 29 |
+
x[0, 1:] = -1
|
| 30 |
+
x[1] = 2
|
| 31 |
+
return x
|
| 32 |
+
elif len(shape) == 2 and shape[0] == shape[1]:
|
| 33 |
+
# always yield a positive definite matrix
|
| 34 |
+
x = np.zeros(shape, dtype=dtype)
|
| 35 |
+
j = np.arange(shape[0])
|
| 36 |
+
x[j, j] = 2
|
| 37 |
+
x[j[:-1], j[:-1]+1] = -1
|
| 38 |
+
x[j[:-1]+1, j[:-1]] = -1
|
| 39 |
+
return x
|
| 40 |
+
else:
|
| 41 |
+
np.random.seed(1234)
|
| 42 |
+
return np.random.randn(*shape).astype(dtype)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _id(x):
|
| 46 |
+
return x
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def assert_no_overwrite(call, shapes, dtypes=None):
|
| 50 |
+
"""
|
| 51 |
+
Test that a call does not overwrite its input arguments
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
if dtypes is None:
|
| 55 |
+
dtypes = [np.float32, np.float64, np.complex64, np.complex128]
|
| 56 |
+
|
| 57 |
+
for dtype in dtypes:
|
| 58 |
+
for order in ["C", "F"]:
|
| 59 |
+
for faker in [_id, _FakeMatrix, _FakeMatrix2]:
|
| 60 |
+
orig_inputs = [_get_array(s, dtype) for s in shapes]
|
| 61 |
+
inputs = [faker(x.copy(order)) for x in orig_inputs]
|
| 62 |
+
call(*inputs)
|
| 63 |
+
msg = f"call modified inputs [{dtype!r}, {faker!r}]"
|
| 64 |
+
for a, b in zip(inputs, orig_inputs):
|
| 65 |
+
np.testing.assert_equal(a, b, err_msg=msg)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/basic.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
|
| 10 |
+
'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
|
| 11 |
+
'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz',
|
| 12 |
+
'atleast_1d', 'atleast_2d', 'get_lapack_funcs',
|
| 13 |
+
'LinAlgError', 'LinAlgWarning', 'levinson',
|
| 14 |
+
]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def __dir__():
|
| 18 |
+
return __all__
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def __getattr__(name):
|
| 22 |
+
return _sub_module_deprecation(sub_package="linalg", module="basic",
|
| 23 |
+
private_modules=["_basic"], all=__all__,
|
| 24 |
+
attribute=name)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/blas.py
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Low-level BLAS functions (:mod:`scipy.linalg.blas`)
|
| 3 |
+
===================================================
|
| 4 |
+
|
| 5 |
+
This module contains low-level functions from the BLAS library.
|
| 6 |
+
|
| 7 |
+
.. versionadded:: 0.12.0
|
| 8 |
+
|
| 9 |
+
.. note::
|
| 10 |
+
|
| 11 |
+
The common ``overwrite_<>`` option in many routines, allows the
|
| 12 |
+
input arrays to be overwritten to avoid extra memory allocation.
|
| 13 |
+
However this requires the array to satisfy two conditions
|
| 14 |
+
which are memory order and the data type to match exactly the
|
| 15 |
+
order and the type expected by the routine.
|
| 16 |
+
|
| 17 |
+
As an example, if you pass a double precision float array to any
|
| 18 |
+
``S....`` routine which expects single precision arguments, f2py
|
| 19 |
+
will create an intermediate array to match the argument types and
|
| 20 |
+
overwriting will be performed on that intermediate array.
|
| 21 |
+
|
| 22 |
+
Similarly, if a C-contiguous array is passed, f2py will pass a
|
| 23 |
+
FORTRAN-contiguous array internally. Please make sure that these
|
| 24 |
+
details are satisfied. More information can be found in the f2py
|
| 25 |
+
documentation.
|
| 26 |
+
|
| 27 |
+
.. warning::
|
| 28 |
+
|
| 29 |
+
These functions do little to no error checking.
|
| 30 |
+
It is possible to cause crashes by mis-using them,
|
| 31 |
+
so prefer using the higher-level routines in `scipy.linalg`.
|
| 32 |
+
|
| 33 |
+
Finding functions
|
| 34 |
+
-----------------
|
| 35 |
+
|
| 36 |
+
.. autosummary::
|
| 37 |
+
:toctree: generated/
|
| 38 |
+
|
| 39 |
+
get_blas_funcs
|
| 40 |
+
find_best_blas_type
|
| 41 |
+
|
| 42 |
+
BLAS Level 1 functions
|
| 43 |
+
----------------------
|
| 44 |
+
|
| 45 |
+
.. autosummary::
|
| 46 |
+
:toctree: generated/
|
| 47 |
+
|
| 48 |
+
caxpy
|
| 49 |
+
ccopy
|
| 50 |
+
cdotc
|
| 51 |
+
cdotu
|
| 52 |
+
crotg
|
| 53 |
+
cscal
|
| 54 |
+
csrot
|
| 55 |
+
csscal
|
| 56 |
+
cswap
|
| 57 |
+
dasum
|
| 58 |
+
daxpy
|
| 59 |
+
dcopy
|
| 60 |
+
ddot
|
| 61 |
+
dnrm2
|
| 62 |
+
drot
|
| 63 |
+
drotg
|
| 64 |
+
drotm
|
| 65 |
+
drotmg
|
| 66 |
+
dscal
|
| 67 |
+
dswap
|
| 68 |
+
dzasum
|
| 69 |
+
dznrm2
|
| 70 |
+
icamax
|
| 71 |
+
idamax
|
| 72 |
+
isamax
|
| 73 |
+
izamax
|
| 74 |
+
sasum
|
| 75 |
+
saxpy
|
| 76 |
+
scasum
|
| 77 |
+
scnrm2
|
| 78 |
+
scopy
|
| 79 |
+
sdot
|
| 80 |
+
snrm2
|
| 81 |
+
srot
|
| 82 |
+
srotg
|
| 83 |
+
srotm
|
| 84 |
+
srotmg
|
| 85 |
+
sscal
|
| 86 |
+
sswap
|
| 87 |
+
zaxpy
|
| 88 |
+
zcopy
|
| 89 |
+
zdotc
|
| 90 |
+
zdotu
|
| 91 |
+
zdrot
|
| 92 |
+
zdscal
|
| 93 |
+
zrotg
|
| 94 |
+
zscal
|
| 95 |
+
zswap
|
| 96 |
+
|
| 97 |
+
BLAS Level 2 functions
|
| 98 |
+
----------------------
|
| 99 |
+
|
| 100 |
+
.. autosummary::
|
| 101 |
+
:toctree: generated/
|
| 102 |
+
|
| 103 |
+
sgbmv
|
| 104 |
+
sgemv
|
| 105 |
+
sger
|
| 106 |
+
ssbmv
|
| 107 |
+
sspr
|
| 108 |
+
sspr2
|
| 109 |
+
ssymv
|
| 110 |
+
ssyr
|
| 111 |
+
ssyr2
|
| 112 |
+
stbmv
|
| 113 |
+
stpsv
|
| 114 |
+
strmv
|
| 115 |
+
strsv
|
| 116 |
+
dgbmv
|
| 117 |
+
dgemv
|
| 118 |
+
dger
|
| 119 |
+
dsbmv
|
| 120 |
+
dspr
|
| 121 |
+
dspr2
|
| 122 |
+
dsymv
|
| 123 |
+
dsyr
|
| 124 |
+
dsyr2
|
| 125 |
+
dtbmv
|
| 126 |
+
dtpsv
|
| 127 |
+
dtrmv
|
| 128 |
+
dtrsv
|
| 129 |
+
cgbmv
|
| 130 |
+
cgemv
|
| 131 |
+
cgerc
|
| 132 |
+
cgeru
|
| 133 |
+
chbmv
|
| 134 |
+
chemv
|
| 135 |
+
cher
|
| 136 |
+
cher2
|
| 137 |
+
chpmv
|
| 138 |
+
chpr
|
| 139 |
+
chpr2
|
| 140 |
+
ctbmv
|
| 141 |
+
ctbsv
|
| 142 |
+
ctpmv
|
| 143 |
+
ctpsv
|
| 144 |
+
ctrmv
|
| 145 |
+
ctrsv
|
| 146 |
+
csyr
|
| 147 |
+
zgbmv
|
| 148 |
+
zgemv
|
| 149 |
+
zgerc
|
| 150 |
+
zgeru
|
| 151 |
+
zhbmv
|
| 152 |
+
zhemv
|
| 153 |
+
zher
|
| 154 |
+
zher2
|
| 155 |
+
zhpmv
|
| 156 |
+
zhpr
|
| 157 |
+
zhpr2
|
| 158 |
+
ztbmv
|
| 159 |
+
ztbsv
|
| 160 |
+
ztpmv
|
| 161 |
+
ztrmv
|
| 162 |
+
ztrsv
|
| 163 |
+
zsyr
|
| 164 |
+
|
| 165 |
+
BLAS Level 3 functions
|
| 166 |
+
----------------------
|
| 167 |
+
|
| 168 |
+
.. autosummary::
|
| 169 |
+
:toctree: generated/
|
| 170 |
+
|
| 171 |
+
sgemm
|
| 172 |
+
ssymm
|
| 173 |
+
ssyr2k
|
| 174 |
+
ssyrk
|
| 175 |
+
strmm
|
| 176 |
+
strsm
|
| 177 |
+
dgemm
|
| 178 |
+
dsymm
|
| 179 |
+
dsyr2k
|
| 180 |
+
dsyrk
|
| 181 |
+
dtrmm
|
| 182 |
+
dtrsm
|
| 183 |
+
cgemm
|
| 184 |
+
chemm
|
| 185 |
+
cher2k
|
| 186 |
+
cherk
|
| 187 |
+
csymm
|
| 188 |
+
csyr2k
|
| 189 |
+
csyrk
|
| 190 |
+
ctrmm
|
| 191 |
+
ctrsm
|
| 192 |
+
zgemm
|
| 193 |
+
zhemm
|
| 194 |
+
zher2k
|
| 195 |
+
zherk
|
| 196 |
+
zsymm
|
| 197 |
+
zsyr2k
|
| 198 |
+
zsyrk
|
| 199 |
+
ztrmm
|
| 200 |
+
ztrsm
|
| 201 |
+
|
| 202 |
+
"""
|
| 203 |
+
#
|
| 204 |
+
# Author: Pearu Peterson, March 2002
|
| 205 |
+
# refactoring by Fabian Pedregosa, March 2010
|
| 206 |
+
#
|
| 207 |
+
|
| 208 |
+
__all__ = ['get_blas_funcs', 'find_best_blas_type']
|
| 209 |
+
|
| 210 |
+
import numpy as _np
|
| 211 |
+
import functools
|
| 212 |
+
|
| 213 |
+
from scipy.linalg import _fblas
|
| 214 |
+
try:
|
| 215 |
+
from scipy.linalg import _cblas
|
| 216 |
+
except ImportError:
|
| 217 |
+
_cblas = None
|
| 218 |
+
|
| 219 |
+
try:
|
| 220 |
+
from scipy.linalg import _fblas_64
|
| 221 |
+
HAS_ILP64 = True
|
| 222 |
+
except ImportError:
|
| 223 |
+
HAS_ILP64 = False
|
| 224 |
+
_fblas_64 = None
|
| 225 |
+
|
| 226 |
+
# Expose all functions (only fblas --- cblas is an implementation detail)
|
| 227 |
+
empty_module = None
|
| 228 |
+
from scipy.linalg._fblas import * # noqa: E402, F403
|
| 229 |
+
del empty_module
|
| 230 |
+
|
| 231 |
+
# all numeric dtypes '?bBhHiIlLqQefdgFDGO' that are safe to be converted to
|
| 232 |
+
|
| 233 |
+
# single precision float : '?bBhH!!!!!!ef!!!!!!'
|
| 234 |
+
# double precision float : '?bBhHiIlLqQefdg!!!!'
|
| 235 |
+
# single precision complex : '?bBhH!!!!!!ef!!F!!!'
|
| 236 |
+
# double precision complex : '?bBhHiIlLqQefdgFDG!'
|
| 237 |
+
|
| 238 |
+
_type_score = {x: 1 for x in '?bBhHef'}
|
| 239 |
+
_type_score.update({x: 2 for x in 'iIlLqQd'})
|
| 240 |
+
|
| 241 |
+
# Handle float128(g) and complex256(G) separately in case non-Windows systems.
|
| 242 |
+
# On Windows, the values will be rewritten to the same key with the same value.
|
| 243 |
+
_type_score.update({'F': 3, 'D': 4, 'g': 2, 'G': 4})
|
| 244 |
+
|
| 245 |
+
# Final mapping to the actual prefixes and dtypes
|
| 246 |
+
_type_conv = {1: ('s', _np.dtype('float32')),
|
| 247 |
+
2: ('d', _np.dtype('float64')),
|
| 248 |
+
3: ('c', _np.dtype('complex64')),
|
| 249 |
+
4: ('z', _np.dtype('complex128'))}
|
| 250 |
+
|
| 251 |
+
# some convenience alias for complex functions
|
| 252 |
+
_blas_alias = {'cnrm2': 'scnrm2', 'znrm2': 'dznrm2',
|
| 253 |
+
'cdot': 'cdotc', 'zdot': 'zdotc',
|
| 254 |
+
'cger': 'cgerc', 'zger': 'zgerc',
|
| 255 |
+
'sdotc': 'sdot', 'sdotu': 'sdot',
|
| 256 |
+
'ddotc': 'ddot', 'ddotu': 'ddot'}
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def find_best_blas_type(arrays=(), dtype=None):
|
| 260 |
+
"""Find best-matching BLAS/LAPACK type.
|
| 261 |
+
|
| 262 |
+
Arrays are used to determine the optimal prefix of BLAS routines.
|
| 263 |
+
|
| 264 |
+
Parameters
|
| 265 |
+
----------
|
| 266 |
+
arrays : sequence of ndarrays, optional
|
| 267 |
+
Arrays can be given to determine optimal prefix of BLAS
|
| 268 |
+
routines. If not given, double-precision routines will be
|
| 269 |
+
used, otherwise the most generic type in arrays will be used.
|
| 270 |
+
dtype : str or dtype, optional
|
| 271 |
+
Data-type specifier. Not used if `arrays` is non-empty.
|
| 272 |
+
|
| 273 |
+
Returns
|
| 274 |
+
-------
|
| 275 |
+
prefix : str
|
| 276 |
+
BLAS/LAPACK prefix character.
|
| 277 |
+
dtype : dtype
|
| 278 |
+
Inferred Numpy data type.
|
| 279 |
+
prefer_fortran : bool
|
| 280 |
+
Whether to prefer Fortran order routines over C order.
|
| 281 |
+
|
| 282 |
+
Examples
|
| 283 |
+
--------
|
| 284 |
+
>>> import numpy as np
|
| 285 |
+
>>> import scipy.linalg.blas as bla
|
| 286 |
+
>>> rng = np.random.default_rng()
|
| 287 |
+
>>> a = rng.random((10,15))
|
| 288 |
+
>>> b = np.asfortranarray(a) # Change the memory layout order
|
| 289 |
+
>>> bla.find_best_blas_type((a,))
|
| 290 |
+
('d', dtype('float64'), False)
|
| 291 |
+
>>> bla.find_best_blas_type((a*1j,))
|
| 292 |
+
('z', dtype('complex128'), False)
|
| 293 |
+
>>> bla.find_best_blas_type((b,))
|
| 294 |
+
('d', dtype('float64'), True)
|
| 295 |
+
|
| 296 |
+
"""
|
| 297 |
+
dtype = _np.dtype(dtype)
|
| 298 |
+
max_score = _type_score.get(dtype.char, 5)
|
| 299 |
+
prefer_fortran = False
|
| 300 |
+
|
| 301 |
+
if arrays:
|
| 302 |
+
# In most cases, single element is passed through, quicker route
|
| 303 |
+
if len(arrays) == 1:
|
| 304 |
+
max_score = _type_score.get(arrays[0].dtype.char, 5)
|
| 305 |
+
prefer_fortran = arrays[0].flags['FORTRAN']
|
| 306 |
+
else:
|
| 307 |
+
# use the most generic type in arrays
|
| 308 |
+
scores = [_type_score.get(x.dtype.char, 5) for x in arrays]
|
| 309 |
+
max_score = max(scores)
|
| 310 |
+
ind_max_score = scores.index(max_score)
|
| 311 |
+
# safe upcasting for mix of float64 and complex64 --> prefix 'z'
|
| 312 |
+
if max_score == 3 and (2 in scores):
|
| 313 |
+
max_score = 4
|
| 314 |
+
|
| 315 |
+
if arrays[ind_max_score].flags['FORTRAN']:
|
| 316 |
+
# prefer Fortran for leading array with column major order
|
| 317 |
+
prefer_fortran = True
|
| 318 |
+
|
| 319 |
+
# Get the LAPACK prefix and the corresponding dtype if not fall back
|
| 320 |
+
# to 'd' and double precision float.
|
| 321 |
+
prefix, dtype = _type_conv.get(max_score, ('d', _np.dtype('float64')))
|
| 322 |
+
|
| 323 |
+
return prefix, dtype, prefer_fortran
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
def _get_funcs(names, arrays, dtype,
|
| 327 |
+
lib_name, fmodule, cmodule,
|
| 328 |
+
fmodule_name, cmodule_name, alias,
|
| 329 |
+
ilp64=False):
|
| 330 |
+
"""
|
| 331 |
+
Return available BLAS/LAPACK functions.
|
| 332 |
+
|
| 333 |
+
Used also in lapack.py. See get_blas_funcs for docstring.
|
| 334 |
+
"""
|
| 335 |
+
|
| 336 |
+
funcs = []
|
| 337 |
+
unpack = False
|
| 338 |
+
dtype = _np.dtype(dtype)
|
| 339 |
+
module1 = (cmodule, cmodule_name)
|
| 340 |
+
module2 = (fmodule, fmodule_name)
|
| 341 |
+
|
| 342 |
+
if isinstance(names, str):
|
| 343 |
+
names = (names,)
|
| 344 |
+
unpack = True
|
| 345 |
+
|
| 346 |
+
prefix, dtype, prefer_fortran = find_best_blas_type(arrays, dtype)
|
| 347 |
+
|
| 348 |
+
if prefer_fortran:
|
| 349 |
+
module1, module2 = module2, module1
|
| 350 |
+
|
| 351 |
+
for name in names:
|
| 352 |
+
func_name = prefix + name
|
| 353 |
+
func_name = alias.get(func_name, func_name)
|
| 354 |
+
func = getattr(module1[0], func_name, None)
|
| 355 |
+
module_name = module1[1]
|
| 356 |
+
if func is None:
|
| 357 |
+
func = getattr(module2[0], func_name, None)
|
| 358 |
+
module_name = module2[1]
|
| 359 |
+
if func is None:
|
| 360 |
+
raise ValueError(
|
| 361 |
+
f'{lib_name} function {func_name} could not be found')
|
| 362 |
+
func.module_name, func.typecode = module_name, prefix
|
| 363 |
+
func.dtype = dtype
|
| 364 |
+
if not ilp64:
|
| 365 |
+
func.int_dtype = _np.dtype(_np.intc)
|
| 366 |
+
else:
|
| 367 |
+
func.int_dtype = _np.dtype(_np.int64)
|
| 368 |
+
func.prefix = prefix # Backward compatibility
|
| 369 |
+
funcs.append(func)
|
| 370 |
+
|
| 371 |
+
if unpack:
|
| 372 |
+
return funcs[0]
|
| 373 |
+
else:
|
| 374 |
+
return funcs
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
def _memoize_get_funcs(func):
|
| 378 |
+
"""
|
| 379 |
+
Memoized fast path for _get_funcs instances
|
| 380 |
+
"""
|
| 381 |
+
memo = {}
|
| 382 |
+
func.memo = memo
|
| 383 |
+
|
| 384 |
+
@functools.wraps(func)
|
| 385 |
+
def getter(names, arrays=(), dtype=None, ilp64=False):
|
| 386 |
+
key = (names, dtype, ilp64)
|
| 387 |
+
for array in arrays:
|
| 388 |
+
# cf. find_blas_funcs
|
| 389 |
+
key += (array.dtype.char, array.flags.fortran)
|
| 390 |
+
|
| 391 |
+
try:
|
| 392 |
+
value = memo.get(key)
|
| 393 |
+
except TypeError:
|
| 394 |
+
# unhashable key etc.
|
| 395 |
+
key = None
|
| 396 |
+
value = None
|
| 397 |
+
|
| 398 |
+
if value is not None:
|
| 399 |
+
return value
|
| 400 |
+
|
| 401 |
+
value = func(names, arrays, dtype, ilp64)
|
| 402 |
+
|
| 403 |
+
if key is not None:
|
| 404 |
+
memo[key] = value
|
| 405 |
+
|
| 406 |
+
return value
|
| 407 |
+
|
| 408 |
+
return getter
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
@_memoize_get_funcs
|
| 412 |
+
def get_blas_funcs(names, arrays=(), dtype=None, ilp64=False):
|
| 413 |
+
"""Return available BLAS function objects from names.
|
| 414 |
+
|
| 415 |
+
Arrays are used to determine the optimal prefix of BLAS routines.
|
| 416 |
+
|
| 417 |
+
Parameters
|
| 418 |
+
----------
|
| 419 |
+
names : str or sequence of str
|
| 420 |
+
Name(s) of BLAS functions without type prefix.
|
| 421 |
+
|
| 422 |
+
arrays : sequence of ndarrays, optional
|
| 423 |
+
Arrays can be given to determine optimal prefix of BLAS
|
| 424 |
+
routines. If not given, double-precision routines will be
|
| 425 |
+
used, otherwise the most generic type in arrays will be used.
|
| 426 |
+
|
| 427 |
+
dtype : str or dtype, optional
|
| 428 |
+
Data-type specifier. Not used if `arrays` is non-empty.
|
| 429 |
+
|
| 430 |
+
ilp64 : {True, False, 'preferred'}, optional
|
| 431 |
+
Whether to return ILP64 routine variant.
|
| 432 |
+
Choosing 'preferred' returns ILP64 routine if available,
|
| 433 |
+
and otherwise the 32-bit routine. Default: False
|
| 434 |
+
|
| 435 |
+
Returns
|
| 436 |
+
-------
|
| 437 |
+
funcs : list
|
| 438 |
+
List containing the found function(s).
|
| 439 |
+
|
| 440 |
+
|
| 441 |
+
Notes
|
| 442 |
+
-----
|
| 443 |
+
This routine automatically chooses between Fortran/C
|
| 444 |
+
interfaces. Fortran code is used whenever possible for arrays with
|
| 445 |
+
column major order. In all other cases, C code is preferred.
|
| 446 |
+
|
| 447 |
+
In BLAS, the naming convention is that all functions start with a
|
| 448 |
+
type prefix, which depends on the type of the principal
|
| 449 |
+
matrix. These can be one of {'s', 'd', 'c', 'z'} for the NumPy
|
| 450 |
+
types {float32, float64, complex64, complex128} respectively.
|
| 451 |
+
The code and the dtype are stored in attributes `typecode` and `dtype`
|
| 452 |
+
of the returned functions.
|
| 453 |
+
|
| 454 |
+
Examples
|
| 455 |
+
--------
|
| 456 |
+
>>> import numpy as np
|
| 457 |
+
>>> import scipy.linalg as LA
|
| 458 |
+
>>> rng = np.random.default_rng()
|
| 459 |
+
>>> a = rng.random((3,2))
|
| 460 |
+
>>> x_gemv = LA.get_blas_funcs('gemv', (a,))
|
| 461 |
+
>>> x_gemv.typecode
|
| 462 |
+
'd'
|
| 463 |
+
>>> x_gemv = LA.get_blas_funcs('gemv',(a*1j,))
|
| 464 |
+
>>> x_gemv.typecode
|
| 465 |
+
'z'
|
| 466 |
+
|
| 467 |
+
"""
|
| 468 |
+
if isinstance(ilp64, str):
|
| 469 |
+
if ilp64 == 'preferred':
|
| 470 |
+
ilp64 = HAS_ILP64
|
| 471 |
+
else:
|
| 472 |
+
raise ValueError("Invalid value for 'ilp64'")
|
| 473 |
+
|
| 474 |
+
if not ilp64:
|
| 475 |
+
return _get_funcs(names, arrays, dtype,
|
| 476 |
+
"BLAS", _fblas, _cblas, "fblas", "cblas",
|
| 477 |
+
_blas_alias, ilp64=False)
|
| 478 |
+
else:
|
| 479 |
+
if not HAS_ILP64:
|
| 480 |
+
raise RuntimeError("BLAS ILP64 routine requested, but Scipy "
|
| 481 |
+
"compiled only with 32-bit BLAS")
|
| 482 |
+
return _get_funcs(names, arrays, dtype,
|
| 483 |
+
"BLAS", _fblas_64, None, "fblas_64", None,
|
| 484 |
+
_blas_alias, ilp64=True)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pxd
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This file was generated by _generate_pyx.py.
|
| 3 |
+
Do not edit this file directly.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
# Within scipy, these wrappers can be used via relative or absolute cimport.
|
| 7 |
+
# Examples:
|
| 8 |
+
# from ..linalg cimport cython_blas
|
| 9 |
+
# from scipy.linalg cimport cython_blas
|
| 10 |
+
# cimport scipy.linalg.cython_blas as cython_blas
|
| 11 |
+
# cimport ..linalg.cython_blas as cython_blas
|
| 12 |
+
|
| 13 |
+
# Within SciPy, if BLAS functions are needed in C/C++/Fortran,
|
| 14 |
+
# these wrappers should not be used.
|
| 15 |
+
# The original libraries should be linked directly.
|
| 16 |
+
|
| 17 |
+
ctypedef float s
|
| 18 |
+
ctypedef double d
|
| 19 |
+
ctypedef float complex c
|
| 20 |
+
ctypedef double complex z
|
| 21 |
+
|
| 22 |
+
cdef void caxpy(int *n, c *ca, c *cx, int *incx, c *cy, int *incy) noexcept nogil
|
| 23 |
+
cdef void ccopy(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
|
| 24 |
+
cdef c cdotc(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
|
| 25 |
+
cdef c cdotu(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
|
| 26 |
+
cdef void cgbmv(char *trans, int *m, int *n, int *kl, int *ku, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
|
| 27 |
+
cdef void cgemm(char *transa, char *transb, int *m, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
|
| 28 |
+
cdef void cgemv(char *trans, int *m, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
|
| 29 |
+
cdef void cgerc(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
|
| 30 |
+
cdef void cgeru(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
|
| 31 |
+
cdef void chbmv(char *uplo, int *n, int *k, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
|
| 32 |
+
cdef void chemm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
|
| 33 |
+
cdef void chemv(char *uplo, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
|
| 34 |
+
cdef void cher(char *uplo, int *n, s *alpha, c *x, int *incx, c *a, int *lda) noexcept nogil
|
| 35 |
+
cdef void cher2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
|
| 36 |
+
cdef void cher2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, s *beta, c *c, int *ldc) noexcept nogil
|
| 37 |
+
cdef void cherk(char *uplo, char *trans, int *n, int *k, s *alpha, c *a, int *lda, s *beta, c *c, int *ldc) noexcept nogil
|
| 38 |
+
cdef void chpmv(char *uplo, int *n, c *alpha, c *ap, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
|
| 39 |
+
cdef void chpr(char *uplo, int *n, s *alpha, c *x, int *incx, c *ap) noexcept nogil
|
| 40 |
+
cdef void chpr2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *ap) noexcept nogil
|
| 41 |
+
cdef void crotg(c *ca, c *cb, s *c, c *s) noexcept nogil
|
| 42 |
+
cdef void cscal(int *n, c *ca, c *cx, int *incx) noexcept nogil
|
| 43 |
+
cdef void csrot(int *n, c *cx, int *incx, c *cy, int *incy, s *c, s *s) noexcept nogil
|
| 44 |
+
cdef void csscal(int *n, s *sa, c *cx, int *incx) noexcept nogil
|
| 45 |
+
cdef void cswap(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
|
| 46 |
+
cdef void csymm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
|
| 47 |
+
cdef void csyr2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
|
| 48 |
+
cdef void csyrk(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *beta, c *c, int *ldc) noexcept nogil
|
| 49 |
+
cdef void ctbmv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil
|
| 50 |
+
cdef void ctbsv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil
|
| 51 |
+
cdef void ctpmv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil
|
| 52 |
+
cdef void ctpsv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil
|
| 53 |
+
cdef void ctrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil
|
| 54 |
+
cdef void ctrmv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil
|
| 55 |
+
cdef void ctrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil
|
| 56 |
+
cdef void ctrsv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil
|
| 57 |
+
cdef d dasum(int *n, d *dx, int *incx) noexcept nogil
|
| 58 |
+
cdef void daxpy(int *n, d *da, d *dx, int *incx, d *dy, int *incy) noexcept nogil
|
| 59 |
+
cdef d dcabs1(z *z) noexcept nogil
|
| 60 |
+
cdef void dcopy(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
|
| 61 |
+
cdef d ddot(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
|
| 62 |
+
cdef void dgbmv(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
|
| 63 |
+
cdef void dgemm(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
|
| 64 |
+
cdef void dgemv(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
|
| 65 |
+
cdef void dger(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil
|
| 66 |
+
cdef d dnrm2(int *n, d *x, int *incx) noexcept nogil
|
| 67 |
+
cdef void drot(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) noexcept nogil
|
| 68 |
+
cdef void drotg(d *da, d *db, d *c, d *s) noexcept nogil
|
| 69 |
+
cdef void drotm(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) noexcept nogil
|
| 70 |
+
cdef void drotmg(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) noexcept nogil
|
| 71 |
+
cdef void dsbmv(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
|
| 72 |
+
cdef void dscal(int *n, d *da, d *dx, int *incx) noexcept nogil
|
| 73 |
+
cdef d dsdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 74 |
+
cdef void dspmv(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
|
| 75 |
+
cdef void dspr(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) noexcept nogil
|
| 76 |
+
cdef void dspr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) noexcept nogil
|
| 77 |
+
cdef void dswap(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
|
| 78 |
+
cdef void dsymm(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
|
| 79 |
+
cdef void dsymv(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
|
| 80 |
+
cdef void dsyr(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) noexcept nogil
|
| 81 |
+
cdef void dsyr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil
|
| 82 |
+
cdef void dsyr2k(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
|
| 83 |
+
cdef void dsyrk(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) noexcept nogil
|
| 84 |
+
cdef void dtbmv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil
|
| 85 |
+
cdef void dtbsv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil
|
| 86 |
+
cdef void dtpmv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil
|
| 87 |
+
cdef void dtpsv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil
|
| 88 |
+
cdef void dtrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil
|
| 89 |
+
cdef void dtrmv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil
|
| 90 |
+
cdef void dtrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil
|
| 91 |
+
cdef void dtrsv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil
|
| 92 |
+
cdef d dzasum(int *n, z *zx, int *incx) noexcept nogil
|
| 93 |
+
cdef d dznrm2(int *n, z *x, int *incx) noexcept nogil
|
| 94 |
+
cdef int icamax(int *n, c *cx, int *incx) noexcept nogil
|
| 95 |
+
cdef int idamax(int *n, d *dx, int *incx) noexcept nogil
|
| 96 |
+
cdef int isamax(int *n, s *sx, int *incx) noexcept nogil
|
| 97 |
+
cdef int izamax(int *n, z *zx, int *incx) noexcept nogil
|
| 98 |
+
cdef bint lsame(char *ca, char *cb) noexcept nogil
|
| 99 |
+
cdef s sasum(int *n, s *sx, int *incx) noexcept nogil
|
| 100 |
+
cdef void saxpy(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 101 |
+
cdef s scasum(int *n, c *cx, int *incx) noexcept nogil
|
| 102 |
+
cdef s scnrm2(int *n, c *x, int *incx) noexcept nogil
|
| 103 |
+
cdef void scopy(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 104 |
+
cdef s sdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 105 |
+
cdef s sdsdot(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 106 |
+
cdef void sgbmv(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
|
| 107 |
+
cdef void sgemm(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
|
| 108 |
+
cdef void sgemv(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
|
| 109 |
+
cdef void sger(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil
|
| 110 |
+
cdef s snrm2(int *n, s *x, int *incx) noexcept nogil
|
| 111 |
+
cdef void srot(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) noexcept nogil
|
| 112 |
+
cdef void srotg(s *sa, s *sb, s *c, s *s) noexcept nogil
|
| 113 |
+
cdef void srotm(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) noexcept nogil
|
| 114 |
+
cdef void srotmg(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) noexcept nogil
|
| 115 |
+
cdef void ssbmv(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
|
| 116 |
+
cdef void sscal(int *n, s *sa, s *sx, int *incx) noexcept nogil
|
| 117 |
+
cdef void sspmv(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
|
| 118 |
+
cdef void sspr(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) noexcept nogil
|
| 119 |
+
cdef void sspr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) noexcept nogil
|
| 120 |
+
cdef void sswap(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
|
| 121 |
+
cdef void ssymm(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
|
| 122 |
+
cdef void ssymv(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
|
| 123 |
+
cdef void ssyr(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) noexcept nogil
|
| 124 |
+
cdef void ssyr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil
|
| 125 |
+
cdef void ssyr2k(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
|
| 126 |
+
cdef void ssyrk(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) noexcept nogil
|
| 127 |
+
cdef void stbmv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil
|
| 128 |
+
cdef void stbsv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil
|
| 129 |
+
cdef void stpmv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil
|
| 130 |
+
cdef void stpsv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil
|
| 131 |
+
cdef void strmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil
|
| 132 |
+
cdef void strmv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil
|
| 133 |
+
cdef void strsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil
|
| 134 |
+
cdef void strsv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil
|
| 135 |
+
cdef void zaxpy(int *n, z *za, z *zx, int *incx, z *zy, int *incy) noexcept nogil
|
| 136 |
+
cdef void zcopy(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
|
| 137 |
+
cdef z zdotc(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
|
| 138 |
+
cdef z zdotu(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
|
| 139 |
+
cdef void zdrot(int *n, z *cx, int *incx, z *cy, int *incy, d *c, d *s) noexcept nogil
|
| 140 |
+
cdef void zdscal(int *n, d *da, z *zx, int *incx) noexcept nogil
|
| 141 |
+
cdef void zgbmv(char *trans, int *m, int *n, int *kl, int *ku, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
|
| 142 |
+
cdef void zgemm(char *transa, char *transb, int *m, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
|
| 143 |
+
cdef void zgemv(char *trans, int *m, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
|
| 144 |
+
cdef void zgerc(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
|
| 145 |
+
cdef void zgeru(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
|
| 146 |
+
cdef void zhbmv(char *uplo, int *n, int *k, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
|
| 147 |
+
cdef void zhemm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
|
| 148 |
+
cdef void zhemv(char *uplo, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
|
| 149 |
+
cdef void zher(char *uplo, int *n, d *alpha, z *x, int *incx, z *a, int *lda) noexcept nogil
|
| 150 |
+
cdef void zher2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
|
| 151 |
+
cdef void zher2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, d *beta, z *c, int *ldc) noexcept nogil
|
| 152 |
+
cdef void zherk(char *uplo, char *trans, int *n, int *k, d *alpha, z *a, int *lda, d *beta, z *c, int *ldc) noexcept nogil
|
| 153 |
+
cdef void zhpmv(char *uplo, int *n, z *alpha, z *ap, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
|
| 154 |
+
cdef void zhpr(char *uplo, int *n, d *alpha, z *x, int *incx, z *ap) noexcept nogil
|
| 155 |
+
cdef void zhpr2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *ap) noexcept nogil
|
| 156 |
+
cdef void zrotg(z *ca, z *cb, d *c, z *s) noexcept nogil
|
| 157 |
+
cdef void zscal(int *n, z *za, z *zx, int *incx) noexcept nogil
|
| 158 |
+
cdef void zswap(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
|
| 159 |
+
cdef void zsymm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
|
| 160 |
+
cdef void zsyr2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
|
| 161 |
+
cdef void zsyrk(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *beta, z *c, int *ldc) noexcept nogil
|
| 162 |
+
cdef void ztbmv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil
|
| 163 |
+
cdef void ztbsv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil
|
| 164 |
+
cdef void ztpmv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil
|
| 165 |
+
cdef void ztpsv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil
|
| 166 |
+
cdef void ztrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil
|
| 167 |
+
cdef void ztrmv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil
|
| 168 |
+
cdef void ztrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil
|
| 169 |
+
cdef void ztrsv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pyx
ADDED
|
@@ -0,0 +1,1422 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file was generated by _generate_pyx.py.
|
| 2 |
+
# Do not edit this file directly.
|
| 3 |
+
# cython: boundscheck = False
|
| 4 |
+
# cython: wraparound = False
|
| 5 |
+
# cython: cdivision = True
|
| 6 |
+
|
| 7 |
+
"""
|
| 8 |
+
BLAS Functions for Cython
|
| 9 |
+
=========================
|
| 10 |
+
|
| 11 |
+
Usable from Cython via::
|
| 12 |
+
|
| 13 |
+
cimport scipy.linalg.cython_blas
|
| 14 |
+
|
| 15 |
+
These wrappers do not check for alignment of arrays.
|
| 16 |
+
Alignment should be checked before these wrappers are used.
|
| 17 |
+
|
| 18 |
+
Raw function pointers (Fortran-style pointer arguments):
|
| 19 |
+
|
| 20 |
+
- caxpy
|
| 21 |
+
- ccopy
|
| 22 |
+
- cdotc
|
| 23 |
+
- cdotu
|
| 24 |
+
- cgbmv
|
| 25 |
+
- cgemm
|
| 26 |
+
- cgemv
|
| 27 |
+
- cgerc
|
| 28 |
+
- cgeru
|
| 29 |
+
- chbmv
|
| 30 |
+
- chemm
|
| 31 |
+
- chemv
|
| 32 |
+
- cher
|
| 33 |
+
- cher2
|
| 34 |
+
- cher2k
|
| 35 |
+
- cherk
|
| 36 |
+
- chpmv
|
| 37 |
+
- chpr
|
| 38 |
+
- chpr2
|
| 39 |
+
- crotg
|
| 40 |
+
- cscal
|
| 41 |
+
- csrot
|
| 42 |
+
- csscal
|
| 43 |
+
- cswap
|
| 44 |
+
- csymm
|
| 45 |
+
- csyr2k
|
| 46 |
+
- csyrk
|
| 47 |
+
- ctbmv
|
| 48 |
+
- ctbsv
|
| 49 |
+
- ctpmv
|
| 50 |
+
- ctpsv
|
| 51 |
+
- ctrmm
|
| 52 |
+
- ctrmv
|
| 53 |
+
- ctrsm
|
| 54 |
+
- ctrsv
|
| 55 |
+
- dasum
|
| 56 |
+
- daxpy
|
| 57 |
+
- dcabs1
|
| 58 |
+
- dcopy
|
| 59 |
+
- ddot
|
| 60 |
+
- dgbmv
|
| 61 |
+
- dgemm
|
| 62 |
+
- dgemv
|
| 63 |
+
- dger
|
| 64 |
+
- dnrm2
|
| 65 |
+
- drot
|
| 66 |
+
- drotg
|
| 67 |
+
- drotm
|
| 68 |
+
- drotmg
|
| 69 |
+
- dsbmv
|
| 70 |
+
- dscal
|
| 71 |
+
- dsdot
|
| 72 |
+
- dspmv
|
| 73 |
+
- dspr
|
| 74 |
+
- dspr2
|
| 75 |
+
- dswap
|
| 76 |
+
- dsymm
|
| 77 |
+
- dsymv
|
| 78 |
+
- dsyr
|
| 79 |
+
- dsyr2
|
| 80 |
+
- dsyr2k
|
| 81 |
+
- dsyrk
|
| 82 |
+
- dtbmv
|
| 83 |
+
- dtbsv
|
| 84 |
+
- dtpmv
|
| 85 |
+
- dtpsv
|
| 86 |
+
- dtrmm
|
| 87 |
+
- dtrmv
|
| 88 |
+
- dtrsm
|
| 89 |
+
- dtrsv
|
| 90 |
+
- dzasum
|
| 91 |
+
- dznrm2
|
| 92 |
+
- icamax
|
| 93 |
+
- idamax
|
| 94 |
+
- isamax
|
| 95 |
+
- izamax
|
| 96 |
+
- lsame
|
| 97 |
+
- sasum
|
| 98 |
+
- saxpy
|
| 99 |
+
- scasum
|
| 100 |
+
- scnrm2
|
| 101 |
+
- scopy
|
| 102 |
+
- sdot
|
| 103 |
+
- sdsdot
|
| 104 |
+
- sgbmv
|
| 105 |
+
- sgemm
|
| 106 |
+
- sgemv
|
| 107 |
+
- sger
|
| 108 |
+
- snrm2
|
| 109 |
+
- srot
|
| 110 |
+
- srotg
|
| 111 |
+
- srotm
|
| 112 |
+
- srotmg
|
| 113 |
+
- ssbmv
|
| 114 |
+
- sscal
|
| 115 |
+
- sspmv
|
| 116 |
+
- sspr
|
| 117 |
+
- sspr2
|
| 118 |
+
- sswap
|
| 119 |
+
- ssymm
|
| 120 |
+
- ssymv
|
| 121 |
+
- ssyr
|
| 122 |
+
- ssyr2
|
| 123 |
+
- ssyr2k
|
| 124 |
+
- ssyrk
|
| 125 |
+
- stbmv
|
| 126 |
+
- stbsv
|
| 127 |
+
- stpmv
|
| 128 |
+
- stpsv
|
| 129 |
+
- strmm
|
| 130 |
+
- strmv
|
| 131 |
+
- strsm
|
| 132 |
+
- strsv
|
| 133 |
+
- zaxpy
|
| 134 |
+
- zcopy
|
| 135 |
+
- zdotc
|
| 136 |
+
- zdotu
|
| 137 |
+
- zdrot
|
| 138 |
+
- zdscal
|
| 139 |
+
- zgbmv
|
| 140 |
+
- zgemm
|
| 141 |
+
- zgemv
|
| 142 |
+
- zgerc
|
| 143 |
+
- zgeru
|
| 144 |
+
- zhbmv
|
| 145 |
+
- zhemm
|
| 146 |
+
- zhemv
|
| 147 |
+
- zher
|
| 148 |
+
- zher2
|
| 149 |
+
- zher2k
|
| 150 |
+
- zherk
|
| 151 |
+
- zhpmv
|
| 152 |
+
- zhpr
|
| 153 |
+
- zhpr2
|
| 154 |
+
- zrotg
|
| 155 |
+
- zscal
|
| 156 |
+
- zswap
|
| 157 |
+
- zsymm
|
| 158 |
+
- zsyr2k
|
| 159 |
+
- zsyrk
|
| 160 |
+
- ztbmv
|
| 161 |
+
- ztbsv
|
| 162 |
+
- ztpmv
|
| 163 |
+
- ztpsv
|
| 164 |
+
- ztrmm
|
| 165 |
+
- ztrmv
|
| 166 |
+
- ztrsm
|
| 167 |
+
- ztrsv
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
"""
|
| 171 |
+
|
| 172 |
+
# Within SciPy, these wrappers can be used via relative or absolute cimport.
|
| 173 |
+
# Examples:
|
| 174 |
+
# from ..linalg cimport cython_blas
|
| 175 |
+
# from scipy.linalg cimport cython_blas
|
| 176 |
+
# cimport scipy.linalg.cython_blas as cython_blas
|
| 177 |
+
# cimport ..linalg.cython_blas as cython_blas
|
| 178 |
+
|
| 179 |
+
# Within SciPy, if BLAS functions are needed in C/C++/Fortran,
|
| 180 |
+
# these wrappers should not be used.
|
| 181 |
+
# The original libraries should be linked directly.
|
| 182 |
+
|
| 183 |
+
cdef extern from "fortran_defs.h":
|
| 184 |
+
pass
|
| 185 |
+
|
| 186 |
+
from numpy cimport npy_complex64, npy_complex128
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
cdef extern from "_blas_subroutines.h":
|
| 190 |
+
void _fortran_caxpy "BLAS_FUNC(caxpy)"(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
|
| 191 |
+
cdef void caxpy(int *n, c *ca, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
|
| 192 |
+
|
| 193 |
+
_fortran_caxpy(n, <npy_complex64*>ca, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
cdef extern from "_blas_subroutines.h":
|
| 197 |
+
void _fortran_ccopy "BLAS_FUNC(ccopy)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
|
| 198 |
+
cdef void ccopy(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
|
| 199 |
+
|
| 200 |
+
_fortran_ccopy(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
cdef extern from "_blas_subroutines.h":
|
| 204 |
+
void _fortran_cdotc "(cdotcwrp_)"(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
|
| 205 |
+
cdef c cdotc(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
|
| 206 |
+
cdef c out
|
| 207 |
+
_fortran_cdotc(<npy_complex64*>&out, n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
|
| 208 |
+
return out
|
| 209 |
+
|
| 210 |
+
cdef extern from "_blas_subroutines.h":
|
| 211 |
+
void _fortran_cdotu "(cdotuwrp_)"(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
|
| 212 |
+
cdef c cdotu(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
|
| 213 |
+
cdef c out
|
| 214 |
+
_fortran_cdotu(<npy_complex64*>&out, n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
|
| 215 |
+
return out
|
| 216 |
+
|
| 217 |
+
cdef extern from "_blas_subroutines.h":
|
| 218 |
+
void _fortran_cgbmv "BLAS_FUNC(cgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
|
| 219 |
+
cdef void cgbmv(char *trans, int *m, int *n, int *kl, int *ku, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
|
| 220 |
+
|
| 221 |
+
_fortran_cgbmv(trans, m, n, kl, ku, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
cdef extern from "_blas_subroutines.h":
|
| 225 |
+
void _fortran_cgemm "BLAS_FUNC(cgemm)"(char *transa, char *transb, int *m, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
|
| 226 |
+
cdef void cgemm(char *transa, char *transb, int *m, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
|
| 227 |
+
|
| 228 |
+
_fortran_cgemm(transa, transb, m, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
cdef extern from "_blas_subroutines.h":
|
| 232 |
+
void _fortran_cgemv "BLAS_FUNC(cgemv)"(char *trans, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
|
| 233 |
+
cdef void cgemv(char *trans, int *m, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
|
| 234 |
+
|
| 235 |
+
_fortran_cgemv(trans, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
cdef extern from "_blas_subroutines.h":
|
| 239 |
+
void _fortran_cgerc "BLAS_FUNC(cgerc)"(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
|
| 240 |
+
cdef void cgerc(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
|
| 241 |
+
|
| 242 |
+
_fortran_cgerc(m, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
cdef extern from "_blas_subroutines.h":
|
| 246 |
+
void _fortran_cgeru "BLAS_FUNC(cgeru)"(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
|
| 247 |
+
cdef void cgeru(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
|
| 248 |
+
|
| 249 |
+
_fortran_cgeru(m, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
cdef extern from "_blas_subroutines.h":
|
| 253 |
+
void _fortran_chbmv "BLAS_FUNC(chbmv)"(char *uplo, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
|
| 254 |
+
cdef void chbmv(char *uplo, int *n, int *k, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
|
| 255 |
+
|
| 256 |
+
_fortran_chbmv(uplo, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
cdef extern from "_blas_subroutines.h":
|
| 260 |
+
void _fortran_chemm "BLAS_FUNC(chemm)"(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
|
| 261 |
+
cdef void chemm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
|
| 262 |
+
|
| 263 |
+
_fortran_chemm(side, uplo, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
cdef extern from "_blas_subroutines.h":
|
| 267 |
+
void _fortran_chemv "BLAS_FUNC(chemv)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
|
| 268 |
+
cdef void chemv(char *uplo, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
|
| 269 |
+
|
| 270 |
+
_fortran_chemv(uplo, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
cdef extern from "_blas_subroutines.h":
|
| 274 |
+
void _fortran_cher "BLAS_FUNC(cher)"(char *uplo, int *n, s *alpha, npy_complex64 *x, int *incx, npy_complex64 *a, int *lda) nogil
|
| 275 |
+
cdef void cher(char *uplo, int *n, s *alpha, c *x, int *incx, c *a, int *lda) noexcept nogil:
|
| 276 |
+
|
| 277 |
+
_fortran_cher(uplo, n, alpha, <npy_complex64*>x, incx, <npy_complex64*>a, lda)
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
cdef extern from "_blas_subroutines.h":
|
| 281 |
+
void _fortran_cher2 "BLAS_FUNC(cher2)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
|
| 282 |
+
cdef void cher2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
|
| 283 |
+
|
| 284 |
+
_fortran_cher2(uplo, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
cdef extern from "_blas_subroutines.h":
|
| 288 |
+
void _fortran_cher2k "BLAS_FUNC(cher2k)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, s *beta, npy_complex64 *c, int *ldc) nogil
|
| 289 |
+
cdef void cher2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, s *beta, c *c, int *ldc) noexcept nogil:
|
| 290 |
+
|
| 291 |
+
_fortran_cher2k(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, beta, <npy_complex64*>c, ldc)
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
cdef extern from "_blas_subroutines.h":
|
| 295 |
+
void _fortran_cherk "BLAS_FUNC(cherk)"(char *uplo, char *trans, int *n, int *k, s *alpha, npy_complex64 *a, int *lda, s *beta, npy_complex64 *c, int *ldc) nogil
|
| 296 |
+
cdef void cherk(char *uplo, char *trans, int *n, int *k, s *alpha, c *a, int *lda, s *beta, c *c, int *ldc) noexcept nogil:
|
| 297 |
+
|
| 298 |
+
_fortran_cherk(uplo, trans, n, k, alpha, <npy_complex64*>a, lda, beta, <npy_complex64*>c, ldc)
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
cdef extern from "_blas_subroutines.h":
|
| 302 |
+
void _fortran_chpmv "BLAS_FUNC(chpmv)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *ap, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
|
| 303 |
+
cdef void chpmv(char *uplo, int *n, c *alpha, c *ap, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
|
| 304 |
+
|
| 305 |
+
_fortran_chpmv(uplo, n, <npy_complex64*>alpha, <npy_complex64*>ap, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
cdef extern from "_blas_subroutines.h":
|
| 309 |
+
void _fortran_chpr "BLAS_FUNC(chpr)"(char *uplo, int *n, s *alpha, npy_complex64 *x, int *incx, npy_complex64 *ap) nogil
|
| 310 |
+
cdef void chpr(char *uplo, int *n, s *alpha, c *x, int *incx, c *ap) noexcept nogil:
|
| 311 |
+
|
| 312 |
+
_fortran_chpr(uplo, n, alpha, <npy_complex64*>x, incx, <npy_complex64*>ap)
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
cdef extern from "_blas_subroutines.h":
|
| 316 |
+
void _fortran_chpr2 "BLAS_FUNC(chpr2)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *ap) nogil
|
| 317 |
+
cdef void chpr2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *ap) noexcept nogil:
|
| 318 |
+
|
| 319 |
+
_fortran_chpr2(uplo, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>ap)
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
cdef extern from "_blas_subroutines.h":
|
| 323 |
+
void _fortran_crotg "BLAS_FUNC(crotg)"(npy_complex64 *ca, npy_complex64 *cb, s *c, npy_complex64 *s) nogil
|
| 324 |
+
cdef void crotg(c *ca, c *cb, s *c, c *s) noexcept nogil:
|
| 325 |
+
|
| 326 |
+
_fortran_crotg(<npy_complex64*>ca, <npy_complex64*>cb, c, <npy_complex64*>s)
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
cdef extern from "_blas_subroutines.h":
|
| 330 |
+
void _fortran_cscal "BLAS_FUNC(cscal)"(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx) nogil
|
| 331 |
+
cdef void cscal(int *n, c *ca, c *cx, int *incx) noexcept nogil:
|
| 332 |
+
|
| 333 |
+
_fortran_cscal(n, <npy_complex64*>ca, <npy_complex64*>cx, incx)
|
| 334 |
+
|
| 335 |
+
|
| 336 |
+
cdef extern from "_blas_subroutines.h":
|
| 337 |
+
void _fortran_csrot "BLAS_FUNC(csrot)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy, s *c, s *s) nogil
|
| 338 |
+
cdef void csrot(int *n, c *cx, int *incx, c *cy, int *incy, s *c, s *s) noexcept nogil:
|
| 339 |
+
|
| 340 |
+
_fortran_csrot(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy, c, s)
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
cdef extern from "_blas_subroutines.h":
|
| 344 |
+
void _fortran_csscal "BLAS_FUNC(csscal)"(int *n, s *sa, npy_complex64 *cx, int *incx) nogil
|
| 345 |
+
cdef void csscal(int *n, s *sa, c *cx, int *incx) noexcept nogil:
|
| 346 |
+
|
| 347 |
+
_fortran_csscal(n, sa, <npy_complex64*>cx, incx)
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
cdef extern from "_blas_subroutines.h":
|
| 351 |
+
void _fortran_cswap "BLAS_FUNC(cswap)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
|
| 352 |
+
cdef void cswap(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
|
| 353 |
+
|
| 354 |
+
_fortran_cswap(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
cdef extern from "_blas_subroutines.h":
|
| 358 |
+
void _fortran_csymm "BLAS_FUNC(csymm)"(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
|
| 359 |
+
cdef void csymm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
|
| 360 |
+
|
| 361 |
+
_fortran_csymm(side, uplo, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
cdef extern from "_blas_subroutines.h":
|
| 365 |
+
void _fortran_csyr2k "BLAS_FUNC(csyr2k)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
|
| 366 |
+
cdef void csyr2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
|
| 367 |
+
|
| 368 |
+
_fortran_csyr2k(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
cdef extern from "_blas_subroutines.h":
|
| 372 |
+
void _fortran_csyrk "BLAS_FUNC(csyrk)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
|
| 373 |
+
cdef void csyrk(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *beta, c *c, int *ldc) noexcept nogil:
|
| 374 |
+
|
| 375 |
+
_fortran_csyrk(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>beta, <npy_complex64*>c, ldc)
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
cdef extern from "_blas_subroutines.h":
|
| 379 |
+
void _fortran_ctbmv "BLAS_FUNC(ctbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
|
| 380 |
+
cdef void ctbmv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil:
|
| 381 |
+
|
| 382 |
+
_fortran_ctbmv(uplo, trans, diag, n, k, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
cdef extern from "_blas_subroutines.h":
|
| 386 |
+
void _fortran_ctbsv "BLAS_FUNC(ctbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
|
| 387 |
+
cdef void ctbsv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil:
|
| 388 |
+
|
| 389 |
+
_fortran_ctbsv(uplo, trans, diag, n, k, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
cdef extern from "_blas_subroutines.h":
|
| 393 |
+
void _fortran_ctpmv "BLAS_FUNC(ctpmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx) nogil
|
| 394 |
+
cdef void ctpmv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil:
|
| 395 |
+
|
| 396 |
+
_fortran_ctpmv(uplo, trans, diag, n, <npy_complex64*>ap, <npy_complex64*>x, incx)
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
cdef extern from "_blas_subroutines.h":
|
| 400 |
+
void _fortran_ctpsv "BLAS_FUNC(ctpsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx) nogil
|
| 401 |
+
cdef void ctpsv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil:
|
| 402 |
+
|
| 403 |
+
_fortran_ctpsv(uplo, trans, diag, n, <npy_complex64*>ap, <npy_complex64*>x, incx)
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
cdef extern from "_blas_subroutines.h":
|
| 407 |
+
void _fortran_ctrmm "BLAS_FUNC(ctrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb) nogil
|
| 408 |
+
cdef void ctrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil:
|
| 409 |
+
|
| 410 |
+
_fortran_ctrmm(side, uplo, transa, diag, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb)
|
| 411 |
+
|
| 412 |
+
|
| 413 |
+
cdef extern from "_blas_subroutines.h":
|
| 414 |
+
void _fortran_ctrmv "BLAS_FUNC(ctrmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
|
| 415 |
+
cdef void ctrmv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil:
|
| 416 |
+
|
| 417 |
+
_fortran_ctrmv(uplo, trans, diag, n, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
|
| 418 |
+
|
| 419 |
+
|
| 420 |
+
cdef extern from "_blas_subroutines.h":
|
| 421 |
+
void _fortran_ctrsm "BLAS_FUNC(ctrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb) nogil
|
| 422 |
+
cdef void ctrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil:
|
| 423 |
+
|
| 424 |
+
_fortran_ctrsm(side, uplo, transa, diag, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb)
|
| 425 |
+
|
| 426 |
+
|
| 427 |
+
cdef extern from "_blas_subroutines.h":
|
| 428 |
+
void _fortran_ctrsv "BLAS_FUNC(ctrsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
|
| 429 |
+
cdef void ctrsv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil:
|
| 430 |
+
|
| 431 |
+
_fortran_ctrsv(uplo, trans, diag, n, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
|
| 432 |
+
|
| 433 |
+
|
| 434 |
+
cdef extern from "_blas_subroutines.h":
|
| 435 |
+
d _fortran_dasum "BLAS_FUNC(dasum)"(int *n, d *dx, int *incx) nogil
|
| 436 |
+
cdef d dasum(int *n, d *dx, int *incx) noexcept nogil:
|
| 437 |
+
|
| 438 |
+
return _fortran_dasum(n, dx, incx)
|
| 439 |
+
|
| 440 |
+
|
| 441 |
+
cdef extern from "_blas_subroutines.h":
|
| 442 |
+
void _fortran_daxpy "BLAS_FUNC(daxpy)"(int *n, d *da, d *dx, int *incx, d *dy, int *incy) nogil
|
| 443 |
+
cdef void daxpy(int *n, d *da, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
|
| 444 |
+
|
| 445 |
+
_fortran_daxpy(n, da, dx, incx, dy, incy)
|
| 446 |
+
|
| 447 |
+
|
| 448 |
+
cdef extern from "_blas_subroutines.h":
|
| 449 |
+
d _fortran_dcabs1 "BLAS_FUNC(dcabs1)"(npy_complex128 *z) nogil
|
| 450 |
+
cdef d dcabs1(z *z) noexcept nogil:
|
| 451 |
+
|
| 452 |
+
return _fortran_dcabs1(<npy_complex128*>z)
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
cdef extern from "_blas_subroutines.h":
|
| 456 |
+
void _fortran_dcopy "BLAS_FUNC(dcopy)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
|
| 457 |
+
cdef void dcopy(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
|
| 458 |
+
|
| 459 |
+
_fortran_dcopy(n, dx, incx, dy, incy)
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
cdef extern from "_blas_subroutines.h":
|
| 463 |
+
d _fortran_ddot "BLAS_FUNC(ddot)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
|
| 464 |
+
cdef d ddot(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
|
| 465 |
+
|
| 466 |
+
return _fortran_ddot(n, dx, incx, dy, incy)
|
| 467 |
+
|
| 468 |
+
|
| 469 |
+
cdef extern from "_blas_subroutines.h":
|
| 470 |
+
void _fortran_dgbmv "BLAS_FUNC(dgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
|
| 471 |
+
cdef void dgbmv(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
|
| 472 |
+
|
| 473 |
+
_fortran_dgbmv(trans, m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy)
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
cdef extern from "_blas_subroutines.h":
|
| 477 |
+
void _fortran_dgemm "BLAS_FUNC(dgemm)"(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
|
| 478 |
+
cdef void dgemm(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
|
| 479 |
+
|
| 480 |
+
_fortran_dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
cdef extern from "_blas_subroutines.h":
|
| 484 |
+
void _fortran_dgemv "BLAS_FUNC(dgemv)"(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
|
| 485 |
+
cdef void dgemv(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
|
| 486 |
+
|
| 487 |
+
_fortran_dgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
cdef extern from "_blas_subroutines.h":
|
| 491 |
+
void _fortran_dger "BLAS_FUNC(dger)"(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) nogil
|
| 492 |
+
cdef void dger(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil:
|
| 493 |
+
|
| 494 |
+
_fortran_dger(m, n, alpha, x, incx, y, incy, a, lda)
|
| 495 |
+
|
| 496 |
+
|
| 497 |
+
cdef extern from "_blas_subroutines.h":
|
| 498 |
+
d _fortran_dnrm2 "BLAS_FUNC(dnrm2)"(int *n, d *x, int *incx) nogil
|
| 499 |
+
cdef d dnrm2(int *n, d *x, int *incx) noexcept nogil:
|
| 500 |
+
|
| 501 |
+
return _fortran_dnrm2(n, x, incx)
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
cdef extern from "_blas_subroutines.h":
|
| 505 |
+
void _fortran_drot "BLAS_FUNC(drot)"(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) nogil
|
| 506 |
+
cdef void drot(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) noexcept nogil:
|
| 507 |
+
|
| 508 |
+
_fortran_drot(n, dx, incx, dy, incy, c, s)
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
cdef extern from "_blas_subroutines.h":
|
| 512 |
+
void _fortran_drotg "BLAS_FUNC(drotg)"(d *da, d *db, d *c, d *s) nogil
|
| 513 |
+
cdef void drotg(d *da, d *db, d *c, d *s) noexcept nogil:
|
| 514 |
+
|
| 515 |
+
_fortran_drotg(da, db, c, s)
|
| 516 |
+
|
| 517 |
+
|
| 518 |
+
cdef extern from "_blas_subroutines.h":
|
| 519 |
+
void _fortran_drotm "BLAS_FUNC(drotm)"(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) nogil
|
| 520 |
+
cdef void drotm(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) noexcept nogil:
|
| 521 |
+
|
| 522 |
+
_fortran_drotm(n, dx, incx, dy, incy, dparam)
|
| 523 |
+
|
| 524 |
+
|
| 525 |
+
cdef extern from "_blas_subroutines.h":
|
| 526 |
+
void _fortran_drotmg "BLAS_FUNC(drotmg)"(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) nogil
|
| 527 |
+
cdef void drotmg(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) noexcept nogil:
|
| 528 |
+
|
| 529 |
+
_fortran_drotmg(dd1, dd2, dx1, dy1, dparam)
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
cdef extern from "_blas_subroutines.h":
|
| 533 |
+
void _fortran_dsbmv "BLAS_FUNC(dsbmv)"(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
|
| 534 |
+
cdef void dsbmv(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
|
| 535 |
+
|
| 536 |
+
_fortran_dsbmv(uplo, n, k, alpha, a, lda, x, incx, beta, y, incy)
|
| 537 |
+
|
| 538 |
+
|
| 539 |
+
cdef extern from "_blas_subroutines.h":
|
| 540 |
+
void _fortran_dscal "BLAS_FUNC(dscal)"(int *n, d *da, d *dx, int *incx) nogil
|
| 541 |
+
cdef void dscal(int *n, d *da, d *dx, int *incx) noexcept nogil:
|
| 542 |
+
|
| 543 |
+
_fortran_dscal(n, da, dx, incx)
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
cdef extern from "_blas_subroutines.h":
|
| 547 |
+
d _fortran_dsdot "BLAS_FUNC(dsdot)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
|
| 548 |
+
cdef d dsdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 549 |
+
|
| 550 |
+
return _fortran_dsdot(n, sx, incx, sy, incy)
|
| 551 |
+
|
| 552 |
+
|
| 553 |
+
cdef extern from "_blas_subroutines.h":
|
| 554 |
+
void _fortran_dspmv "BLAS_FUNC(dspmv)"(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) nogil
|
| 555 |
+
cdef void dspmv(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
|
| 556 |
+
|
| 557 |
+
_fortran_dspmv(uplo, n, alpha, ap, x, incx, beta, y, incy)
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
cdef extern from "_blas_subroutines.h":
|
| 561 |
+
void _fortran_dspr "BLAS_FUNC(dspr)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) nogil
|
| 562 |
+
cdef void dspr(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) noexcept nogil:
|
| 563 |
+
|
| 564 |
+
_fortran_dspr(uplo, n, alpha, x, incx, ap)
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
cdef extern from "_blas_subroutines.h":
|
| 568 |
+
void _fortran_dspr2 "BLAS_FUNC(dspr2)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) nogil
|
| 569 |
+
cdef void dspr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) noexcept nogil:
|
| 570 |
+
|
| 571 |
+
_fortran_dspr2(uplo, n, alpha, x, incx, y, incy, ap)
|
| 572 |
+
|
| 573 |
+
|
| 574 |
+
cdef extern from "_blas_subroutines.h":
|
| 575 |
+
void _fortran_dswap "BLAS_FUNC(dswap)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
|
| 576 |
+
cdef void dswap(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
|
| 577 |
+
|
| 578 |
+
_fortran_dswap(n, dx, incx, dy, incy)
|
| 579 |
+
|
| 580 |
+
|
| 581 |
+
cdef extern from "_blas_subroutines.h":
|
| 582 |
+
void _fortran_dsymm "BLAS_FUNC(dsymm)"(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
|
| 583 |
+
cdef void dsymm(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
|
| 584 |
+
|
| 585 |
+
_fortran_dsymm(side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 586 |
+
|
| 587 |
+
|
| 588 |
+
cdef extern from "_blas_subroutines.h":
|
| 589 |
+
void _fortran_dsymv "BLAS_FUNC(dsymv)"(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
|
| 590 |
+
cdef void dsymv(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
|
| 591 |
+
|
| 592 |
+
_fortran_dsymv(uplo, n, alpha, a, lda, x, incx, beta, y, incy)
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
cdef extern from "_blas_subroutines.h":
|
| 596 |
+
void _fortran_dsyr "BLAS_FUNC(dsyr)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) nogil
|
| 597 |
+
cdef void dsyr(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) noexcept nogil:
|
| 598 |
+
|
| 599 |
+
_fortran_dsyr(uplo, n, alpha, x, incx, a, lda)
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
cdef extern from "_blas_subroutines.h":
|
| 603 |
+
void _fortran_dsyr2 "BLAS_FUNC(dsyr2)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) nogil
|
| 604 |
+
cdef void dsyr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil:
|
| 605 |
+
|
| 606 |
+
_fortran_dsyr2(uplo, n, alpha, x, incx, y, incy, a, lda)
|
| 607 |
+
|
| 608 |
+
|
| 609 |
+
cdef extern from "_blas_subroutines.h":
|
| 610 |
+
void _fortran_dsyr2k "BLAS_FUNC(dsyr2k)"(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
|
| 611 |
+
cdef void dsyr2k(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
|
| 612 |
+
|
| 613 |
+
_fortran_dsyr2k(uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 614 |
+
|
| 615 |
+
|
| 616 |
+
cdef extern from "_blas_subroutines.h":
|
| 617 |
+
void _fortran_dsyrk "BLAS_FUNC(dsyrk)"(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) nogil
|
| 618 |
+
cdef void dsyrk(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) noexcept nogil:
|
| 619 |
+
|
| 620 |
+
_fortran_dsyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
|
| 621 |
+
|
| 622 |
+
|
| 623 |
+
cdef extern from "_blas_subroutines.h":
|
| 624 |
+
void _fortran_dtbmv "BLAS_FUNC(dtbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) nogil
|
| 625 |
+
cdef void dtbmv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil:
|
| 626 |
+
|
| 627 |
+
_fortran_dtbmv(uplo, trans, diag, n, k, a, lda, x, incx)
|
| 628 |
+
|
| 629 |
+
|
| 630 |
+
cdef extern from "_blas_subroutines.h":
|
| 631 |
+
void _fortran_dtbsv "BLAS_FUNC(dtbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) nogil
|
| 632 |
+
cdef void dtbsv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil:
|
| 633 |
+
|
| 634 |
+
_fortran_dtbsv(uplo, trans, diag, n, k, a, lda, x, incx)
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
cdef extern from "_blas_subroutines.h":
|
| 638 |
+
void _fortran_dtpmv "BLAS_FUNC(dtpmv)"(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) nogil
|
| 639 |
+
cdef void dtpmv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil:
|
| 640 |
+
|
| 641 |
+
_fortran_dtpmv(uplo, trans, diag, n, ap, x, incx)
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
cdef extern from "_blas_subroutines.h":
|
| 645 |
+
void _fortran_dtpsv "BLAS_FUNC(dtpsv)"(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) nogil
|
| 646 |
+
cdef void dtpsv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil:
|
| 647 |
+
|
| 648 |
+
_fortran_dtpsv(uplo, trans, diag, n, ap, x, incx)
|
| 649 |
+
|
| 650 |
+
|
| 651 |
+
cdef extern from "_blas_subroutines.h":
|
| 652 |
+
void _fortran_dtrmm "BLAS_FUNC(dtrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) nogil
|
| 653 |
+
cdef void dtrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil:
|
| 654 |
+
|
| 655 |
+
_fortran_dtrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
cdef extern from "_blas_subroutines.h":
|
| 659 |
+
void _fortran_dtrmv "BLAS_FUNC(dtrmv)"(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) nogil
|
| 660 |
+
cdef void dtrmv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil:
|
| 661 |
+
|
| 662 |
+
_fortran_dtrmv(uplo, trans, diag, n, a, lda, x, incx)
|
| 663 |
+
|
| 664 |
+
|
| 665 |
+
cdef extern from "_blas_subroutines.h":
|
| 666 |
+
void _fortran_dtrsm "BLAS_FUNC(dtrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) nogil
|
| 667 |
+
cdef void dtrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil:
|
| 668 |
+
|
| 669 |
+
_fortran_dtrsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
|
| 670 |
+
|
| 671 |
+
|
| 672 |
+
cdef extern from "_blas_subroutines.h":
|
| 673 |
+
void _fortran_dtrsv "BLAS_FUNC(dtrsv)"(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) nogil
|
| 674 |
+
cdef void dtrsv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil:
|
| 675 |
+
|
| 676 |
+
_fortran_dtrsv(uplo, trans, diag, n, a, lda, x, incx)
|
| 677 |
+
|
| 678 |
+
|
| 679 |
+
cdef extern from "_blas_subroutines.h":
|
| 680 |
+
d _fortran_dzasum "BLAS_FUNC(dzasum)"(int *n, npy_complex128 *zx, int *incx) nogil
|
| 681 |
+
cdef d dzasum(int *n, z *zx, int *incx) noexcept nogil:
|
| 682 |
+
|
| 683 |
+
return _fortran_dzasum(n, <npy_complex128*>zx, incx)
|
| 684 |
+
|
| 685 |
+
|
| 686 |
+
cdef extern from "_blas_subroutines.h":
|
| 687 |
+
d _fortran_dznrm2 "BLAS_FUNC(dznrm2)"(int *n, npy_complex128 *x, int *incx) nogil
|
| 688 |
+
cdef d dznrm2(int *n, z *x, int *incx) noexcept nogil:
|
| 689 |
+
|
| 690 |
+
return _fortran_dznrm2(n, <npy_complex128*>x, incx)
|
| 691 |
+
|
| 692 |
+
|
| 693 |
+
cdef extern from "_blas_subroutines.h":
|
| 694 |
+
int _fortran_icamax "BLAS_FUNC(icamax)"(int *n, npy_complex64 *cx, int *incx) nogil
|
| 695 |
+
cdef int icamax(int *n, c *cx, int *incx) noexcept nogil:
|
| 696 |
+
|
| 697 |
+
return _fortran_icamax(n, <npy_complex64*>cx, incx)
|
| 698 |
+
|
| 699 |
+
|
| 700 |
+
cdef extern from "_blas_subroutines.h":
|
| 701 |
+
int _fortran_idamax "BLAS_FUNC(idamax)"(int *n, d *dx, int *incx) nogil
|
| 702 |
+
cdef int idamax(int *n, d *dx, int *incx) noexcept nogil:
|
| 703 |
+
|
| 704 |
+
return _fortran_idamax(n, dx, incx)
|
| 705 |
+
|
| 706 |
+
|
| 707 |
+
cdef extern from "_blas_subroutines.h":
|
| 708 |
+
int _fortran_isamax "BLAS_FUNC(isamax)"(int *n, s *sx, int *incx) nogil
|
| 709 |
+
cdef int isamax(int *n, s *sx, int *incx) noexcept nogil:
|
| 710 |
+
|
| 711 |
+
return _fortran_isamax(n, sx, incx)
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
cdef extern from "_blas_subroutines.h":
|
| 715 |
+
int _fortran_izamax "BLAS_FUNC(izamax)"(int *n, npy_complex128 *zx, int *incx) nogil
|
| 716 |
+
cdef int izamax(int *n, z *zx, int *incx) noexcept nogil:
|
| 717 |
+
|
| 718 |
+
return _fortran_izamax(n, <npy_complex128*>zx, incx)
|
| 719 |
+
|
| 720 |
+
|
| 721 |
+
cdef extern from "_blas_subroutines.h":
|
| 722 |
+
bint _fortran_lsame "BLAS_FUNC(lsame)"(char *ca, char *cb) nogil
|
| 723 |
+
cdef bint lsame(char *ca, char *cb) noexcept nogil:
|
| 724 |
+
|
| 725 |
+
return _fortran_lsame(ca, cb)
|
| 726 |
+
|
| 727 |
+
|
| 728 |
+
cdef extern from "_blas_subroutines.h":
|
| 729 |
+
s _fortran_sasum "BLAS_FUNC(sasum)"(int *n, s *sx, int *incx) nogil
|
| 730 |
+
cdef s sasum(int *n, s *sx, int *incx) noexcept nogil:
|
| 731 |
+
|
| 732 |
+
return _fortran_sasum(n, sx, incx)
|
| 733 |
+
|
| 734 |
+
|
| 735 |
+
cdef extern from "_blas_subroutines.h":
|
| 736 |
+
void _fortran_saxpy "BLAS_FUNC(saxpy)"(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) nogil
|
| 737 |
+
cdef void saxpy(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 738 |
+
|
| 739 |
+
_fortran_saxpy(n, sa, sx, incx, sy, incy)
|
| 740 |
+
|
| 741 |
+
|
| 742 |
+
cdef extern from "_blas_subroutines.h":
|
| 743 |
+
s _fortran_scasum "BLAS_FUNC(scasum)"(int *n, npy_complex64 *cx, int *incx) nogil
|
| 744 |
+
cdef s scasum(int *n, c *cx, int *incx) noexcept nogil:
|
| 745 |
+
|
| 746 |
+
return _fortran_scasum(n, <npy_complex64*>cx, incx)
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
cdef extern from "_blas_subroutines.h":
|
| 750 |
+
s _fortran_scnrm2 "BLAS_FUNC(scnrm2)"(int *n, npy_complex64 *x, int *incx) nogil
|
| 751 |
+
cdef s scnrm2(int *n, c *x, int *incx) noexcept nogil:
|
| 752 |
+
|
| 753 |
+
return _fortran_scnrm2(n, <npy_complex64*>x, incx)
|
| 754 |
+
|
| 755 |
+
|
| 756 |
+
cdef extern from "_blas_subroutines.h":
|
| 757 |
+
void _fortran_scopy "BLAS_FUNC(scopy)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
|
| 758 |
+
cdef void scopy(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 759 |
+
|
| 760 |
+
_fortran_scopy(n, sx, incx, sy, incy)
|
| 761 |
+
|
| 762 |
+
|
| 763 |
+
cdef extern from "_blas_subroutines.h":
|
| 764 |
+
s _fortran_sdot "BLAS_FUNC(sdot)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
|
| 765 |
+
cdef s sdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 766 |
+
|
| 767 |
+
return _fortran_sdot(n, sx, incx, sy, incy)
|
| 768 |
+
|
| 769 |
+
|
| 770 |
+
cdef extern from "_blas_subroutines.h":
|
| 771 |
+
s _fortran_sdsdot "BLAS_FUNC(sdsdot)"(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) nogil
|
| 772 |
+
cdef s sdsdot(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 773 |
+
|
| 774 |
+
return _fortran_sdsdot(n, sb, sx, incx, sy, incy)
|
| 775 |
+
|
| 776 |
+
|
| 777 |
+
cdef extern from "_blas_subroutines.h":
|
| 778 |
+
void _fortran_sgbmv "BLAS_FUNC(sgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
|
| 779 |
+
cdef void sgbmv(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
|
| 780 |
+
|
| 781 |
+
_fortran_sgbmv(trans, m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy)
|
| 782 |
+
|
| 783 |
+
|
| 784 |
+
cdef extern from "_blas_subroutines.h":
|
| 785 |
+
void _fortran_sgemm "BLAS_FUNC(sgemm)"(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
|
| 786 |
+
cdef void sgemm(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
|
| 787 |
+
|
| 788 |
+
_fortran_sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 789 |
+
|
| 790 |
+
|
| 791 |
+
cdef extern from "_blas_subroutines.h":
|
| 792 |
+
void _fortran_sgemv "BLAS_FUNC(sgemv)"(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
|
| 793 |
+
cdef void sgemv(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
|
| 794 |
+
|
| 795 |
+
_fortran_sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
|
| 796 |
+
|
| 797 |
+
|
| 798 |
+
cdef extern from "_blas_subroutines.h":
|
| 799 |
+
void _fortran_sger "BLAS_FUNC(sger)"(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) nogil
|
| 800 |
+
cdef void sger(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil:
|
| 801 |
+
|
| 802 |
+
_fortran_sger(m, n, alpha, x, incx, y, incy, a, lda)
|
| 803 |
+
|
| 804 |
+
|
| 805 |
+
cdef extern from "_blas_subroutines.h":
|
| 806 |
+
s _fortran_snrm2 "BLAS_FUNC(snrm2)"(int *n, s *x, int *incx) nogil
|
| 807 |
+
cdef s snrm2(int *n, s *x, int *incx) noexcept nogil:
|
| 808 |
+
|
| 809 |
+
return _fortran_snrm2(n, x, incx)
|
| 810 |
+
|
| 811 |
+
|
| 812 |
+
cdef extern from "_blas_subroutines.h":
|
| 813 |
+
void _fortran_srot "BLAS_FUNC(srot)"(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) nogil
|
| 814 |
+
cdef void srot(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) noexcept nogil:
|
| 815 |
+
|
| 816 |
+
_fortran_srot(n, sx, incx, sy, incy, c, s)
|
| 817 |
+
|
| 818 |
+
|
| 819 |
+
cdef extern from "_blas_subroutines.h":
|
| 820 |
+
void _fortran_srotg "BLAS_FUNC(srotg)"(s *sa, s *sb, s *c, s *s) nogil
|
| 821 |
+
cdef void srotg(s *sa, s *sb, s *c, s *s) noexcept nogil:
|
| 822 |
+
|
| 823 |
+
_fortran_srotg(sa, sb, c, s)
|
| 824 |
+
|
| 825 |
+
|
| 826 |
+
cdef extern from "_blas_subroutines.h":
|
| 827 |
+
void _fortran_srotm "BLAS_FUNC(srotm)"(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) nogil
|
| 828 |
+
cdef void srotm(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) noexcept nogil:
|
| 829 |
+
|
| 830 |
+
_fortran_srotm(n, sx, incx, sy, incy, sparam)
|
| 831 |
+
|
| 832 |
+
|
| 833 |
+
cdef extern from "_blas_subroutines.h":
|
| 834 |
+
void _fortran_srotmg "BLAS_FUNC(srotmg)"(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) nogil
|
| 835 |
+
cdef void srotmg(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) noexcept nogil:
|
| 836 |
+
|
| 837 |
+
_fortran_srotmg(sd1, sd2, sx1, sy1, sparam)
|
| 838 |
+
|
| 839 |
+
|
| 840 |
+
cdef extern from "_blas_subroutines.h":
|
| 841 |
+
void _fortran_ssbmv "BLAS_FUNC(ssbmv)"(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
|
| 842 |
+
cdef void ssbmv(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
|
| 843 |
+
|
| 844 |
+
_fortran_ssbmv(uplo, n, k, alpha, a, lda, x, incx, beta, y, incy)
|
| 845 |
+
|
| 846 |
+
|
| 847 |
+
cdef extern from "_blas_subroutines.h":
|
| 848 |
+
void _fortran_sscal "BLAS_FUNC(sscal)"(int *n, s *sa, s *sx, int *incx) nogil
|
| 849 |
+
cdef void sscal(int *n, s *sa, s *sx, int *incx) noexcept nogil:
|
| 850 |
+
|
| 851 |
+
_fortran_sscal(n, sa, sx, incx)
|
| 852 |
+
|
| 853 |
+
|
| 854 |
+
cdef extern from "_blas_subroutines.h":
|
| 855 |
+
void _fortran_sspmv "BLAS_FUNC(sspmv)"(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) nogil
|
| 856 |
+
cdef void sspmv(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
|
| 857 |
+
|
| 858 |
+
_fortran_sspmv(uplo, n, alpha, ap, x, incx, beta, y, incy)
|
| 859 |
+
|
| 860 |
+
|
| 861 |
+
cdef extern from "_blas_subroutines.h":
|
| 862 |
+
void _fortran_sspr "BLAS_FUNC(sspr)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) nogil
|
| 863 |
+
cdef void sspr(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) noexcept nogil:
|
| 864 |
+
|
| 865 |
+
_fortran_sspr(uplo, n, alpha, x, incx, ap)
|
| 866 |
+
|
| 867 |
+
|
| 868 |
+
cdef extern from "_blas_subroutines.h":
|
| 869 |
+
void _fortran_sspr2 "BLAS_FUNC(sspr2)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) nogil
|
| 870 |
+
cdef void sspr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) noexcept nogil:
|
| 871 |
+
|
| 872 |
+
_fortran_sspr2(uplo, n, alpha, x, incx, y, incy, ap)
|
| 873 |
+
|
| 874 |
+
|
| 875 |
+
cdef extern from "_blas_subroutines.h":
|
| 876 |
+
void _fortran_sswap "BLAS_FUNC(sswap)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
|
| 877 |
+
cdef void sswap(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
|
| 878 |
+
|
| 879 |
+
_fortran_sswap(n, sx, incx, sy, incy)
|
| 880 |
+
|
| 881 |
+
|
| 882 |
+
cdef extern from "_blas_subroutines.h":
|
| 883 |
+
void _fortran_ssymm "BLAS_FUNC(ssymm)"(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
|
| 884 |
+
cdef void ssymm(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
|
| 885 |
+
|
| 886 |
+
_fortran_ssymm(side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 887 |
+
|
| 888 |
+
|
| 889 |
+
cdef extern from "_blas_subroutines.h":
|
| 890 |
+
void _fortran_ssymv "BLAS_FUNC(ssymv)"(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
|
| 891 |
+
cdef void ssymv(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
|
| 892 |
+
|
| 893 |
+
_fortran_ssymv(uplo, n, alpha, a, lda, x, incx, beta, y, incy)
|
| 894 |
+
|
| 895 |
+
|
| 896 |
+
cdef extern from "_blas_subroutines.h":
|
| 897 |
+
void _fortran_ssyr "BLAS_FUNC(ssyr)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) nogil
|
| 898 |
+
cdef void ssyr(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) noexcept nogil:
|
| 899 |
+
|
| 900 |
+
_fortran_ssyr(uplo, n, alpha, x, incx, a, lda)
|
| 901 |
+
|
| 902 |
+
|
| 903 |
+
cdef extern from "_blas_subroutines.h":
|
| 904 |
+
void _fortran_ssyr2 "BLAS_FUNC(ssyr2)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) nogil
|
| 905 |
+
cdef void ssyr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil:
|
| 906 |
+
|
| 907 |
+
_fortran_ssyr2(uplo, n, alpha, x, incx, y, incy, a, lda)
|
| 908 |
+
|
| 909 |
+
|
| 910 |
+
cdef extern from "_blas_subroutines.h":
|
| 911 |
+
void _fortran_ssyr2k "BLAS_FUNC(ssyr2k)"(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
|
| 912 |
+
cdef void ssyr2k(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
|
| 913 |
+
|
| 914 |
+
_fortran_ssyr2k(uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
|
| 915 |
+
|
| 916 |
+
|
| 917 |
+
cdef extern from "_blas_subroutines.h":
|
| 918 |
+
void _fortran_ssyrk "BLAS_FUNC(ssyrk)"(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) nogil
|
| 919 |
+
cdef void ssyrk(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) noexcept nogil:
|
| 920 |
+
|
| 921 |
+
_fortran_ssyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
|
| 922 |
+
|
| 923 |
+
|
| 924 |
+
cdef extern from "_blas_subroutines.h":
|
| 925 |
+
void _fortran_stbmv "BLAS_FUNC(stbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) nogil
|
| 926 |
+
cdef void stbmv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil:
|
| 927 |
+
|
| 928 |
+
_fortran_stbmv(uplo, trans, diag, n, k, a, lda, x, incx)
|
| 929 |
+
|
| 930 |
+
|
| 931 |
+
cdef extern from "_blas_subroutines.h":
|
| 932 |
+
void _fortran_stbsv "BLAS_FUNC(stbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) nogil
|
| 933 |
+
cdef void stbsv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil:
|
| 934 |
+
|
| 935 |
+
_fortran_stbsv(uplo, trans, diag, n, k, a, lda, x, incx)
|
| 936 |
+
|
| 937 |
+
|
| 938 |
+
cdef extern from "_blas_subroutines.h":
|
| 939 |
+
void _fortran_stpmv "BLAS_FUNC(stpmv)"(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) nogil
|
| 940 |
+
cdef void stpmv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil:
|
| 941 |
+
|
| 942 |
+
_fortran_stpmv(uplo, trans, diag, n, ap, x, incx)
|
| 943 |
+
|
| 944 |
+
|
| 945 |
+
cdef extern from "_blas_subroutines.h":
|
| 946 |
+
void _fortran_stpsv "BLAS_FUNC(stpsv)"(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) nogil
|
| 947 |
+
cdef void stpsv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil:
|
| 948 |
+
|
| 949 |
+
_fortran_stpsv(uplo, trans, diag, n, ap, x, incx)
|
| 950 |
+
|
| 951 |
+
|
| 952 |
+
cdef extern from "_blas_subroutines.h":
|
| 953 |
+
void _fortran_strmm "BLAS_FUNC(strmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) nogil
|
| 954 |
+
cdef void strmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil:
|
| 955 |
+
|
| 956 |
+
_fortran_strmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
|
| 957 |
+
|
| 958 |
+
|
| 959 |
+
cdef extern from "_blas_subroutines.h":
|
| 960 |
+
void _fortran_strmv "BLAS_FUNC(strmv)"(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) nogil
|
| 961 |
+
cdef void strmv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil:
|
| 962 |
+
|
| 963 |
+
_fortran_strmv(uplo, trans, diag, n, a, lda, x, incx)
|
| 964 |
+
|
| 965 |
+
|
| 966 |
+
cdef extern from "_blas_subroutines.h":
|
| 967 |
+
void _fortran_strsm "BLAS_FUNC(strsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) nogil
|
| 968 |
+
cdef void strsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil:
|
| 969 |
+
|
| 970 |
+
_fortran_strsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
|
| 971 |
+
|
| 972 |
+
|
| 973 |
+
cdef extern from "_blas_subroutines.h":
|
| 974 |
+
void _fortran_strsv "BLAS_FUNC(strsv)"(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) nogil
|
| 975 |
+
cdef void strsv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil:
|
| 976 |
+
|
| 977 |
+
_fortran_strsv(uplo, trans, diag, n, a, lda, x, incx)
|
| 978 |
+
|
| 979 |
+
|
| 980 |
+
cdef extern from "_blas_subroutines.h":
|
| 981 |
+
void _fortran_zaxpy "BLAS_FUNC(zaxpy)"(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
|
| 982 |
+
cdef void zaxpy(int *n, z *za, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
|
| 983 |
+
|
| 984 |
+
_fortran_zaxpy(n, <npy_complex128*>za, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
|
| 985 |
+
|
| 986 |
+
|
| 987 |
+
cdef extern from "_blas_subroutines.h":
|
| 988 |
+
void _fortran_zcopy "BLAS_FUNC(zcopy)"(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
|
| 989 |
+
cdef void zcopy(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
|
| 990 |
+
|
| 991 |
+
_fortran_zcopy(n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
|
| 992 |
+
|
| 993 |
+
|
| 994 |
+
cdef extern from "_blas_subroutines.h":
|
| 995 |
+
void _fortran_zdotc "(zdotcwrp_)"(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
|
| 996 |
+
cdef z zdotc(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
|
| 997 |
+
cdef z out
|
| 998 |
+
_fortran_zdotc(<npy_complex128*>&out, n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
|
| 999 |
+
return out
|
| 1000 |
+
|
| 1001 |
+
cdef extern from "_blas_subroutines.h":
|
| 1002 |
+
void _fortran_zdotu "(zdotuwrp_)"(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
|
| 1003 |
+
cdef z zdotu(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
|
| 1004 |
+
cdef z out
|
| 1005 |
+
_fortran_zdotu(<npy_complex128*>&out, n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
|
| 1006 |
+
return out
|
| 1007 |
+
|
| 1008 |
+
cdef extern from "_blas_subroutines.h":
|
| 1009 |
+
void _fortran_zdrot "BLAS_FUNC(zdrot)"(int *n, npy_complex128 *cx, int *incx, npy_complex128 *cy, int *incy, d *c, d *s) nogil
|
| 1010 |
+
cdef void zdrot(int *n, z *cx, int *incx, z *cy, int *incy, d *c, d *s) noexcept nogil:
|
| 1011 |
+
|
| 1012 |
+
_fortran_zdrot(n, <npy_complex128*>cx, incx, <npy_complex128*>cy, incy, c, s)
|
| 1013 |
+
|
| 1014 |
+
|
| 1015 |
+
cdef extern from "_blas_subroutines.h":
|
| 1016 |
+
void _fortran_zdscal "BLAS_FUNC(zdscal)"(int *n, d *da, npy_complex128 *zx, int *incx) nogil
|
| 1017 |
+
cdef void zdscal(int *n, d *da, z *zx, int *incx) noexcept nogil:
|
| 1018 |
+
|
| 1019 |
+
_fortran_zdscal(n, da, <npy_complex128*>zx, incx)
|
| 1020 |
+
|
| 1021 |
+
|
| 1022 |
+
cdef extern from "_blas_subroutines.h":
|
| 1023 |
+
void _fortran_zgbmv "BLAS_FUNC(zgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
|
| 1024 |
+
cdef void zgbmv(char *trans, int *m, int *n, int *kl, int *ku, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
|
| 1025 |
+
|
| 1026 |
+
_fortran_zgbmv(trans, m, n, kl, ku, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
|
| 1027 |
+
|
| 1028 |
+
|
| 1029 |
+
cdef extern from "_blas_subroutines.h":
|
| 1030 |
+
void _fortran_zgemm "BLAS_FUNC(zgemm)"(char *transa, char *transb, int *m, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
|
| 1031 |
+
cdef void zgemm(char *transa, char *transb, int *m, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
|
| 1032 |
+
|
| 1033 |
+
_fortran_zgemm(transa, transb, m, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
|
| 1034 |
+
|
| 1035 |
+
|
| 1036 |
+
cdef extern from "_blas_subroutines.h":
|
| 1037 |
+
void _fortran_zgemv "BLAS_FUNC(zgemv)"(char *trans, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
|
| 1038 |
+
cdef void zgemv(char *trans, int *m, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
|
| 1039 |
+
|
| 1040 |
+
_fortran_zgemv(trans, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
|
| 1041 |
+
|
| 1042 |
+
|
| 1043 |
+
cdef extern from "_blas_subroutines.h":
|
| 1044 |
+
void _fortran_zgerc "BLAS_FUNC(zgerc)"(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
|
| 1045 |
+
cdef void zgerc(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
|
| 1046 |
+
|
| 1047 |
+
_fortran_zgerc(m, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
|
| 1048 |
+
|
| 1049 |
+
|
| 1050 |
+
cdef extern from "_blas_subroutines.h":
|
| 1051 |
+
void _fortran_zgeru "BLAS_FUNC(zgeru)"(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
|
| 1052 |
+
cdef void zgeru(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
|
| 1053 |
+
|
| 1054 |
+
_fortran_zgeru(m, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
|
| 1055 |
+
|
| 1056 |
+
|
| 1057 |
+
cdef extern from "_blas_subroutines.h":
|
| 1058 |
+
void _fortran_zhbmv "BLAS_FUNC(zhbmv)"(char *uplo, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
|
| 1059 |
+
cdef void zhbmv(char *uplo, int *n, int *k, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
|
| 1060 |
+
|
| 1061 |
+
_fortran_zhbmv(uplo, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
|
| 1062 |
+
|
| 1063 |
+
|
| 1064 |
+
cdef extern from "_blas_subroutines.h":
|
| 1065 |
+
void _fortran_zhemm "BLAS_FUNC(zhemm)"(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
|
| 1066 |
+
cdef void zhemm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
|
| 1067 |
+
|
| 1068 |
+
_fortran_zhemm(side, uplo, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
|
| 1069 |
+
|
| 1070 |
+
|
| 1071 |
+
cdef extern from "_blas_subroutines.h":
|
| 1072 |
+
void _fortran_zhemv "BLAS_FUNC(zhemv)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
|
| 1073 |
+
cdef void zhemv(char *uplo, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
|
| 1074 |
+
|
| 1075 |
+
_fortran_zhemv(uplo, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
|
| 1076 |
+
|
| 1077 |
+
|
| 1078 |
+
cdef extern from "_blas_subroutines.h":
|
| 1079 |
+
void _fortran_zher "BLAS_FUNC(zher)"(char *uplo, int *n, d *alpha, npy_complex128 *x, int *incx, npy_complex128 *a, int *lda) nogil
|
| 1080 |
+
cdef void zher(char *uplo, int *n, d *alpha, z *x, int *incx, z *a, int *lda) noexcept nogil:
|
| 1081 |
+
|
| 1082 |
+
_fortran_zher(uplo, n, alpha, <npy_complex128*>x, incx, <npy_complex128*>a, lda)
|
| 1083 |
+
|
| 1084 |
+
|
| 1085 |
+
cdef extern from "_blas_subroutines.h":
|
| 1086 |
+
void _fortran_zher2 "BLAS_FUNC(zher2)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
|
| 1087 |
+
cdef void zher2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
|
| 1088 |
+
|
| 1089 |
+
_fortran_zher2(uplo, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
|
| 1090 |
+
|
| 1091 |
+
|
| 1092 |
+
cdef extern from "_blas_subroutines.h":
|
| 1093 |
+
void _fortran_zher2k "BLAS_FUNC(zher2k)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, d *beta, npy_complex128 *c, int *ldc) nogil
|
| 1094 |
+
cdef void zher2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, d *beta, z *c, int *ldc) noexcept nogil:
|
| 1095 |
+
|
| 1096 |
+
_fortran_zher2k(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, beta, <npy_complex128*>c, ldc)
|
| 1097 |
+
|
| 1098 |
+
|
| 1099 |
+
cdef extern from "_blas_subroutines.h":
|
| 1100 |
+
void _fortran_zherk "BLAS_FUNC(zherk)"(char *uplo, char *trans, int *n, int *k, d *alpha, npy_complex128 *a, int *lda, d *beta, npy_complex128 *c, int *ldc) nogil
|
| 1101 |
+
cdef void zherk(char *uplo, char *trans, int *n, int *k, d *alpha, z *a, int *lda, d *beta, z *c, int *ldc) noexcept nogil:
|
| 1102 |
+
|
| 1103 |
+
_fortran_zherk(uplo, trans, n, k, alpha, <npy_complex128*>a, lda, beta, <npy_complex128*>c, ldc)
|
| 1104 |
+
|
| 1105 |
+
|
| 1106 |
+
cdef extern from "_blas_subroutines.h":
|
| 1107 |
+
void _fortran_zhpmv "BLAS_FUNC(zhpmv)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *ap, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
|
| 1108 |
+
cdef void zhpmv(char *uplo, int *n, z *alpha, z *ap, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
|
| 1109 |
+
|
| 1110 |
+
_fortran_zhpmv(uplo, n, <npy_complex128*>alpha, <npy_complex128*>ap, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
|
| 1111 |
+
|
| 1112 |
+
|
| 1113 |
+
cdef extern from "_blas_subroutines.h":
|
| 1114 |
+
void _fortran_zhpr "BLAS_FUNC(zhpr)"(char *uplo, int *n, d *alpha, npy_complex128 *x, int *incx, npy_complex128 *ap) nogil
|
| 1115 |
+
cdef void zhpr(char *uplo, int *n, d *alpha, z *x, int *incx, z *ap) noexcept nogil:
|
| 1116 |
+
|
| 1117 |
+
_fortran_zhpr(uplo, n, alpha, <npy_complex128*>x, incx, <npy_complex128*>ap)
|
| 1118 |
+
|
| 1119 |
+
|
| 1120 |
+
cdef extern from "_blas_subroutines.h":
|
| 1121 |
+
void _fortran_zhpr2 "BLAS_FUNC(zhpr2)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *ap) nogil
|
| 1122 |
+
cdef void zhpr2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *ap) noexcept nogil:
|
| 1123 |
+
|
| 1124 |
+
_fortran_zhpr2(uplo, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>ap)
|
| 1125 |
+
|
| 1126 |
+
|
| 1127 |
+
cdef extern from "_blas_subroutines.h":
|
| 1128 |
+
void _fortran_zrotg "BLAS_FUNC(zrotg)"(npy_complex128 *ca, npy_complex128 *cb, d *c, npy_complex128 *s) nogil
|
| 1129 |
+
cdef void zrotg(z *ca, z *cb, d *c, z *s) noexcept nogil:
|
| 1130 |
+
|
| 1131 |
+
_fortran_zrotg(<npy_complex128*>ca, <npy_complex128*>cb, c, <npy_complex128*>s)
|
| 1132 |
+
|
| 1133 |
+
|
| 1134 |
+
cdef extern from "_blas_subroutines.h":
|
| 1135 |
+
void _fortran_zscal "BLAS_FUNC(zscal)"(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx) nogil
|
| 1136 |
+
cdef void zscal(int *n, z *za, z *zx, int *incx) noexcept nogil:
|
| 1137 |
+
|
| 1138 |
+
_fortran_zscal(n, <npy_complex128*>za, <npy_complex128*>zx, incx)
|
| 1139 |
+
|
| 1140 |
+
|
| 1141 |
+
cdef extern from "_blas_subroutines.h":
|
| 1142 |
+
void _fortran_zswap "BLAS_FUNC(zswap)"(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
|
| 1143 |
+
cdef void zswap(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
|
| 1144 |
+
|
| 1145 |
+
_fortran_zswap(n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
|
| 1146 |
+
|
| 1147 |
+
|
| 1148 |
+
cdef extern from "_blas_subroutines.h":
|
| 1149 |
+
void _fortran_zsymm "BLAS_FUNC(zsymm)"(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
|
| 1150 |
+
cdef void zsymm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
|
| 1151 |
+
|
| 1152 |
+
_fortran_zsymm(side, uplo, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
|
| 1153 |
+
|
| 1154 |
+
|
| 1155 |
+
cdef extern from "_blas_subroutines.h":
|
| 1156 |
+
void _fortran_zsyr2k "BLAS_FUNC(zsyr2k)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
|
| 1157 |
+
cdef void zsyr2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
|
| 1158 |
+
|
| 1159 |
+
_fortran_zsyr2k(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
|
| 1160 |
+
|
| 1161 |
+
|
| 1162 |
+
cdef extern from "_blas_subroutines.h":
|
| 1163 |
+
void _fortran_zsyrk "BLAS_FUNC(zsyrk)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
|
| 1164 |
+
cdef void zsyrk(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *beta, z *c, int *ldc) noexcept nogil:
|
| 1165 |
+
|
| 1166 |
+
_fortran_zsyrk(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>beta, <npy_complex128*>c, ldc)
|
| 1167 |
+
|
| 1168 |
+
|
| 1169 |
+
cdef extern from "_blas_subroutines.h":
|
| 1170 |
+
void _fortran_ztbmv "BLAS_FUNC(ztbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
|
| 1171 |
+
cdef void ztbmv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil:
|
| 1172 |
+
|
| 1173 |
+
_fortran_ztbmv(uplo, trans, diag, n, k, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
|
| 1174 |
+
|
| 1175 |
+
|
| 1176 |
+
cdef extern from "_blas_subroutines.h":
|
| 1177 |
+
void _fortran_ztbsv "BLAS_FUNC(ztbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
|
| 1178 |
+
cdef void ztbsv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil:
|
| 1179 |
+
|
| 1180 |
+
_fortran_ztbsv(uplo, trans, diag, n, k, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
|
| 1181 |
+
|
| 1182 |
+
|
| 1183 |
+
cdef extern from "_blas_subroutines.h":
|
| 1184 |
+
void _fortran_ztpmv "BLAS_FUNC(ztpmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx) nogil
|
| 1185 |
+
cdef void ztpmv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil:
|
| 1186 |
+
|
| 1187 |
+
_fortran_ztpmv(uplo, trans, diag, n, <npy_complex128*>ap, <npy_complex128*>x, incx)
|
| 1188 |
+
|
| 1189 |
+
|
| 1190 |
+
cdef extern from "_blas_subroutines.h":
|
| 1191 |
+
void _fortran_ztpsv "BLAS_FUNC(ztpsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx) nogil
|
| 1192 |
+
cdef void ztpsv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil:
|
| 1193 |
+
|
| 1194 |
+
_fortran_ztpsv(uplo, trans, diag, n, <npy_complex128*>ap, <npy_complex128*>x, incx)
|
| 1195 |
+
|
| 1196 |
+
|
| 1197 |
+
cdef extern from "_blas_subroutines.h":
|
| 1198 |
+
void _fortran_ztrmm "BLAS_FUNC(ztrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb) nogil
|
| 1199 |
+
cdef void ztrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil:
|
| 1200 |
+
|
| 1201 |
+
_fortran_ztrmm(side, uplo, transa, diag, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb)
|
| 1202 |
+
|
| 1203 |
+
|
| 1204 |
+
cdef extern from "_blas_subroutines.h":
|
| 1205 |
+
void _fortran_ztrmv "BLAS_FUNC(ztrmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
|
| 1206 |
+
cdef void ztrmv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil:
|
| 1207 |
+
|
| 1208 |
+
_fortran_ztrmv(uplo, trans, diag, n, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
|
| 1209 |
+
|
| 1210 |
+
|
| 1211 |
+
cdef extern from "_blas_subroutines.h":
|
| 1212 |
+
void _fortran_ztrsm "BLAS_FUNC(ztrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb) nogil
|
| 1213 |
+
cdef void ztrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil:
|
| 1214 |
+
|
| 1215 |
+
_fortran_ztrsm(side, uplo, transa, diag, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb)
|
| 1216 |
+
|
| 1217 |
+
|
| 1218 |
+
cdef extern from "_blas_subroutines.h":
|
| 1219 |
+
void _fortran_ztrsv "BLAS_FUNC(ztrsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
|
| 1220 |
+
cdef void ztrsv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil:
|
| 1221 |
+
|
| 1222 |
+
_fortran_ztrsv(uplo, trans, diag, n, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
|
| 1223 |
+
|
| 1224 |
+
|
| 1225 |
+
|
| 1226 |
+
# Python-accessible wrappers for testing:
|
| 1227 |
+
|
| 1228 |
+
cdef inline bint _is_contiguous(double[:,:] a, int axis) noexcept nogil:
|
| 1229 |
+
return (a.strides[axis] == sizeof(a[0,0]) or a.shape[axis] == 1)
|
| 1230 |
+
|
| 1231 |
+
cpdef float complex _test_cdotc(float complex[:] cx, float complex[:] cy) noexcept nogil:
|
| 1232 |
+
cdef:
|
| 1233 |
+
int n = cx.shape[0]
|
| 1234 |
+
int incx = cx.strides[0] // sizeof(cx[0])
|
| 1235 |
+
int incy = cy.strides[0] // sizeof(cy[0])
|
| 1236 |
+
return cdotc(&n, &cx[0], &incx, &cy[0], &incy)
|
| 1237 |
+
|
| 1238 |
+
cpdef float complex _test_cdotu(float complex[:] cx, float complex[:] cy) noexcept nogil:
|
| 1239 |
+
cdef:
|
| 1240 |
+
int n = cx.shape[0]
|
| 1241 |
+
int incx = cx.strides[0] // sizeof(cx[0])
|
| 1242 |
+
int incy = cy.strides[0] // sizeof(cy[0])
|
| 1243 |
+
return cdotu(&n, &cx[0], &incx, &cy[0], &incy)
|
| 1244 |
+
|
| 1245 |
+
cpdef double _test_dasum(double[:] dx) noexcept nogil:
|
| 1246 |
+
cdef:
|
| 1247 |
+
int n = dx.shape[0]
|
| 1248 |
+
int incx = dx.strides[0] // sizeof(dx[0])
|
| 1249 |
+
return dasum(&n, &dx[0], &incx)
|
| 1250 |
+
|
| 1251 |
+
cpdef double _test_ddot(double[:] dx, double[:] dy) noexcept nogil:
|
| 1252 |
+
cdef:
|
| 1253 |
+
int n = dx.shape[0]
|
| 1254 |
+
int incx = dx.strides[0] // sizeof(dx[0])
|
| 1255 |
+
int incy = dy.strides[0] // sizeof(dy[0])
|
| 1256 |
+
return ddot(&n, &dx[0], &incx, &dy[0], &incy)
|
| 1257 |
+
|
| 1258 |
+
cpdef int _test_dgemm(double alpha, double[:,:] a, double[:,:] b, double beta,
|
| 1259 |
+
double[:,:] c) except -1 nogil:
|
| 1260 |
+
cdef:
|
| 1261 |
+
char *transa
|
| 1262 |
+
char *transb
|
| 1263 |
+
int m, n, k, lda, ldb, ldc
|
| 1264 |
+
double *a0=&a[0,0]
|
| 1265 |
+
double *b0=&b[0,0]
|
| 1266 |
+
double *c0=&c[0,0]
|
| 1267 |
+
# In the case that c is C contiguous, swap a and b and
|
| 1268 |
+
# swap whether or not each of them is transposed.
|
| 1269 |
+
# This can be done because a.dot(b) = b.T.dot(a.T).T.
|
| 1270 |
+
if _is_contiguous(c, 1):
|
| 1271 |
+
if _is_contiguous(a, 1):
|
| 1272 |
+
transb = 'n'
|
| 1273 |
+
ldb = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
|
| 1274 |
+
elif _is_contiguous(a, 0):
|
| 1275 |
+
transb = 't'
|
| 1276 |
+
ldb = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
|
| 1277 |
+
else:
|
| 1278 |
+
with gil:
|
| 1279 |
+
raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
|
| 1280 |
+
if _is_contiguous(b, 1):
|
| 1281 |
+
transa = 'n'
|
| 1282 |
+
lda = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
|
| 1283 |
+
elif _is_contiguous(b, 0):
|
| 1284 |
+
transa = 't'
|
| 1285 |
+
lda = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
|
| 1286 |
+
else:
|
| 1287 |
+
with gil:
|
| 1288 |
+
raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
|
| 1289 |
+
k = b.shape[0]
|
| 1290 |
+
if k != a.shape[1]:
|
| 1291 |
+
with gil:
|
| 1292 |
+
raise ValueError("Shape mismatch in input arrays.")
|
| 1293 |
+
m = b.shape[1]
|
| 1294 |
+
n = a.shape[0]
|
| 1295 |
+
if n != c.shape[0] or m != c.shape[1]:
|
| 1296 |
+
with gil:
|
| 1297 |
+
raise ValueError("Output array does not have the correct shape.")
|
| 1298 |
+
ldc = (&c[1,0]) - c0 if c.shape[0] > 1 else 1
|
| 1299 |
+
dgemm(transa, transb, &m, &n, &k, &alpha, b0, &lda, a0,
|
| 1300 |
+
&ldb, &beta, c0, &ldc)
|
| 1301 |
+
elif _is_contiguous(c, 0):
|
| 1302 |
+
if _is_contiguous(a, 1):
|
| 1303 |
+
transa = 't'
|
| 1304 |
+
lda = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
|
| 1305 |
+
elif _is_contiguous(a, 0):
|
| 1306 |
+
transa = 'n'
|
| 1307 |
+
lda = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
|
| 1308 |
+
else:
|
| 1309 |
+
with gil:
|
| 1310 |
+
raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
|
| 1311 |
+
if _is_contiguous(b, 1):
|
| 1312 |
+
transb = 't'
|
| 1313 |
+
ldb = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
|
| 1314 |
+
elif _is_contiguous(b, 0):
|
| 1315 |
+
transb = 'n'
|
| 1316 |
+
ldb = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
|
| 1317 |
+
else:
|
| 1318 |
+
with gil:
|
| 1319 |
+
raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
|
| 1320 |
+
m = a.shape[0]
|
| 1321 |
+
k = a.shape[1]
|
| 1322 |
+
if k != b.shape[0]:
|
| 1323 |
+
with gil:
|
| 1324 |
+
raise ValueError("Shape mismatch in input arrays.")
|
| 1325 |
+
n = b.shape[1]
|
| 1326 |
+
if m != c.shape[0] or n != c.shape[1]:
|
| 1327 |
+
with gil:
|
| 1328 |
+
raise ValueError("Output array does not have the correct shape.")
|
| 1329 |
+
ldc = (&c[0,1]) - c0 if c.shape[1] > 1 else 1
|
| 1330 |
+
dgemm(transa, transb, &m, &n, &k, &alpha, a0, &lda, b0,
|
| 1331 |
+
&ldb, &beta, c0, &ldc)
|
| 1332 |
+
else:
|
| 1333 |
+
with gil:
|
| 1334 |
+
raise ValueError("Input 'c' is neither C nor Fortran contiguous.")
|
| 1335 |
+
return 0
|
| 1336 |
+
|
| 1337 |
+
cpdef double _test_dnrm2(double[:] x) noexcept nogil:
|
| 1338 |
+
cdef:
|
| 1339 |
+
int n = x.shape[0]
|
| 1340 |
+
int incx = x.strides[0] // sizeof(x[0])
|
| 1341 |
+
return dnrm2(&n, &x[0], &incx)
|
| 1342 |
+
|
| 1343 |
+
cpdef double _test_dzasum(double complex[:] zx) noexcept nogil:
|
| 1344 |
+
cdef:
|
| 1345 |
+
int n = zx.shape[0]
|
| 1346 |
+
int incx = zx.strides[0] // sizeof(zx[0])
|
| 1347 |
+
return dzasum(&n, &zx[0], &incx)
|
| 1348 |
+
|
| 1349 |
+
cpdef double _test_dznrm2(double complex[:] x) noexcept nogil:
|
| 1350 |
+
cdef:
|
| 1351 |
+
int n = x.shape[0]
|
| 1352 |
+
int incx = x.strides[0] // sizeof(x[0])
|
| 1353 |
+
return dznrm2(&n, &x[0], &incx)
|
| 1354 |
+
|
| 1355 |
+
cpdef int _test_icamax(float complex[:] cx) noexcept nogil:
|
| 1356 |
+
cdef:
|
| 1357 |
+
int n = cx.shape[0]
|
| 1358 |
+
int incx = cx.strides[0] // sizeof(cx[0])
|
| 1359 |
+
return icamax(&n, &cx[0], &incx)
|
| 1360 |
+
|
| 1361 |
+
cpdef int _test_idamax(double[:] dx) noexcept nogil:
|
| 1362 |
+
cdef:
|
| 1363 |
+
int n = dx.shape[0]
|
| 1364 |
+
int incx = dx.strides[0] // sizeof(dx[0])
|
| 1365 |
+
return idamax(&n, &dx[0], &incx)
|
| 1366 |
+
|
| 1367 |
+
cpdef int _test_isamax(float[:] sx) noexcept nogil:
|
| 1368 |
+
cdef:
|
| 1369 |
+
int n = sx.shape[0]
|
| 1370 |
+
int incx = sx.strides[0] // sizeof(sx[0])
|
| 1371 |
+
return isamax(&n, &sx[0], &incx)
|
| 1372 |
+
|
| 1373 |
+
cpdef int _test_izamax(double complex[:] zx) noexcept nogil:
|
| 1374 |
+
cdef:
|
| 1375 |
+
int n = zx.shape[0]
|
| 1376 |
+
int incx = zx.strides[0] // sizeof(zx[0])
|
| 1377 |
+
return izamax(&n, &zx[0], &incx)
|
| 1378 |
+
|
| 1379 |
+
cpdef float _test_sasum(float[:] sx) noexcept nogil:
|
| 1380 |
+
cdef:
|
| 1381 |
+
int n = sx.shape[0]
|
| 1382 |
+
int incx = sx.strides[0] // sizeof(sx[0])
|
| 1383 |
+
return sasum(&n, &sx[0], &incx)
|
| 1384 |
+
|
| 1385 |
+
cpdef float _test_scasum(float complex[:] cx) noexcept nogil:
|
| 1386 |
+
cdef:
|
| 1387 |
+
int n = cx.shape[0]
|
| 1388 |
+
int incx = cx.strides[0] // sizeof(cx[0])
|
| 1389 |
+
return scasum(&n, &cx[0], &incx)
|
| 1390 |
+
|
| 1391 |
+
cpdef float _test_scnrm2(float complex[:] x) noexcept nogil:
|
| 1392 |
+
cdef:
|
| 1393 |
+
int n = x.shape[0]
|
| 1394 |
+
int incx = x.strides[0] // sizeof(x[0])
|
| 1395 |
+
return scnrm2(&n, &x[0], &incx)
|
| 1396 |
+
|
| 1397 |
+
cpdef float _test_sdot(float[:] sx, float[:] sy) noexcept nogil:
|
| 1398 |
+
cdef:
|
| 1399 |
+
int n = sx.shape[0]
|
| 1400 |
+
int incx = sx.strides[0] // sizeof(sx[0])
|
| 1401 |
+
int incy = sy.strides[0] // sizeof(sy[0])
|
| 1402 |
+
return sdot(&n, &sx[0], &incx, &sy[0], &incy)
|
| 1403 |
+
|
| 1404 |
+
cpdef float _test_snrm2(float[:] x) noexcept nogil:
|
| 1405 |
+
cdef:
|
| 1406 |
+
int n = x.shape[0]
|
| 1407 |
+
int incx = x.strides[0] // sizeof(x[0])
|
| 1408 |
+
return snrm2(&n, &x[0], &incx)
|
| 1409 |
+
|
| 1410 |
+
cpdef double complex _test_zdotc(double complex[:] zx, double complex[:] zy) noexcept nogil:
|
| 1411 |
+
cdef:
|
| 1412 |
+
int n = zx.shape[0]
|
| 1413 |
+
int incx = zx.strides[0] // sizeof(zx[0])
|
| 1414 |
+
int incy = zy.strides[0] // sizeof(zy[0])
|
| 1415 |
+
return zdotc(&n, &zx[0], &incx, &zy[0], &incy)
|
| 1416 |
+
|
| 1417 |
+
cpdef double complex _test_zdotu(double complex[:] zx, double complex[:] zy) noexcept nogil:
|
| 1418 |
+
cdef:
|
| 1419 |
+
int n = zx.shape[0]
|
| 1420 |
+
int incx = zx.strides[0] // sizeof(zx[0])
|
| 1421 |
+
int incy = zy.strides[0] // sizeof(zy[0])
|
| 1422 |
+
return zdotu(&n, &zx[0], &incx, &zy[0], &incy)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pxd
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pyx
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'eig', 'eigvals', 'eigh', 'eigvalsh',
|
| 10 |
+
'eig_banded', 'eigvals_banded',
|
| 11 |
+
'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf',
|
| 12 |
+
'array', 'isfinite', 'inexact', 'nonzero', 'iscomplexobj',
|
| 13 |
+
'flatnonzero', 'argsort', 'iscomplex', 'einsum', 'eye', 'inf',
|
| 14 |
+
'LinAlgError', 'norm', 'get_lapack_funcs'
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def __dir__():
|
| 19 |
+
return __all__
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def __getattr__(name):
|
| 23 |
+
return _sub_module_deprecation(sub_package="linalg", module="decomp",
|
| 24 |
+
private_modules=["_decomp"], all=__all__,
|
| 25 |
+
attribute=name)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_cholesky.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'cholesky', 'cho_factor', 'cho_solve', 'cholesky_banded',
|
| 10 |
+
'cho_solve_banded', 'asarray_chkfinite', 'atleast_2d',
|
| 11 |
+
'LinAlgError', 'get_lapack_funcs'
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def __dir__():
|
| 16 |
+
return __all__
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def __getattr__(name):
|
| 20 |
+
return _sub_module_deprecation(sub_package="linalg", module="decomp_cholesky",
|
| 21 |
+
private_modules=["_decomp_cholesky"], all=__all__,
|
| 22 |
+
attribute=name)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_lu.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'lu', 'lu_solve', 'lu_factor',
|
| 10 |
+
'asarray_chkfinite', 'LinAlgWarning', 'get_lapack_funcs',
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def __dir__():
|
| 15 |
+
return __all__
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def __getattr__(name):
|
| 19 |
+
return _sub_module_deprecation(sub_package="linalg", module="decomp_lu",
|
| 20 |
+
private_modules=["_decomp_lu"], all=__all__,
|
| 21 |
+
attribute=name)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_qr.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'qr', 'qr_multiply', 'rq', 'get_lapack_funcs', 'safecall'
|
| 10 |
+
]
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def __dir__():
|
| 14 |
+
return __all__
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def __getattr__(name):
|
| 18 |
+
return _sub_module_deprecation(sub_package="linalg", module="decomp_qr",
|
| 19 |
+
private_modules=["_decomp_qr"], all=__all__,
|
| 20 |
+
attribute=name)
|
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_schur.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is not meant for public use and will be removed in SciPy v2.0.0.
|
| 2 |
+
# Use the `scipy.linalg` namespace for importing the functions
|
| 3 |
+
# included below.
|
| 4 |
+
|
| 5 |
+
from scipy._lib.deprecation import _sub_module_deprecation
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
__all__ = [ # noqa: F822
|
| 9 |
+
'schur', 'rsf2csf', 'asarray_chkfinite', 'single', 'array', 'norm',
|
| 10 |
+
'LinAlgError', 'get_lapack_funcs', 'eigvals', 'eps', 'feps'
|
| 11 |
+
]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def __dir__():
|
| 15 |
+
return __all__
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def __getattr__(name):
|
| 19 |
+
return _sub_module_deprecation(sub_package="linalg", module="decomp_schur",
|
| 20 |
+
private_modules=["_decomp_schur"], all=__all__,
|
| 21 |
+
attribute=name)
|
| 22 |
+
|