scipy 1.15.3__cp312-cp312-musllinux_1_2_aarch64.whl → 1.16.0rc2__cp312-cp312-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scipy/__config__.py +10 -10
- scipy/__init__.py +3 -6
- scipy/_cyutility.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_array_api.py +486 -161
- scipy/_lib/_array_api_compat_vendor.py +9 -0
- scipy/_lib/_bunch.py +4 -0
- scipy/_lib/_ccallback_c.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_docscrape.py +1 -1
- scipy/_lib/_elementwise_iterative_method.py +15 -26
- scipy/_lib/_fpumode.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_ccallback.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_test_deprecation_call.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_test_deprecation_def.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_testutils.py +6 -2
- scipy/_lib/_uarray/_uarray.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/_util.py +222 -125
- scipy/_lib/array_api_compat/__init__.py +4 -4
- scipy/_lib/array_api_compat/_internal.py +19 -6
- scipy/_lib/array_api_compat/common/__init__.py +1 -1
- scipy/_lib/array_api_compat/common/_aliases.py +365 -193
- scipy/_lib/array_api_compat/common/_fft.py +94 -64
- scipy/_lib/array_api_compat/common/_helpers.py +413 -180
- scipy/_lib/array_api_compat/common/_linalg.py +116 -40
- scipy/_lib/array_api_compat/common/_typing.py +179 -10
- scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
- scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
- scipy/_lib/array_api_compat/cupy/_info.py +16 -6
- scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
- scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
- scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
- scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
- scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
- scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
- scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
- scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
- scipy/_lib/array_api_compat/numpy/_info.py +36 -16
- scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
- scipy/_lib/array_api_compat/numpy/fft.py +11 -5
- scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
- scipy/_lib/array_api_compat/torch/__init__.py +3 -5
- scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
- scipy/_lib/array_api_compat/torch/_info.py +27 -16
- scipy/_lib/array_api_compat/torch/_typing.py +3 -0
- scipy/_lib/array_api_compat/torch/fft.py +17 -18
- scipy/_lib/array_api_compat/torch/linalg.py +16 -16
- scipy/_lib/array_api_extra/__init__.py +26 -3
- scipy/_lib/array_api_extra/_delegation.py +171 -0
- scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_at.py +463 -0
- scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
- scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
- scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
- scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
- scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
- scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
- scipy/_lib/array_api_extra/testing.py +359 -0
- scipy/_lib/decorator.py +2 -2
- scipy/_lib/doccer.py +1 -7
- scipy/_lib/messagestream.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/_lib/pyprima/__init__.py +212 -0
- scipy/_lib/pyprima/cobyla/__init__.py +0 -0
- scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
- scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
- scipy/_lib/pyprima/cobyla/geometry.py +226 -0
- scipy/_lib/pyprima/cobyla/initialize.py +215 -0
- scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
- scipy/_lib/pyprima/cobyla/update.py +289 -0
- scipy/_lib/pyprima/common/__init__.py +0 -0
- scipy/_lib/pyprima/common/_bounds.py +34 -0
- scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
- scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
- scipy/_lib/pyprima/common/_project.py +173 -0
- scipy/_lib/pyprima/common/checkbreak.py +93 -0
- scipy/_lib/pyprima/common/consts.py +47 -0
- scipy/_lib/pyprima/common/evaluate.py +99 -0
- scipy/_lib/pyprima/common/history.py +38 -0
- scipy/_lib/pyprima/common/infos.py +30 -0
- scipy/_lib/pyprima/common/linalg.py +435 -0
- scipy/_lib/pyprima/common/message.py +290 -0
- scipy/_lib/pyprima/common/powalg.py +131 -0
- scipy/_lib/pyprima/common/preproc.py +277 -0
- scipy/_lib/pyprima/common/present.py +5 -0
- scipy/_lib/pyprima/common/ratio.py +54 -0
- scipy/_lib/pyprima/common/redrho.py +47 -0
- scipy/_lib/pyprima/common/selectx.py +296 -0
- scipy/_lib/tests/test__util.py +105 -121
- scipy/_lib/tests/test_array_api.py +166 -35
- scipy/_lib/tests/test_bunch.py +7 -0
- scipy/_lib/tests/test_ccallback.py +2 -10
- scipy/_lib/tests/test_public_api.py +13 -0
- scipy/cluster/_hierarchy.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/cluster/_optimal_leaf_ordering.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/cluster/_vq.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/cluster/hierarchy.py +393 -223
- scipy/cluster/tests/test_hierarchy.py +273 -335
- scipy/cluster/tests/test_vq.py +45 -61
- scipy/cluster/vq.py +39 -35
- scipy/conftest.py +263 -157
- scipy/constants/_constants.py +4 -1
- scipy/constants/tests/test_codata.py +2 -2
- scipy/constants/tests/test_constants.py +11 -18
- scipy/datasets/_download_all.py +15 -1
- scipy/datasets/_fetchers.py +7 -1
- scipy/datasets/_utils.py +1 -1
- scipy/differentiate/_differentiate.py +25 -25
- scipy/differentiate/tests/test_differentiate.py +24 -25
- scipy/fft/_basic.py +20 -0
- scipy/fft/_helper.py +3 -34
- scipy/fft/_pocketfft/helper.py +29 -1
- scipy/fft/_pocketfft/pypocketfft.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/fft/_pocketfft/tests/test_basic.py +2 -4
- scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
- scipy/fft/_realtransforms.py +13 -0
- scipy/fft/tests/test_basic.py +27 -25
- scipy/fft/tests/test_fftlog.py +16 -7
- scipy/fft/tests/test_helper.py +18 -34
- scipy/fft/tests/test_real_transforms.py +8 -10
- scipy/fftpack/convolve.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/fftpack/tests/test_basic.py +2 -4
- scipy/fftpack/tests/test_real_transforms.py +8 -9
- scipy/integrate/_bvp.py +9 -3
- scipy/integrate/_cubature.py +3 -2
- scipy/integrate/_dop.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_lsoda.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_quadpack_py.py +11 -7
- scipy/integrate/_quadrature.py +3 -3
- scipy/integrate/_rules/_base.py +2 -2
- scipy/integrate/_tanhsinh.py +48 -47
- scipy/integrate/_test_multivariate.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_test_odeint_banded.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/_vode.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/integrate/tests/test__quad_vec.py +0 -6
- scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
- scipy/integrate/tests/test_cubature.py +21 -35
- scipy/integrate/tests/test_quadrature.py +6 -8
- scipy/integrate/tests/test_tanhsinh.py +56 -48
- scipy/interpolate/__init__.py +70 -58
- scipy/interpolate/_bary_rational.py +22 -22
- scipy/interpolate/_bsplines.py +119 -66
- scipy/interpolate/_cubic.py +65 -50
- scipy/interpolate/_dfitpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_dierckx.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_fitpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_fitpack2.py +9 -6
- scipy/interpolate/_fitpack_impl.py +32 -26
- scipy/interpolate/_fitpack_repro.py +23 -19
- scipy/interpolate/_interpnd.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_interpolate.py +30 -12
- scipy/interpolate/_ndbspline.py +13 -18
- scipy/interpolate/_ndgriddata.py +5 -8
- scipy/interpolate/_polyint.py +95 -31
- scipy/interpolate/_ppoly.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/interpolate/dfitpack.py +0 -20
- scipy/interpolate/interpnd.py +1 -2
- scipy/interpolate/tests/test_bary_rational.py +2 -2
- scipy/interpolate/tests/test_bsplines.py +97 -1
- scipy/interpolate/tests/test_fitpack2.py +39 -1
- scipy/interpolate/tests/test_interpnd.py +32 -20
- scipy/interpolate/tests/test_interpolate.py +48 -4
- scipy/interpolate/tests/test_rgi.py +2 -1
- scipy/io/_fast_matrix_market/__init__.py +2 -0
- scipy/io/_fast_matrix_market/_fmm_core.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
- scipy/io/_harwell_boeing/hb.py +7 -11
- scipy/io/_idl.py +5 -7
- scipy/io/_netcdf.py +15 -5
- scipy/io/_test_fortran.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/io/arff/tests/test_arffread.py +3 -3
- scipy/io/matlab/__init__.py +5 -3
- scipy/io/matlab/_mio.py +4 -1
- scipy/io/matlab/_mio5.py +19 -13
- scipy/io/matlab/_mio5_utils.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/io/matlab/_mio_utils.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/io/matlab/tests/test_mio.py +46 -18
- scipy/io/matlab/tests/test_mio_funcs.py +1 -1
- scipy/io/tests/test_mmio.py +7 -1
- scipy/io/tests/test_wavfile.py +41 -0
- scipy/io/wavfile.py +57 -10
- scipy/linalg/_basic.py +113 -86
- scipy/linalg/_cythonized_array_utils.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_decomp.py +22 -9
- scipy/linalg/_decomp_cholesky.py +28 -13
- scipy/linalg/_decomp_cossin.py +45 -30
- scipy/linalg/_decomp_interpolative.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_decomp_polar.py +2 -0
- scipy/linalg/_decomp_qr.py +6 -2
- scipy/linalg/_decomp_qz.py +3 -0
- scipy/linalg/_decomp_schur.py +3 -1
- scipy/linalg/_decomp_svd.py +13 -2
- scipy/linalg/_decomp_update.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_flapack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_linalg_pythran.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/cython_lapack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/linalg/lapack.py +22 -2
- scipy/linalg/tests/_cython_examples/meson.build +7 -0
- scipy/linalg/tests/test_basic.py +31 -16
- scipy/linalg/tests/test_batch.py +588 -0
- scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
- scipy/linalg/tests/test_decomp.py +40 -3
- scipy/linalg/tests/test_decomp_cossin.py +14 -0
- scipy/linalg/tests/test_decomp_ldl.py +1 -1
- scipy/linalg/tests/test_lapack.py +115 -7
- scipy/linalg/tests/test_matfuncs.py +157 -102
- scipy/linalg/tests/test_procrustes.py +0 -7
- scipy/linalg/tests/test_solve_toeplitz.py +1 -1
- scipy/linalg/tests/test_special_matrices.py +1 -5
- scipy/ndimage/__init__.py +1 -0
- scipy/ndimage/_ctest.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/ndimage/_cytest.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/ndimage/_delegators.py +8 -2
- scipy/ndimage/_filters.py +453 -5
- scipy/ndimage/_interpolation.py +36 -6
- scipy/ndimage/_measurements.py +4 -2
- scipy/ndimage/_morphology.py +5 -0
- scipy/ndimage/_nd_image.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/ndimage/_support_alternative_backends.py +18 -6
- scipy/ndimage/tests/test_filters.py +370 -259
- scipy/ndimage/tests/test_fourier.py +7 -9
- scipy/ndimage/tests/test_interpolation.py +68 -61
- scipy/ndimage/tests/test_measurements.py +18 -35
- scipy/ndimage/tests/test_morphology.py +143 -131
- scipy/ndimage/tests/test_splines.py +1 -3
- scipy/odr/__odrpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_bracket.py +17 -24
- scipy/optimize/_chandrupatla.py +9 -10
- scipy/optimize/_cobyla_py.py +104 -123
- scipy/optimize/_constraints.py +14 -10
- scipy/optimize/_differentiable_functions.py +371 -230
- scipy/optimize/_differentialevolution.py +4 -3
- scipy/optimize/_direct.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_highspy/_core.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_highspy/_highs_options.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_lbfgsb.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_lbfgsb_py.py +57 -16
- scipy/optimize/_linprog_doc.py +2 -2
- scipy/optimize/_linprog_highs.py +2 -2
- scipy/optimize/_linprog_ip.py +25 -10
- scipy/optimize/_linprog_util.py +14 -16
- scipy/optimize/_lsap.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_lsq/least_squares.py +198 -126
- scipy/optimize/_lsq/lsq_linear.py +6 -6
- scipy/optimize/_lsq/trf.py +35 -8
- scipy/optimize/_milp.py +3 -1
- scipy/optimize/_minimize.py +105 -36
- scipy/optimize/_minpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_nnls.py +20 -21
- scipy/optimize/_nonlin.py +34 -3
- scipy/optimize/_numdiff.py +288 -110
- scipy/optimize/_optimize.py +86 -48
- scipy/optimize/_pava_pybind.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_remove_redundancy.py +5 -5
- scipy/optimize/_root_scalar.py +1 -1
- scipy/optimize/_shgo.py +6 -0
- scipy/optimize/_shgo_lib/_complex.py +1 -1
- scipy/optimize/_slsqp_py.py +216 -124
- scipy/optimize/_slsqplib.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_trustregion.py +20 -6
- scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
- scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
- scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
- scipy/optimize/_trustregion_constr/projections.py +12 -8
- scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
- scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
- scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
- scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
- scipy/optimize/_trustregion_exact.py +0 -1
- scipy/optimize/_zeros.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/slsqp.py +0 -1
- scipy/optimize/tests/test__basinhopping.py +1 -1
- scipy/optimize/tests/test__differential_evolution.py +4 -4
- scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
- scipy/optimize/tests/test__numdiff.py +66 -22
- scipy/optimize/tests/test__remove_redundancy.py +2 -2
- scipy/optimize/tests/test__shgo.py +9 -1
- scipy/optimize/tests/test_bracket.py +36 -46
- scipy/optimize/tests/test_chandrupatla.py +133 -135
- scipy/optimize/tests/test_cobyla.py +74 -45
- scipy/optimize/tests/test_constraints.py +1 -1
- scipy/optimize/tests/test_differentiable_functions.py +226 -6
- scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
- scipy/optimize/tests/test_least_squares.py +125 -13
- scipy/optimize/tests/test_linear_assignment.py +3 -3
- scipy/optimize/tests/test_linprog.py +3 -3
- scipy/optimize/tests/test_lsq_linear.py +6 -6
- scipy/optimize/tests/test_minimize_constrained.py +2 -2
- scipy/optimize/tests/test_minpack.py +4 -4
- scipy/optimize/tests/test_nnls.py +43 -3
- scipy/optimize/tests/test_nonlin.py +36 -0
- scipy/optimize/tests/test_optimize.py +95 -17
- scipy/optimize/tests/test_slsqp.py +36 -4
- scipy/optimize/tests/test_zeros.py +34 -1
- scipy/signal/__init__.py +12 -23
- scipy/signal/_delegators.py +568 -0
- scipy/signal/_filter_design.py +459 -241
- scipy/signal/_fir_filter_design.py +262 -90
- scipy/signal/_lti_conversion.py +3 -2
- scipy/signal/_ltisys.py +118 -91
- scipy/signal/_max_len_seq_inner.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_peak_finding_utils.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_polyutils.py +172 -0
- scipy/signal/_short_time_fft.py +519 -70
- scipy/signal/_signal_api.py +30 -0
- scipy/signal/_signaltools.py +719 -399
- scipy/signal/_sigtools.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_sosfilt.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_spline_filters.py +108 -68
- scipy/signal/_support_alternative_backends.py +73 -0
- scipy/signal/_upfirdn.py +4 -1
- scipy/signal/_upfirdn_apply.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/signal/_waveforms.py +2 -11
- scipy/signal/_wavelets.py +1 -1
- scipy/signal/fir_filter_design.py +1 -0
- scipy/signal/spline.py +4 -11
- scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
- scipy/signal/tests/test_bsplines.py +114 -79
- scipy/signal/tests/test_cont2discrete.py +9 -2
- scipy/signal/tests/test_filter_design.py +721 -481
- scipy/signal/tests/test_fir_filter_design.py +332 -140
- scipy/signal/tests/test_savitzky_golay.py +4 -3
- scipy/signal/tests/test_short_time_fft.py +221 -3
- scipy/signal/tests/test_signaltools.py +2144 -1348
- scipy/signal/tests/test_spectral.py +50 -6
- scipy/signal/tests/test_splines.py +161 -96
- scipy/signal/tests/test_upfirdn.py +84 -50
- scipy/signal/tests/test_waveforms.py +20 -0
- scipy/signal/tests/test_windows.py +607 -466
- scipy/signal/windows/_windows.py +287 -148
- scipy/sparse/__init__.py +23 -4
- scipy/sparse/_base.py +270 -108
- scipy/sparse/_bsr.py +7 -4
- scipy/sparse/_compressed.py +59 -231
- scipy/sparse/_construct.py +90 -38
- scipy/sparse/_coo.py +115 -181
- scipy/sparse/_csc.py +4 -4
- scipy/sparse/_csparsetools.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/_csr.py +2 -2
- scipy/sparse/_data.py +48 -48
- scipy/sparse/_dia.py +105 -18
- scipy/sparse/_dok.py +0 -23
- scipy/sparse/_index.py +4 -4
- scipy/sparse/_matrix.py +23 -0
- scipy/sparse/_sparsetools.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/_sputils.py +37 -22
- scipy/sparse/base.py +0 -9
- scipy/sparse/bsr.py +0 -14
- scipy/sparse/compressed.py +0 -23
- scipy/sparse/construct.py +0 -6
- scipy/sparse/coo.py +0 -14
- scipy/sparse/csc.py +0 -3
- scipy/sparse/csgraph/_flow.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_matching.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_reordering.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_shortest_path.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_tools.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/_traversal.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/csgraph/tests/test_matching.py +14 -2
- scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
- scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
- scipy/sparse/csr.py +0 -5
- scipy/sparse/data.py +1 -6
- scipy/sparse/dia.py +0 -7
- scipy/sparse/dok.py +0 -10
- scipy/sparse/linalg/_dsolve/_superlu.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
- scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
- scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
- scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
- scipy/sparse/linalg/_interface.py +17 -18
- scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
- scipy/sparse/linalg/_isolve/iterative.py +51 -45
- scipy/sparse/linalg/_isolve/lgmres.py +6 -6
- scipy/sparse/linalg/_isolve/minres.py +5 -5
- scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
- scipy/sparse/linalg/_isolve/utils.py +2 -8
- scipy/sparse/linalg/_matfuncs.py +1 -1
- scipy/sparse/linalg/_norm.py +1 -1
- scipy/sparse/linalg/_propack/_cpropack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_propack/_spropack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
- scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
- scipy/sparse/tests/test_arithmetic1d.py +5 -2
- scipy/sparse/tests/test_base.py +214 -42
- scipy/sparse/tests/test_common1d.py +7 -7
- scipy/sparse/tests/test_construct.py +1 -1
- scipy/sparse/tests/test_coo.py +272 -4
- scipy/sparse/tests/test_sparsetools.py +5 -0
- scipy/sparse/tests/test_sputils.py +36 -7
- scipy/spatial/_ckdtree.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/_distance_pybind.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/_distance_wrap.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/_hausdorff.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/_qhull.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/_voronoi.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/distance.py +49 -42
- scipy/spatial/tests/test_distance.py +15 -1
- scipy/spatial/tests/test_kdtree.py +1 -0
- scipy/spatial/tests/test_qhull.py +7 -2
- scipy/spatial/transform/__init__.py +5 -3
- scipy/spatial/transform/_rigid_transform.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/transform/_rotation.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
- scipy/spatial/transform/tests/test_rotation.py +1213 -832
- scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
- scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
- scipy/special/__init__.py +1 -47
- scipy/special/_add_newdocs.py +34 -772
- scipy/special/_basic.py +22 -25
- scipy/special/_comb.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_ellip_harm_2.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_gufuncs.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_special_ufuncs.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/_ufuncs_cxx.pxd +2 -15
- scipy/special/_ufuncs_cxx.pyx +5 -44
- scipy/special/_ufuncs_cxx_defs.h +2 -16
- scipy/special/_ufuncs_defs.h +0 -8
- scipy/special/cython_special.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/special/cython_special.pxd +1 -1
- scipy/special/tests/_cython_examples/meson.build +10 -1
- scipy/special/tests/test_basic.py +153 -20
- scipy/special/tests/test_boost_ufuncs.py +3 -0
- scipy/special/tests/test_cdflib.py +35 -11
- scipy/special/tests/test_gammainc.py +16 -0
- scipy/special/tests/test_hyp2f1.py +2 -2
- scipy/special/tests/test_log1mexp.py +85 -0
- scipy/special/tests/test_logsumexp.py +206 -64
- scipy/special/tests/test_mpmath.py +1 -0
- scipy/special/tests/test_nan_inputs.py +1 -1
- scipy/special/tests/test_orthogonal.py +17 -18
- scipy/special/tests/test_sf_error.py +3 -2
- scipy/special/tests/test_sph_harm.py +6 -7
- scipy/special/tests/test_support_alternative_backends.py +211 -76
- scipy/stats/__init__.py +4 -1
- scipy/stats/_ansari_swilk_statistics.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_continued_fraction.py +387 -0
- scipy/stats/_continuous_distns.py +277 -310
- scipy/stats/_correlation.py +1 -1
- scipy/stats/_covariance.py +6 -3
- scipy/stats/_discrete_distns.py +39 -32
- scipy/stats/_distn_infrastructure.py +39 -12
- scipy/stats/_distribution_infrastructure.py +900 -238
- scipy/stats/_entropy.py +9 -10
- scipy/{_lib → stats}/_finite_differences.py +1 -1
- scipy/stats/_hypotests.py +83 -50
- scipy/stats/_kde.py +53 -49
- scipy/stats/_ksstats.py +1 -1
- scipy/stats/_levy_stable/__init__.py +7 -15
- scipy/stats/_levy_stable/levyst.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_morestats.py +118 -73
- scipy/stats/_mstats_basic.py +13 -17
- scipy/stats/_mstats_extras.py +8 -8
- scipy/stats/_multivariate.py +89 -113
- scipy/stats/_new_distributions.py +97 -20
- scipy/stats/_page_trend_test.py +12 -5
- scipy/stats/_probability_distribution.py +265 -43
- scipy/stats/_qmc.py +14 -9
- scipy/stats/_qmc_cy.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_stats.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
- scipy/stats/_variation.py +6 -8
- scipy/stats/_wilcoxon.py +13 -7
- scipy/stats/tests/common_tests.py +6 -4
- scipy/stats/tests/test_axis_nan_policy.py +62 -24
- scipy/stats/tests/test_continued_fraction.py +173 -0
- scipy/stats/tests/test_continuous.py +379 -60
- scipy/stats/tests/test_continuous_basic.py +18 -12
- scipy/stats/tests/test_discrete_basic.py +14 -8
- scipy/stats/tests/test_discrete_distns.py +16 -16
- scipy/stats/tests/test_distributions.py +95 -75
- scipy/stats/tests/test_entropy.py +40 -48
- scipy/stats/tests/test_fit.py +4 -3
- scipy/stats/tests/test_hypotests.py +153 -24
- scipy/stats/tests/test_kdeoth.py +109 -41
- scipy/stats/tests/test_marray.py +289 -0
- scipy/stats/tests/test_morestats.py +79 -47
- scipy/stats/tests/test_mstats_basic.py +3 -3
- scipy/stats/tests/test_multivariate.py +434 -83
- scipy/stats/tests/test_qmc.py +13 -10
- scipy/stats/tests/test_quantile.py +199 -0
- scipy/stats/tests/test_rank.py +119 -112
- scipy/stats/tests/test_resampling.py +47 -56
- scipy/stats/tests/test_sampling.py +9 -4
- scipy/stats/tests/test_stats.py +799 -939
- scipy/stats/tests/test_variation.py +8 -6
- scipy/version.py +2 -2
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +1262 -1269
- scipy.libs/libgcc_s-69c45f16.so.1 +0 -0
- scipy.libs/libgfortran-db0b6589.so.5.0.0 +0 -0
- scipy.libs/{libstdc++-1b614e01.so.6.0.32 → libstdc++-1f1a71be.so.6.0.33} +0 -0
- scipy/_lib/array_api_extra/_funcs.py +0 -484
- scipy/_lib/array_api_extra/_typing.py +0 -8
- scipy/interpolate/_bspl.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_cobyla.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_cython_nnls.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/optimize/_slsqp.cpython-312-aarch64-linux-musl.so +0 -0
- scipy/spatial/qhull_src/COPYING.txt +0 -38
- scipy/special/libsf_error_state.so +0 -0
- scipy/special/tests/test_log_softmax.py +0 -109
- scipy/special/tests/test_xsf_cuda.py +0 -114
- scipy/special/xsf/binom.h +0 -89
- scipy/special/xsf/cdflib.h +0 -100
- scipy/special/xsf/cephes/airy.h +0 -307
- scipy/special/xsf/cephes/besselpoly.h +0 -51
- scipy/special/xsf/cephes/beta.h +0 -257
- scipy/special/xsf/cephes/cbrt.h +0 -131
- scipy/special/xsf/cephes/chbevl.h +0 -85
- scipy/special/xsf/cephes/chdtr.h +0 -193
- scipy/special/xsf/cephes/const.h +0 -87
- scipy/special/xsf/cephes/ellie.h +0 -293
- scipy/special/xsf/cephes/ellik.h +0 -251
- scipy/special/xsf/cephes/ellpe.h +0 -107
- scipy/special/xsf/cephes/ellpk.h +0 -117
- scipy/special/xsf/cephes/expn.h +0 -260
- scipy/special/xsf/cephes/gamma.h +0 -398
- scipy/special/xsf/cephes/hyp2f1.h +0 -596
- scipy/special/xsf/cephes/hyperg.h +0 -361
- scipy/special/xsf/cephes/i0.h +0 -149
- scipy/special/xsf/cephes/i1.h +0 -158
- scipy/special/xsf/cephes/igam.h +0 -421
- scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
- scipy/special/xsf/cephes/igami.h +0 -313
- scipy/special/xsf/cephes/j0.h +0 -225
- scipy/special/xsf/cephes/j1.h +0 -198
- scipy/special/xsf/cephes/jv.h +0 -715
- scipy/special/xsf/cephes/k0.h +0 -164
- scipy/special/xsf/cephes/k1.h +0 -163
- scipy/special/xsf/cephes/kn.h +0 -243
- scipy/special/xsf/cephes/lanczos.h +0 -112
- scipy/special/xsf/cephes/ndtr.h +0 -275
- scipy/special/xsf/cephes/poch.h +0 -85
- scipy/special/xsf/cephes/polevl.h +0 -167
- scipy/special/xsf/cephes/psi.h +0 -194
- scipy/special/xsf/cephes/rgamma.h +0 -111
- scipy/special/xsf/cephes/scipy_iv.h +0 -811
- scipy/special/xsf/cephes/shichi.h +0 -248
- scipy/special/xsf/cephes/sici.h +0 -224
- scipy/special/xsf/cephes/sindg.h +0 -221
- scipy/special/xsf/cephes/tandg.h +0 -139
- scipy/special/xsf/cephes/trig.h +0 -58
- scipy/special/xsf/cephes/unity.h +0 -186
- scipy/special/xsf/cephes/zeta.h +0 -172
- scipy/special/xsf/config.h +0 -304
- scipy/special/xsf/digamma.h +0 -205
- scipy/special/xsf/error.h +0 -57
- scipy/special/xsf/evalpoly.h +0 -47
- scipy/special/xsf/expint.h +0 -266
- scipy/special/xsf/hyp2f1.h +0 -694
- scipy/special/xsf/iv_ratio.h +0 -173
- scipy/special/xsf/lambertw.h +0 -150
- scipy/special/xsf/loggamma.h +0 -163
- scipy/special/xsf/sici.h +0 -200
- scipy/special/xsf/tools.h +0 -427
- scipy/special/xsf/trig.h +0 -164
- scipy/special/xsf/wright_bessel.h +0 -843
- scipy/special/xsf/zlog1.h +0 -35
- scipy/stats/_mvn.cpython-312-aarch64-linux-musl.so +0 -0
- scipy.libs/libgcc_s-7393e603.so.1 +0 -0
- scipy.libs/libgfortran-eb933d8e.so.5.0.0 +0 -0
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/WHEEL +0 -0
@@ -3,6 +3,7 @@ Test functions for multivariate normal distributions.
|
|
3
3
|
|
4
4
|
"""
|
5
5
|
import pickle
|
6
|
+
from dataclasses import dataclass
|
6
7
|
|
7
8
|
from numpy.testing import (assert_allclose, assert_almost_equal,
|
8
9
|
assert_array_almost_equal, assert_equal,
|
@@ -29,11 +30,13 @@ from scipy.stats import (multivariate_normal, multivariate_hypergeom,
|
|
29
30
|
dirichlet_multinomial, vonmises)
|
30
31
|
|
31
32
|
from scipy.stats import _covariance, Covariance
|
33
|
+
from scipy.stats._continuous_distns import _norm_pdf as norm_pdf
|
32
34
|
from scipy import stats
|
33
35
|
|
34
|
-
from scipy.integrate import tanhsinh
|
36
|
+
from scipy.integrate import tanhsinh, cubature, quad
|
35
37
|
from scipy.integrate import romb, qmc_quad, dblquad, tplquad
|
36
38
|
from scipy.special import multigammaln
|
39
|
+
import scipy.special as special
|
37
40
|
|
38
41
|
from .common_tests import check_random_state_property
|
39
42
|
from .data._mvt import _qsimvtv
|
@@ -291,6 +294,231 @@ def _sample_orthonormal_matrix(n):
|
|
291
294
|
return u
|
292
295
|
|
293
296
|
|
297
|
+
@dataclass
|
298
|
+
class MVNProblem:
|
299
|
+
"""Instantiate a multivariate normal integration problem with special structure.
|
300
|
+
|
301
|
+
When covariance matrix is a correlation matrix where the off-diagonal entries
|
302
|
+
``covar[i, j] == lambdas[i]*lambdas[j]`` for ``i != j``, then the multidimensional
|
303
|
+
integral reduces to a simpler univariate integral that can be numerically integrated
|
304
|
+
easily.
|
305
|
+
|
306
|
+
The ``generate_*()`` classmethods provide a few options for creating variations
|
307
|
+
of this problem.
|
308
|
+
|
309
|
+
References
|
310
|
+
----------
|
311
|
+
.. [1] Tong, Y.L. "The Multivariate Normal Distribution".
|
312
|
+
Springer-Verlag. p192. 1990.
|
313
|
+
"""
|
314
|
+
ndim : int
|
315
|
+
low : np.ndarray
|
316
|
+
high : np.ndarray
|
317
|
+
lambdas : np.ndarray
|
318
|
+
covar : np.ndarray
|
319
|
+
target_val : float
|
320
|
+
target_err : float
|
321
|
+
|
322
|
+
#: The `generator_halves()` case has an analytically-known true value that we'll
|
323
|
+
#: record here. It remain None for most cases, though.
|
324
|
+
true_val : float | None = None
|
325
|
+
|
326
|
+
def __init__(self, ndim, low, high, lambdas):
|
327
|
+
super().__init__()
|
328
|
+
self.ndim = ndim
|
329
|
+
self.low = low
|
330
|
+
self.high = high
|
331
|
+
self.lambdas = lambdas
|
332
|
+
|
333
|
+
self.covar = np.outer(self.lambdas, self.lambdas)
|
334
|
+
np.fill_diagonal(self.covar, 1.0)
|
335
|
+
self.find_target()
|
336
|
+
|
337
|
+
@classmethod
|
338
|
+
def generate_semigeneral(cls, ndim, rng=None):
|
339
|
+
"""Random lambdas, random upper bounds, infinite lower bounds.
|
340
|
+
"""
|
341
|
+
rng = np.random.default_rng(rng)
|
342
|
+
low = np.full(ndim, -np.inf)
|
343
|
+
high = rng.uniform(0.0, np.sqrt(ndim), size=ndim)
|
344
|
+
lambdas = rng.uniform(-1.0, 1.0, size=ndim)
|
345
|
+
|
346
|
+
self = cls(
|
347
|
+
ndim=ndim,
|
348
|
+
low=low,
|
349
|
+
high=high,
|
350
|
+
lambdas=lambdas,
|
351
|
+
)
|
352
|
+
return self
|
353
|
+
|
354
|
+
@classmethod
|
355
|
+
def generate_constant(cls, ndim, rng=None):
|
356
|
+
"""Constant off-diagonal covariance, random upper bounds, infinite lower bounds.
|
357
|
+
"""
|
358
|
+
rng = np.random.default_rng(rng)
|
359
|
+
low = np.full(ndim, -np.inf)
|
360
|
+
high = rng.uniform(0.0, np.sqrt(ndim), size=ndim)
|
361
|
+
sigma = np.sqrt(rng.uniform(0.0, 1.0))
|
362
|
+
lambdas = np.full(ndim, sigma)
|
363
|
+
|
364
|
+
self = cls(
|
365
|
+
ndim=ndim,
|
366
|
+
low=low,
|
367
|
+
high=high,
|
368
|
+
lambdas=lambdas,
|
369
|
+
)
|
370
|
+
return self
|
371
|
+
|
372
|
+
@classmethod
|
373
|
+
def generate_halves(cls, ndim, rng=None):
|
374
|
+
"""Off-diagonal covariance of 0.5, negative orthant bounds.
|
375
|
+
|
376
|
+
True analytically-derived answer is 1/(ndim+1).
|
377
|
+
"""
|
378
|
+
low = np.full(ndim, -np.inf)
|
379
|
+
high = np.zeros(ndim)
|
380
|
+
lambdas = np.sqrt(0.5)
|
381
|
+
|
382
|
+
self = cls(
|
383
|
+
ndim=ndim,
|
384
|
+
low=low,
|
385
|
+
high=high,
|
386
|
+
lambdas=lambdas,
|
387
|
+
)
|
388
|
+
self.true_val = 1 / (ndim+1)
|
389
|
+
return self
|
390
|
+
|
391
|
+
def find_target(self, **kwds):
|
392
|
+
"""Perform the simplified integral and store the results.
|
393
|
+
"""
|
394
|
+
d = dict(
|
395
|
+
a=-9.0,
|
396
|
+
b=+9.0,
|
397
|
+
)
|
398
|
+
d.update(kwds)
|
399
|
+
self.target_val, self.target_err = quad(self.univariate_func, **d)
|
400
|
+
|
401
|
+
def _univariate_term(self, t):
|
402
|
+
"""The parameter-specific term of the univariate integrand,
|
403
|
+
for separate plotting.
|
404
|
+
"""
|
405
|
+
denom = np.sqrt(1 - self.lambdas**2)
|
406
|
+
return np.prod(
|
407
|
+
special.ndtr((self.high + self.lambdas*t[:, np.newaxis]) / denom) -
|
408
|
+
special.ndtr((self.low + self.lambdas*t[:, np.newaxis]) / denom),
|
409
|
+
axis=1,
|
410
|
+
)
|
411
|
+
|
412
|
+
def univariate_func(self, t):
|
413
|
+
"""Univariate integrand.
|
414
|
+
"""
|
415
|
+
t = np.atleast_1d(t)
|
416
|
+
return np.squeeze(norm_pdf(t) * self._univariate_term(t))
|
417
|
+
|
418
|
+
def plot_integrand(self):
|
419
|
+
"""Plot the univariate integrand and its component terms for understanding.
|
420
|
+
"""
|
421
|
+
from matplotlib import pyplot as plt
|
422
|
+
|
423
|
+
t = np.linspace(-9.0, 9.0, 1001)
|
424
|
+
plt.plot(t, norm_pdf(t), label=r'$\phi(t)$')
|
425
|
+
plt.plot(t, self._univariate_term(t), label=r'$f(t)$')
|
426
|
+
plt.plot(t, self.univariate_func(t), label=r'$f(t)*phi(t)$')
|
427
|
+
plt.legend()
|
428
|
+
|
429
|
+
|
430
|
+
@dataclass
|
431
|
+
class SingularMVNProblem:
|
432
|
+
"""Instantiate a multivariate normal integration problem with a special singular
|
433
|
+
covariance structure.
|
434
|
+
|
435
|
+
When covariance matrix is a correlation matrix where the off-diagonal entries
|
436
|
+
``covar[i, j] == -lambdas[i]*lambdas[j]`` for ``i != j``, and
|
437
|
+
``sum(lambdas**2 / (1+lambdas**2)) == 1``, then the matrix is singular, and
|
438
|
+
the multidimensional integral reduces to a simpler univariate integral that
|
439
|
+
can be numerically integrated fairly easily.
|
440
|
+
|
441
|
+
The lower bound must be infinite, though the upper bounds can be general.
|
442
|
+
|
443
|
+
References
|
444
|
+
----------
|
445
|
+
.. [1] Kwong, K.-S. (1995). "Evaluation of the one-sided percentage points of the
|
446
|
+
singular multivariate normal distribution." Journal of Statistical
|
447
|
+
Computation and Simulation, 51(2-4), 121-135. doi:10.1080/00949659508811627
|
448
|
+
"""
|
449
|
+
ndim : int
|
450
|
+
low : np.ndarray
|
451
|
+
high : np.ndarray
|
452
|
+
lambdas : np.ndarray
|
453
|
+
covar : np.ndarray
|
454
|
+
target_val : float
|
455
|
+
target_err : float
|
456
|
+
|
457
|
+
def __init__(self, ndim, high, lambdas):
|
458
|
+
self.ndim = ndim
|
459
|
+
self.high = high
|
460
|
+
self.lambdas = lambdas
|
461
|
+
|
462
|
+
self.low = np.full(ndim, -np.inf)
|
463
|
+
self.covar = -np.outer(self.lambdas, self.lambdas)
|
464
|
+
np.fill_diagonal(self.covar, 1.0)
|
465
|
+
self.find_target()
|
466
|
+
|
467
|
+
@classmethod
|
468
|
+
def generate_semiinfinite(cls, ndim, rng=None):
|
469
|
+
"""Singular lambdas, random upper bounds.
|
470
|
+
"""
|
471
|
+
rng = np.random.default_rng(rng)
|
472
|
+
high = rng.uniform(0.0, np.sqrt(ndim), size=ndim)
|
473
|
+
p = rng.dirichlet(np.full(ndim, 1.0))
|
474
|
+
lambdas = np.sqrt(p / (1-p)) * rng.choice([-1.0, 1.0], size=ndim)
|
475
|
+
|
476
|
+
self = cls(
|
477
|
+
ndim=ndim,
|
478
|
+
high=high,
|
479
|
+
lambdas=lambdas,
|
480
|
+
)
|
481
|
+
return self
|
482
|
+
|
483
|
+
def find_target(self, **kwds):
|
484
|
+
d = dict(
|
485
|
+
a=-9.0,
|
486
|
+
b=+9.0,
|
487
|
+
)
|
488
|
+
d.update(kwds)
|
489
|
+
self.target_val, self.target_err = quad(self.univariate_func, **d)
|
490
|
+
|
491
|
+
def _univariate_term(self, t):
|
492
|
+
denom = np.sqrt(1 + self.lambdas**2)
|
493
|
+
i1 = np.prod(
|
494
|
+
special.ndtr((self.high - 1j*self.lambdas*t[:, np.newaxis]) / denom),
|
495
|
+
axis=1,
|
496
|
+
)
|
497
|
+
i2 = np.prod(
|
498
|
+
special.ndtr((-self.high + 1j*self.lambdas*t[:, np.newaxis]) / denom),
|
499
|
+
axis=1,
|
500
|
+
)
|
501
|
+
# The imaginary part is an odd function, so it can be ignored; it will integrate
|
502
|
+
# out to 0.
|
503
|
+
return (i1 - (-1)**self.ndim * i2).real
|
504
|
+
|
505
|
+
def univariate_func(self, t):
|
506
|
+
t = np.atleast_1d(t)
|
507
|
+
return (norm_pdf(t) * self._univariate_term(t)).squeeze()
|
508
|
+
|
509
|
+
def plot_integrand(self):
|
510
|
+
"""Plot the univariate integrand and its component terms for understanding.
|
511
|
+
"""
|
512
|
+
from matplotlib import pyplot as plt
|
513
|
+
|
514
|
+
t = np.linspace(-9.0, 9.0, 1001)
|
515
|
+
plt.plot(t, norm_pdf(t), label=r'$\phi(t)$')
|
516
|
+
plt.plot(t, self._univariate_term(t), label=r'$f(t)$')
|
517
|
+
plt.plot(t, self.univariate_func(t), label=r'$f(t)*phi(t)$')
|
518
|
+
plt.ylim(-0.1, 1.1)
|
519
|
+
plt.legend()
|
520
|
+
|
521
|
+
|
294
522
|
class TestMultivariateNormal:
|
295
523
|
def test_input_shape(self):
|
296
524
|
mu = np.arange(3)
|
@@ -483,17 +711,17 @@ class TestMultivariateNormal:
|
|
483
711
|
assert_allclose(psd.log_pdet, large_total_log)
|
484
712
|
|
485
713
|
def test_broadcasting(self):
|
486
|
-
np.random.
|
714
|
+
rng = np.random.RandomState(1234)
|
487
715
|
n = 4
|
488
716
|
|
489
717
|
# Construct a random covariance matrix.
|
490
|
-
data =
|
718
|
+
data = rng.randn(n, n)
|
491
719
|
cov = np.dot(data, data.T)
|
492
|
-
mean =
|
720
|
+
mean = rng.randn(n)
|
493
721
|
|
494
722
|
# Construct an ndarray which can be interpreted as
|
495
723
|
# a 2x3 array whose elements are random data vectors.
|
496
|
-
X =
|
724
|
+
X = rng.randn(2, 3, n)
|
497
725
|
|
498
726
|
# Check that multiple data points can be evaluated at once.
|
499
727
|
desired_pdf = multivariate_normal.pdf(X, mean, cov)
|
@@ -724,25 +952,25 @@ class TestMultivariateNormal:
|
|
724
952
|
# Generate large sample and compare sample mean and sample covariance
|
725
953
|
# with mean and covariance matrix.
|
726
954
|
|
727
|
-
np.random.
|
955
|
+
rng = np.random.RandomState(2846)
|
728
956
|
|
729
957
|
n = 3
|
730
|
-
mean =
|
731
|
-
M =
|
958
|
+
mean = rng.randn(n)
|
959
|
+
M = rng.randn(n, n)
|
732
960
|
cov = np.dot(M, M.T)
|
733
961
|
size = 5000
|
734
962
|
|
735
|
-
sample = multivariate_normal.rvs(mean, cov, size)
|
963
|
+
sample = multivariate_normal.rvs(mean, cov, size, random_state=rng)
|
736
964
|
|
737
965
|
assert_allclose(np.cov(sample.T), cov, rtol=1e-1)
|
738
966
|
assert_allclose(sample.mean(0), mean, rtol=1e-1)
|
739
967
|
|
740
968
|
def test_entropy(self):
|
741
|
-
np.random.
|
969
|
+
rng = np.random.RandomState(2846)
|
742
970
|
|
743
971
|
n = 3
|
744
|
-
mean =
|
745
|
-
M =
|
972
|
+
mean = rng.randn(n)
|
973
|
+
M = rng.randn(n, n)
|
746
974
|
cov = np.dot(M, M.T)
|
747
975
|
|
748
976
|
rv = multivariate_normal(mean, cov)
|
@@ -810,6 +1038,70 @@ class TestMultivariateNormal:
|
|
810
1038
|
cdf = multivariate_normal.cdf(b, mean, cov, lower_limit=a)
|
811
1039
|
assert_allclose(cdf, cdf[0]*expected_signs)
|
812
1040
|
|
1041
|
+
@pytest.mark.slow
|
1042
|
+
def test_cdf_vs_cubature(self):
|
1043
|
+
ndim = 3
|
1044
|
+
rng = np.random.default_rng(123)
|
1045
|
+
a = rng.uniform(size=(ndim, ndim))
|
1046
|
+
cov = a.T @ a
|
1047
|
+
m = rng.uniform(size=ndim)
|
1048
|
+
dist = multivariate_normal(mean=m, cov=cov)
|
1049
|
+
x = rng.uniform(low=-3, high=3, size=(ndim,))
|
1050
|
+
cdf = dist.cdf(x)
|
1051
|
+
dist_i = multivariate_normal(mean=[0]*ndim, cov=cov)
|
1052
|
+
cdf_i = cubature(dist_i.pdf, [-np.inf]*ndim, x - m).estimate
|
1053
|
+
assert_allclose(cdf, cdf_i, atol=5e-6)
|
1054
|
+
|
1055
|
+
def test_cdf_known(self):
|
1056
|
+
# https://github.com/scipy/scipy/pull/17410#issuecomment-1312628547
|
1057
|
+
for ndim in range(2, 12):
|
1058
|
+
cov = np.full((ndim, ndim), 0.5)
|
1059
|
+
np.fill_diagonal(cov, 1.)
|
1060
|
+
dist = multivariate_normal([0]*ndim, cov=cov)
|
1061
|
+
assert_allclose(
|
1062
|
+
dist.cdf([0]*ndim),
|
1063
|
+
1. / (1. + ndim),
|
1064
|
+
atol=5e-5
|
1065
|
+
)
|
1066
|
+
|
1067
|
+
@pytest.mark.parametrize("ndim", range(2, 10))
|
1068
|
+
@pytest.mark.parametrize("seed", [0xdeadbeef, 0xdd24528764c9773579731c6b022b48e2])
|
1069
|
+
def test_cdf_vs_univariate(self, seed, ndim):
|
1070
|
+
rng = np.random.default_rng(seed)
|
1071
|
+
case = MVNProblem.generate_semigeneral(ndim=ndim, rng=rng)
|
1072
|
+
assert (case.low == -np.inf).all()
|
1073
|
+
|
1074
|
+
dist = multivariate_normal(mean=[0]*ndim, cov=case.covar)
|
1075
|
+
cdf_val = dist.cdf(case.high, rng=rng)
|
1076
|
+
assert_allclose(cdf_val, case.target_val, atol=5e-5)
|
1077
|
+
|
1078
|
+
@pytest.mark.parametrize("ndim", range(2, 11))
|
1079
|
+
@pytest.mark.parametrize("seed", [0xdeadbeef, 0xdd24528764c9773579731c6b022b48e2])
|
1080
|
+
def test_cdf_vs_univariate_2(self, seed, ndim):
|
1081
|
+
rng = np.random.default_rng(seed)
|
1082
|
+
case = MVNProblem.generate_constant(ndim=ndim, rng=rng)
|
1083
|
+
assert (case.low == -np.inf).all()
|
1084
|
+
|
1085
|
+
dist = multivariate_normal(mean=[0]*ndim, cov=case.covar)
|
1086
|
+
cdf_val = dist.cdf(case.high, rng=rng)
|
1087
|
+
assert_allclose(cdf_val, case.target_val, atol=5e-5)
|
1088
|
+
|
1089
|
+
@pytest.mark.parametrize("ndim", range(4, 11))
|
1090
|
+
@pytest.mark.parametrize("seed", [0xdeadbeef, 0xdd24528764c9773579731c6b022b48e4])
|
1091
|
+
def test_cdf_vs_univariate_singular(self, seed, ndim):
|
1092
|
+
# NB: ndim = 2, 3 has much poorer accuracy than ndim > 3 for many seeds.
|
1093
|
+
# No idea why.
|
1094
|
+
rng = np.random.default_rng(seed)
|
1095
|
+
case = SingularMVNProblem.generate_semiinfinite(ndim=ndim, rng=rng)
|
1096
|
+
assert (case.low == -np.inf).all()
|
1097
|
+
|
1098
|
+
dist = multivariate_normal(mean=[0]*ndim, cov=case.covar, allow_singular=True,
|
1099
|
+
# default maxpts is too slow, limit it here
|
1100
|
+
maxpts=10_000*case.covar.shape[0]
|
1101
|
+
)
|
1102
|
+
cdf_val = dist.cdf(case.high, rng=rng)
|
1103
|
+
assert_allclose(cdf_val, case.target_val, atol=1e-3)
|
1104
|
+
|
813
1105
|
def test_mean_cov(self):
|
814
1106
|
# test the interaction between a Covariance object and mean
|
815
1107
|
P = np.diag(1 / np.array([1, 2, 3]))
|
@@ -1495,22 +1787,22 @@ class TestWishart:
|
|
1495
1787
|
w = wishart(df, scale)
|
1496
1788
|
|
1497
1789
|
# Get the generated random variables from a known seed
|
1498
|
-
np.random.
|
1499
|
-
w_rvs = wishart.rvs(df, scale)
|
1500
|
-
np.random.
|
1501
|
-
frozen_w_rvs = w.rvs()
|
1790
|
+
rng = np.random.RandomState(248042)
|
1791
|
+
w_rvs = wishart.rvs(df, scale, random_state=rng)
|
1792
|
+
rng = np.random.RandomState(248042)
|
1793
|
+
frozen_w_rvs = w.rvs(random_state=rng)
|
1502
1794
|
|
1503
1795
|
# Manually calculate what it should be, based on the Bartlett (1933)
|
1504
1796
|
# decomposition of a Wishart into D A A' D', where D is the Cholesky
|
1505
1797
|
# factorization of the scale matrix and A is the lower triangular matrix
|
1506
1798
|
# with the square root of chi^2 variates on the diagonal and N(0,1)
|
1507
1799
|
# variates in the lower triangle.
|
1508
|
-
np.random.
|
1509
|
-
covariances =
|
1800
|
+
rng = np.random.RandomState(248042)
|
1801
|
+
covariances = rng.normal(size=3)
|
1510
1802
|
variances = np.r_[
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1803
|
+
rng.chisquare(df),
|
1804
|
+
rng.chisquare(df-1),
|
1805
|
+
rng.chisquare(df-2),
|
1514
1806
|
]**0.5
|
1515
1807
|
|
1516
1808
|
# Construct the lower-triangular A matrix
|
@@ -1531,7 +1823,7 @@ class TestWishart:
|
|
1531
1823
|
# chi-squared distribution.
|
1532
1824
|
# Test variance, mean, entropy, pdf
|
1533
1825
|
# Kolgomorov-Smirnov test for rvs
|
1534
|
-
np.random.
|
1826
|
+
rng = np.random.default_rng(482974)
|
1535
1827
|
|
1536
1828
|
sn = 500
|
1537
1829
|
dim = 1
|
@@ -1552,7 +1844,7 @@ class TestWishart:
|
|
1552
1844
|
assert_allclose(w.pdf(X), c.pdf(X))
|
1553
1845
|
|
1554
1846
|
# rvs
|
1555
|
-
rvs = w.rvs(size=sn)
|
1847
|
+
rvs = w.rvs(size=sn, random_state=rng)
|
1556
1848
|
args = (df,)
|
1557
1849
|
alpha = 0.01
|
1558
1850
|
check_distribution_rvs('chi2', args, alpha, rvs)
|
@@ -1562,7 +1854,7 @@ class TestWishart:
|
|
1562
1854
|
# transformed to a scaled chi-squared distribution.
|
1563
1855
|
# For :math:`S \sim W_p(V,n)` and :math:`\lambda \in \mathbb{R}^p` we have
|
1564
1856
|
# :math:`\lambda' S \lambda \sim \lambda' V \lambda \times \chi^2(n)`
|
1565
|
-
np.random.
|
1857
|
+
rng = np.random.default_rng(482974)
|
1566
1858
|
|
1567
1859
|
sn = 500
|
1568
1860
|
df = 10
|
@@ -1587,7 +1879,7 @@ class TestWishart:
|
|
1587
1879
|
assert_allclose(w.pdf(X), c.pdf(X))
|
1588
1880
|
|
1589
1881
|
# rvs
|
1590
|
-
rvs = w.rvs(size=sn)
|
1882
|
+
rvs = w.rvs(size=sn, random_state=rng)
|
1591
1883
|
args = (df,0,sigma_lamda)
|
1592
1884
|
alpha = 0.01
|
1593
1885
|
check_distribution_rvs('chi2', args, alpha, rvs)
|
@@ -1637,10 +1929,17 @@ class TestMultinomial:
|
|
1637
1929
|
@pytest.mark.parametrize("n", [0, 3])
|
1638
1930
|
def test_rvs_np(self, n):
|
1639
1931
|
# test that .rvs agrees w/numpy
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1932
|
+
message = "Some rows of `p` do not sum to 1.0 within..."
|
1933
|
+
with pytest.warns(FutureWarning, match=message):
|
1934
|
+
rndm = np.random.RandomState(123)
|
1935
|
+
sc_rvs = multinomial.rvs(n, [1/4.]*3, size=7, random_state=123)
|
1936
|
+
np_rvs = rndm.multinomial(n, [1/4.]*3, size=7)
|
1937
|
+
assert_equal(sc_rvs, np_rvs)
|
1938
|
+
with pytest.warns(FutureWarning, match=message):
|
1939
|
+
rndm = np.random.RandomState(123)
|
1940
|
+
sc_rvs = multinomial.rvs(n, [1/4.]*5, size=7, random_state=123)
|
1941
|
+
np_rvs = rndm.multinomial(n, [1/4.]*5, size=7)
|
1942
|
+
assert_equal(sc_rvs, np_rvs)
|
1644
1943
|
|
1645
1944
|
def test_pmf(self):
|
1646
1945
|
vals0 = multinomial.pmf((5,), 5, (1,))
|
@@ -1715,7 +2014,7 @@ class TestMultinomial:
|
|
1715
2014
|
assert_allclose(ent0, binom.entropy(n, .2), rtol=1e-8)
|
1716
2015
|
|
1717
2016
|
def test_entropy_broadcasting(self):
|
1718
|
-
ent0 = multinomial.entropy([2, 3], [.2, .
|
2017
|
+
ent0 = multinomial.entropy([2, 3], [.2, .8])
|
1719
2018
|
assert_allclose(ent0, [binom.entropy(2, .2), binom.entropy(3, .2)],
|
1720
2019
|
rtol=1e-8)
|
1721
2020
|
|
@@ -1764,6 +2063,17 @@ class TestMultinomial:
|
|
1764
2063
|
logpmf = multinomial.logpmf(x, n, p)
|
1765
2064
|
assert np.isfinite(logpmf)
|
1766
2065
|
|
2066
|
+
@pytest.mark.parametrize('dtype', [np.float32, np.float64])
|
2067
|
+
def test_gh_22565(self, dtype):
|
2068
|
+
# Same issue as gh-11860 above, essentially, but the original
|
2069
|
+
# fix didn't completely solve the problem.
|
2070
|
+
n = 19
|
2071
|
+
p = np.asarray([0.2, 0.2, 0.2, 0.2, 0.2], dtype=dtype)
|
2072
|
+
res1 = multinomial.pmf(x=[1, 2, 5, 7, 4], n=n, p=p)
|
2073
|
+
res2 = multinomial.pmf(x=[1, 2, 4, 5, 7], n=n, p=p)
|
2074
|
+
np.testing.assert_allclose(res1, res2, rtol=1e-15)
|
2075
|
+
|
2076
|
+
|
1767
2077
|
class TestInvwishart:
|
1768
2078
|
def test_frozen(self):
|
1769
2079
|
# Test that the frozen and non-frozen inverse Wishart gives the same
|
@@ -1802,7 +2112,7 @@ class TestInvwishart:
|
|
1802
2112
|
# just an inverse gamma distribution.
|
1803
2113
|
# Test variance, mean, pdf, entropy
|
1804
2114
|
# Kolgomorov-Smirnov test for rvs
|
1805
|
-
np.random.
|
2115
|
+
rng = np.random.RandomState(482974)
|
1806
2116
|
|
1807
2117
|
sn = 500
|
1808
2118
|
dim = 1
|
@@ -1822,7 +2132,7 @@ class TestInvwishart:
|
|
1822
2132
|
assert_allclose(iw.pdf(X), ig.pdf(X))
|
1823
2133
|
|
1824
2134
|
# rvs
|
1825
|
-
rvs = iw.rvs(size=sn)
|
2135
|
+
rvs = iw.rvs(size=sn, random_state=rng)
|
1826
2136
|
args = (df/2, 0, 1./2)
|
1827
2137
|
alpha = 0.01
|
1828
2138
|
check_distribution_rvs('invgamma', args, alpha, rvs)
|
@@ -1843,10 +2153,10 @@ class TestInvwishart:
|
|
1843
2153
|
iw = invwishart(df, scale)
|
1844
2154
|
|
1845
2155
|
# Get the generated random variables from a known seed
|
1846
|
-
np.random.
|
1847
|
-
iw_rvs = invwishart.rvs(df, scale)
|
1848
|
-
np.random.
|
1849
|
-
frozen_iw_rvs = iw.rvs()
|
2156
|
+
rng = np.random.RandomState(608072)
|
2157
|
+
iw_rvs = invwishart.rvs(df, scale, random_state=rng)
|
2158
|
+
rng = np.random.RandomState(608072)
|
2159
|
+
frozen_iw_rvs = iw.rvs(random_state=rng)
|
1850
2160
|
|
1851
2161
|
# Manually calculate what it should be, based on the decomposition in
|
1852
2162
|
# https://arxiv.org/abs/2310.15884 of an invers-Wishart into L L',
|
@@ -1855,12 +2165,12 @@ class TestInvwishart:
|
|
1855
2165
|
# variates on the diagonal and N(0,1) variates in the lower triangle.
|
1856
2166
|
# the diagonal chi^2 variates in this A are reversed compared to those
|
1857
2167
|
# in the Bartlett decomposition A for Wishart rvs.
|
1858
|
-
np.random.
|
1859
|
-
covariances =
|
2168
|
+
rng = np.random.RandomState(608072)
|
2169
|
+
covariances = rng.normal(size=3)
|
1860
2170
|
variances = np.r_[
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
2171
|
+
rng.chisquare(df-2),
|
2172
|
+
rng.chisquare(df-1),
|
2173
|
+
rng.chisquare(df),
|
1864
2174
|
]**0.5
|
1865
2175
|
|
1866
2176
|
# Construct the lower-triangular A matrix
|
@@ -1930,21 +2240,16 @@ class TestInvwishart:
|
|
1930
2240
|
|
1931
2241
|
class TestSpecialOrthoGroup:
|
1932
2242
|
def test_reproducibility(self):
|
1933
|
-
np.random.
|
1934
|
-
|
1935
|
-
|
1936
|
-
[0.
|
1937
|
-
[0.09873351, 0.03177334, 0.99460653]])
|
1938
|
-
assert_array_almost_equal(x, expected)
|
1939
|
-
|
1940
|
-
random_state = np.random.RandomState(seed=514)
|
1941
|
-
x = special_ortho_group.rvs(3, random_state=random_state)
|
2243
|
+
x = special_ortho_group.rvs(3, random_state=np.random.default_rng(514))
|
2244
|
+
expected = np.array([[-0.93200988, 0.01533561, -0.36210826],
|
2245
|
+
[0.35742128, 0.20446501, -0.91128705],
|
2246
|
+
[0.06006333, -0.97875374, -0.19604469]])
|
1942
2247
|
assert_array_almost_equal(x, expected)
|
1943
2248
|
|
1944
2249
|
def test_invalid_dim(self):
|
1945
2250
|
assert_raises(ValueError, special_ortho_group.rvs, None)
|
1946
2251
|
assert_raises(ValueError, special_ortho_group.rvs, (2, 2))
|
1947
|
-
assert_raises(ValueError, special_ortho_group.rvs, 1)
|
2252
|
+
assert_raises(ValueError, special_ortho_group.rvs, -1)
|
1948
2253
|
assert_raises(ValueError, special_ortho_group.rvs, 2.5)
|
1949
2254
|
|
1950
2255
|
def test_frozen_matrix(self):
|
@@ -1979,8 +2284,9 @@ class TestSpecialOrthoGroup:
|
|
1979
2284
|
dim = 5
|
1980
2285
|
samples = 1000 # Not too many, or the test takes too long
|
1981
2286
|
ks_prob = .05
|
1982
|
-
|
1983
|
-
|
2287
|
+
xs = special_ortho_group.rvs(
|
2288
|
+
dim, size=samples, random_state=np.random.default_rng(513)
|
2289
|
+
)
|
1984
2290
|
|
1985
2291
|
# Dot a few rows (0, 1, 2) with unit vectors (0, 2, 4, 3),
|
1986
2292
|
# effectively picking off entries in the matrices of xs.
|
@@ -1997,12 +2303,20 @@ class TestSpecialOrthoGroup:
|
|
1997
2303
|
ks_tests = [ks_2samp(proj[p0], proj[p1])[1] for (p0, p1) in pairs]
|
1998
2304
|
assert_array_less([ks_prob]*len(pairs), ks_tests)
|
1999
2305
|
|
2306
|
+
def test_one_by_one(self):
|
2307
|
+
# Test that the distribution is a delta function at the identity matrix
|
2308
|
+
# when dim=1
|
2309
|
+
assert_allclose(special_ortho_group.rvs(1, size=1000), 1, rtol=1e-13)
|
2310
|
+
|
2311
|
+
def test_zero_by_zero(self):
|
2312
|
+
assert_equal(special_ortho_group.rvs(0, size=4).shape, (4, 0, 0))
|
2313
|
+
|
2000
2314
|
|
2001
2315
|
class TestOrthoGroup:
|
2002
2316
|
def test_reproducibility(self):
|
2003
2317
|
seed = 514
|
2004
|
-
np.random.
|
2005
|
-
x = ortho_group.rvs(3)
|
2318
|
+
rng = np.random.RandomState(seed)
|
2319
|
+
x = ortho_group.rvs(3, random_state=rng)
|
2006
2320
|
x2 = ortho_group.rvs(3, random_state=seed)
|
2007
2321
|
# Note this matrix has det -1, distinguishing O(N) from SO(N)
|
2008
2322
|
assert_almost_equal(np.linalg.det(x), -1)
|
@@ -2015,7 +2329,7 @@ class TestOrthoGroup:
|
|
2015
2329
|
def test_invalid_dim(self):
|
2016
2330
|
assert_raises(ValueError, ortho_group.rvs, None)
|
2017
2331
|
assert_raises(ValueError, ortho_group.rvs, (2, 2))
|
2018
|
-
assert_raises(ValueError, ortho_group.rvs, 1)
|
2332
|
+
assert_raises(ValueError, ortho_group.rvs, -1)
|
2019
2333
|
assert_raises(ValueError, ortho_group.rvs, 2.5)
|
2020
2334
|
|
2021
2335
|
def test_frozen_matrix(self):
|
@@ -2067,8 +2381,8 @@ class TestOrthoGroup:
|
|
2067
2381
|
dim = 5
|
2068
2382
|
samples = 1000 # Not too many, or the test takes too long
|
2069
2383
|
ks_prob = .05
|
2070
|
-
np.random.
|
2071
|
-
xs = ortho_group.rvs(dim, size=samples)
|
2384
|
+
rng = np.random.RandomState(518) # Note that the test is sensitive to seed too
|
2385
|
+
xs = ortho_group.rvs(dim, size=samples, random_state=rng)
|
2072
2386
|
|
2073
2387
|
# Dot a few rows (0, 1, 2) with unit vectors (0, 2, 4, 3),
|
2074
2388
|
# effectively picking off entries in the matrices of xs.
|
@@ -2085,19 +2399,34 @@ class TestOrthoGroup:
|
|
2085
2399
|
ks_tests = [ks_2samp(proj[p0], proj[p1])[1] for (p0, p1) in pairs]
|
2086
2400
|
assert_array_less([ks_prob]*len(pairs), ks_tests)
|
2087
2401
|
|
2402
|
+
def test_one_by_one(self):
|
2403
|
+
# Test that the 1x1 distribution gives ±1 with equal probability.
|
2404
|
+
dim = 1
|
2405
|
+
xs = ortho_group.rvs(dim, size=5000, random_state=np.random.default_rng(514))
|
2406
|
+
assert_allclose(np.abs(xs), 1, rtol=1e-13)
|
2407
|
+
k = np.sum(xs > 0)
|
2408
|
+
n = len(xs)
|
2409
|
+
res = stats.binomtest(k, n)
|
2410
|
+
low, high = res.proportion_ci(confidence_level=0.95)
|
2411
|
+
assert low < 0.5 < high
|
2412
|
+
|
2413
|
+
def test_zero_by_zero(self):
|
2414
|
+
assert_equal(special_ortho_group.rvs(0, size=4).shape, (4, 0, 0))
|
2415
|
+
|
2088
2416
|
@pytest.mark.slow
|
2089
2417
|
def test_pairwise_distances(self):
|
2090
2418
|
# Test that the distribution of pairwise distances is close to correct.
|
2091
|
-
np.random.
|
2419
|
+
rng = np.random.RandomState(514)
|
2092
2420
|
|
2093
|
-
def random_ortho(dim):
|
2094
|
-
u, _s, v = np.linalg.svd(
|
2421
|
+
def random_ortho(dim, random_state=None):
|
2422
|
+
u, _s, v = np.linalg.svd(rng.normal(size=(dim, dim)))
|
2095
2423
|
return np.dot(u, v)
|
2096
2424
|
|
2097
2425
|
for dim in range(2, 6):
|
2098
2426
|
def generate_test_statistics(rvs, N=1000, eps=1e-10):
|
2099
2427
|
stats = np.array([
|
2100
|
-
np.sum((rvs(dim=dim) -
|
2428
|
+
np.sum((rvs(dim=dim, random_state=rng) -
|
2429
|
+
rvs(dim=dim, random_state=rng))**2)
|
2101
2430
|
for _ in range(N)
|
2102
2431
|
])
|
2103
2432
|
# Add a bit of noise to account for numeric accuracy.
|
@@ -2114,9 +2443,9 @@ class TestOrthoGroup:
|
|
2114
2443
|
|
2115
2444
|
class TestRandomCorrelation:
|
2116
2445
|
def test_reproducibility(self):
|
2117
|
-
np.random.
|
2446
|
+
rng = np.random.RandomState(514)
|
2118
2447
|
eigs = (.5, .8, 1.2, 1.5)
|
2119
|
-
x = random_correlation.rvs(eigs)
|
2448
|
+
x = random_correlation.rvs(eigs, random_state=rng)
|
2120
2449
|
x2 = random_correlation.rvs(eigs, random_state=514)
|
2121
2450
|
expected = np.array([[1., -0.184851, 0.109017, -0.227494],
|
2122
2451
|
[-0.184851, 1., 0.231236, 0.326669],
|
@@ -2157,13 +2486,13 @@ class TestRandomCorrelation:
|
|
2157
2486
|
def norm(i, e):
|
2158
2487
|
return i*e/sum(e)
|
2159
2488
|
|
2160
|
-
np.random.
|
2489
|
+
rng = np.random.RandomState(123)
|
2161
2490
|
|
2162
|
-
eigs = [norm(i,
|
2491
|
+
eigs = [norm(i, rng.uniform(size=i)) for i in range(2, 6)]
|
2163
2492
|
eigs.append([4,0,0,0])
|
2164
2493
|
|
2165
2494
|
ones = [[1.]*len(e) for e in eigs]
|
2166
|
-
xs = [random_correlation.rvs(e) for e in eigs]
|
2495
|
+
xs = [random_correlation.rvs(e, random_state=rng) for e in eigs]
|
2167
2496
|
|
2168
2497
|
# Test that determinants are products of eigenvalues
|
2169
2498
|
# These are positive by construction
|
@@ -2274,8 +2603,8 @@ class TestUniformDirection:
|
|
2274
2603
|
|
2275
2604
|
class TestUnitaryGroup:
|
2276
2605
|
def test_reproducibility(self):
|
2277
|
-
np.random.
|
2278
|
-
x = unitary_group.rvs(3)
|
2606
|
+
rng = np.random.RandomState(514)
|
2607
|
+
x = unitary_group.rvs(3, random_state=rng)
|
2279
2608
|
x2 = unitary_group.rvs(3, random_state=514)
|
2280
2609
|
|
2281
2610
|
expected = np.array(
|
@@ -2290,7 +2619,7 @@ class TestUnitaryGroup:
|
|
2290
2619
|
def test_invalid_dim(self):
|
2291
2620
|
assert_raises(ValueError, unitary_group.rvs, None)
|
2292
2621
|
assert_raises(ValueError, unitary_group.rvs, (2, 2))
|
2293
|
-
assert_raises(ValueError, unitary_group.rvs, 1)
|
2622
|
+
assert_raises(ValueError, unitary_group.rvs, -1)
|
2294
2623
|
assert_raises(ValueError, unitary_group.rvs, 2.5)
|
2295
2624
|
|
2296
2625
|
def test_frozen_matrix(self):
|
@@ -2319,17 +2648,22 @@ class TestUnitaryGroup:
|
|
2319
2648
|
# the complex plane, are uncorrelated.
|
2320
2649
|
|
2321
2650
|
# Generate samples
|
2322
|
-
dim
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2651
|
+
for dim in (1, 5):
|
2652
|
+
samples = 1000 # Not too many, or the test takes too long
|
2653
|
+
# Note that the test is sensitive to seed too
|
2654
|
+
xs = unitary_group.rvs(
|
2655
|
+
dim, size=samples, random_state=np.random.default_rng(514)
|
2656
|
+
)
|
2657
|
+
|
2658
|
+
# The angles "x" of the eigenvalues should be uniformly distributed
|
2659
|
+
# Overall this seems to be a necessary but weak test of the distribution.
|
2660
|
+
eigs = np.vstack([scipy.linalg.eigvals(x) for x in xs])
|
2661
|
+
x = np.arctan2(eigs.imag, eigs.real)
|
2662
|
+
res = kstest(x.ravel(), uniform(-np.pi, 2*np.pi).cdf)
|
2663
|
+
assert_(res.pvalue > 0.05)
|
2326
2664
|
|
2327
|
-
|
2328
|
-
|
2329
|
-
eigs = np.vstack([scipy.linalg.eigvals(x) for x in xs])
|
2330
|
-
x = np.arctan2(eigs.imag, eigs.real)
|
2331
|
-
res = kstest(x.ravel(), uniform(-np.pi, 2*np.pi).cdf)
|
2332
|
-
assert_(res.pvalue > 0.05)
|
2665
|
+
def test_zero_by_zero(self):
|
2666
|
+
assert_equal(unitary_group.rvs(0, size=4).shape, (4, 0, 0))
|
2333
2667
|
|
2334
2668
|
|
2335
2669
|
class TestMultivariateT:
|
@@ -2443,6 +2777,7 @@ class TestMultivariateT:
|
|
2443
2777
|
_, p = normaltest(samples)
|
2444
2778
|
assert ((p > P_VAL_MIN).all())
|
2445
2779
|
|
2780
|
+
@pytest.mark.thread_unsafe
|
2446
2781
|
@patch('scipy.stats.multivariate_normal._logpdf')
|
2447
2782
|
def test_mvt_with_inf_df_calls_normal(self, mock):
|
2448
2783
|
dist = multivariate_t(0, 1, df=np.inf, seed=7)
|
@@ -3393,7 +3728,8 @@ def check_pickling(distfn, args):
|
|
3393
3728
|
distfn.random_state = rndm
|
3394
3729
|
|
3395
3730
|
|
3396
|
-
|
3731
|
+
@pytest.mark.thread_unsafe
|
3732
|
+
def test_random_state_property(num_parallel_threads):
|
3397
3733
|
scale = np.eye(3)
|
3398
3734
|
scale[0, 1] = 0.5
|
3399
3735
|
scale[1, 0] = 0.5
|
@@ -3753,6 +4089,21 @@ class TestDirichletMultinomial:
|
|
3753
4089
|
assert_equal(dist.var(), 0)
|
3754
4090
|
assert_equal(dist.cov(), 0)
|
3755
4091
|
|
4092
|
+
def test_n_is_zero(self):
|
4093
|
+
# similarly, only one possible outcome if n is zero
|
4094
|
+
n = 0
|
4095
|
+
alpha = np.asarray([1., 1.])
|
4096
|
+
x = np.asarray([0, 0])
|
4097
|
+
dist = dirichlet_multinomial(alpha, n)
|
4098
|
+
|
4099
|
+
assert_equal(dist.pmf(x), 1)
|
4100
|
+
assert_equal(dist.pmf(x+1), 0)
|
4101
|
+
assert_equal(dist.logpmf(x), 0)
|
4102
|
+
assert_equal(dist.logpmf(x+1), -np.inf)
|
4103
|
+
assert_equal(dist.mean(), [0, 0])
|
4104
|
+
assert_equal(dist.var(), [0, 0])
|
4105
|
+
assert_equal(dist.cov(), [[0, 0], [0, 0]])
|
4106
|
+
|
3756
4107
|
@pytest.mark.parametrize('method_name', ['pmf', 'logpmf'])
|
3757
4108
|
def test_against_betabinom_pmf(self, method_name):
|
3758
4109
|
rng, m, alpha, n, x = self.get_params(100)
|
@@ -3815,11 +4166,11 @@ class TestDirichletMultinomial:
|
|
3815
4166
|
with assert_raises(ValueError, match=text):
|
3816
4167
|
dirichlet_multinomial.logpmf(x0, [3, -1, 4], n0)
|
3817
4168
|
|
3818
|
-
text = "`n` must be a
|
4169
|
+
text = "`n` must be a non-negative integer."
|
3819
4170
|
with assert_raises(ValueError, match=text):
|
3820
4171
|
dirichlet_multinomial.logpmf(x0, alpha0, 49.1)
|
3821
4172
|
with assert_raises(ValueError, match=text):
|
3822
|
-
dirichlet_multinomial.logpmf(x0, alpha0,
|
4173
|
+
dirichlet_multinomial.logpmf(x0, alpha0, -1)
|
3823
4174
|
|
3824
4175
|
x = np.array([1, 2, 3, 4])
|
3825
4176
|
alpha = np.array([3, 4, 5])
|