scipy 1.16.2__cp313-cp313t-win_arm64.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 +161 -0
- scipy/__init__.py +150 -0
- scipy/_cyutility.cp313t-win_arm64.lib +0 -0
- scipy/_cyutility.cp313t-win_arm64.pyd +0 -0
- scipy/_distributor_init.py +18 -0
- scipy/_lib/__init__.py +14 -0
- scipy/_lib/_array_api.py +931 -0
- scipy/_lib/_array_api_compat_vendor.py +9 -0
- scipy/_lib/_array_api_no_0d.py +103 -0
- scipy/_lib/_bunch.py +229 -0
- scipy/_lib/_ccallback.py +251 -0
- scipy/_lib/_ccallback_c.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_ccallback_c.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_disjoint_set.py +254 -0
- scipy/_lib/_docscrape.py +761 -0
- scipy/_lib/_elementwise_iterative_method.py +346 -0
- scipy/_lib/_fpumode.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_fpumode.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_gcutils.py +105 -0
- scipy/_lib/_pep440.py +487 -0
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_ccallback.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_test_ccallback.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_test_deprecation_call.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_test_deprecation_call.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_test_deprecation_def.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_test_deprecation_def.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_testutils.py +373 -0
- scipy/_lib/_threadsafety.py +58 -0
- scipy/_lib/_tmpdirs.py +86 -0
- scipy/_lib/_uarray/LICENSE +29 -0
- scipy/_lib/_uarray/__init__.py +116 -0
- scipy/_lib/_uarray/_backend.py +707 -0
- scipy/_lib/_uarray/_uarray.cp313t-win_arm64.lib +0 -0
- scipy/_lib/_uarray/_uarray.cp313t-win_arm64.pyd +0 -0
- scipy/_lib/_util.py +1283 -0
- scipy/_lib/array_api_compat/__init__.py +22 -0
- scipy/_lib/array_api_compat/_internal.py +59 -0
- scipy/_lib/array_api_compat/common/__init__.py +1 -0
- scipy/_lib/array_api_compat/common/_aliases.py +727 -0
- scipy/_lib/array_api_compat/common/_fft.py +213 -0
- scipy/_lib/array_api_compat/common/_helpers.py +1058 -0
- scipy/_lib/array_api_compat/common/_linalg.py +232 -0
- scipy/_lib/array_api_compat/common/_typing.py +192 -0
- scipy/_lib/array_api_compat/cupy/__init__.py +13 -0
- scipy/_lib/array_api_compat/cupy/_aliases.py +156 -0
- scipy/_lib/array_api_compat/cupy/_info.py +336 -0
- scipy/_lib/array_api_compat/cupy/_typing.py +31 -0
- scipy/_lib/array_api_compat/cupy/fft.py +36 -0
- scipy/_lib/array_api_compat/cupy/linalg.py +49 -0
- scipy/_lib/array_api_compat/dask/__init__.py +0 -0
- scipy/_lib/array_api_compat/dask/array/__init__.py +12 -0
- scipy/_lib/array_api_compat/dask/array/_aliases.py +376 -0
- scipy/_lib/array_api_compat/dask/array/_info.py +416 -0
- scipy/_lib/array_api_compat/dask/array/fft.py +21 -0
- scipy/_lib/array_api_compat/dask/array/linalg.py +72 -0
- scipy/_lib/array_api_compat/numpy/__init__.py +28 -0
- scipy/_lib/array_api_compat/numpy/_aliases.py +190 -0
- scipy/_lib/array_api_compat/numpy/_info.py +366 -0
- scipy/_lib/array_api_compat/numpy/_typing.py +30 -0
- scipy/_lib/array_api_compat/numpy/fft.py +35 -0
- scipy/_lib/array_api_compat/numpy/linalg.py +143 -0
- scipy/_lib/array_api_compat/torch/__init__.py +22 -0
- scipy/_lib/array_api_compat/torch/_aliases.py +855 -0
- scipy/_lib/array_api_compat/torch/_info.py +369 -0
- scipy/_lib/array_api_compat/torch/_typing.py +3 -0
- scipy/_lib/array_api_compat/torch/fft.py +85 -0
- scipy/_lib/array_api_compat/torch/linalg.py +121 -0
- scipy/_lib/array_api_extra/__init__.py +38 -0
- 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/cobyqa/__init__.py +20 -0
- scipy/_lib/cobyqa/framework.py +1240 -0
- scipy/_lib/cobyqa/main.py +1506 -0
- scipy/_lib/cobyqa/models.py +1529 -0
- scipy/_lib/cobyqa/problem.py +1296 -0
- scipy/_lib/cobyqa/settings.py +132 -0
- scipy/_lib/cobyqa/subsolvers/__init__.py +14 -0
- scipy/_lib/cobyqa/subsolvers/geometry.py +387 -0
- scipy/_lib/cobyqa/subsolvers/optim.py +1203 -0
- scipy/_lib/cobyqa/utils/__init__.py +18 -0
- scipy/_lib/cobyqa/utils/exceptions.py +22 -0
- scipy/_lib/cobyqa/utils/math.py +77 -0
- scipy/_lib/cobyqa/utils/versions.py +67 -0
- scipy/_lib/decorator.py +399 -0
- scipy/_lib/deprecation.py +274 -0
- scipy/_lib/doccer.py +366 -0
- scipy/_lib/messagestream.cp313t-win_arm64.lib +0 -0
- scipy/_lib/messagestream.cp313t-win_arm64.pyd +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/__init__.py +0 -0
- scipy/_lib/tests/test__gcutils.py +110 -0
- scipy/_lib/tests/test__pep440.py +67 -0
- scipy/_lib/tests/test__testutils.py +32 -0
- scipy/_lib/tests/test__threadsafety.py +51 -0
- scipy/_lib/tests/test__util.py +641 -0
- scipy/_lib/tests/test_array_api.py +322 -0
- scipy/_lib/tests/test_bunch.py +169 -0
- scipy/_lib/tests/test_ccallback.py +196 -0
- scipy/_lib/tests/test_config.py +45 -0
- scipy/_lib/tests/test_deprecation.py +10 -0
- scipy/_lib/tests/test_doccer.py +143 -0
- scipy/_lib/tests/test_import_cycles.py +18 -0
- scipy/_lib/tests/test_public_api.py +482 -0
- scipy/_lib/tests/test_scipy_version.py +28 -0
- scipy/_lib/tests/test_tmpdirs.py +48 -0
- scipy/_lib/tests/test_warnings.py +137 -0
- scipy/_lib/uarray.py +31 -0
- scipy/cluster/__init__.py +31 -0
- scipy/cluster/_hierarchy.cp313t-win_arm64.lib +0 -0
- scipy/cluster/_hierarchy.cp313t-win_arm64.pyd +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp313t-win_arm64.lib +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp313t-win_arm64.pyd +0 -0
- scipy/cluster/_vq.cp313t-win_arm64.lib +0 -0
- scipy/cluster/_vq.cp313t-win_arm64.pyd +0 -0
- scipy/cluster/hierarchy.py +4348 -0
- scipy/cluster/tests/__init__.py +0 -0
- scipy/cluster/tests/hierarchy_test_data.py +145 -0
- scipy/cluster/tests/test_disjoint_set.py +202 -0
- scipy/cluster/tests/test_hierarchy.py +1238 -0
- scipy/cluster/tests/test_vq.py +434 -0
- scipy/cluster/vq.py +832 -0
- scipy/conftest.py +683 -0
- scipy/constants/__init__.py +358 -0
- scipy/constants/_codata.py +2266 -0
- scipy/constants/_constants.py +369 -0
- scipy/constants/codata.py +21 -0
- scipy/constants/constants.py +53 -0
- scipy/constants/tests/__init__.py +0 -0
- scipy/constants/tests/test_codata.py +78 -0
- scipy/constants/tests/test_constants.py +83 -0
- scipy/datasets/__init__.py +90 -0
- scipy/datasets/_download_all.py +71 -0
- scipy/datasets/_fetchers.py +225 -0
- scipy/datasets/_registry.py +26 -0
- scipy/datasets/_utils.py +81 -0
- scipy/datasets/tests/__init__.py +0 -0
- scipy/datasets/tests/test_data.py +128 -0
- scipy/differentiate/__init__.py +27 -0
- scipy/differentiate/_differentiate.py +1129 -0
- scipy/differentiate/tests/__init__.py +0 -0
- scipy/differentiate/tests/test_differentiate.py +694 -0
- scipy/fft/__init__.py +114 -0
- scipy/fft/_backend.py +196 -0
- scipy/fft/_basic.py +1650 -0
- scipy/fft/_basic_backend.py +197 -0
- scipy/fft/_debug_backends.py +22 -0
- scipy/fft/_fftlog.py +223 -0
- scipy/fft/_fftlog_backend.py +200 -0
- scipy/fft/_helper.py +348 -0
- scipy/fft/_pocketfft/LICENSE.md +25 -0
- scipy/fft/_pocketfft/__init__.py +9 -0
- scipy/fft/_pocketfft/basic.py +251 -0
- scipy/fft/_pocketfft/helper.py +249 -0
- scipy/fft/_pocketfft/pypocketfft.cp313t-win_arm64.lib +0 -0
- scipy/fft/_pocketfft/pypocketfft.cp313t-win_arm64.pyd +0 -0
- scipy/fft/_pocketfft/realtransforms.py +109 -0
- scipy/fft/_pocketfft/tests/__init__.py +0 -0
- scipy/fft/_pocketfft/tests/test_basic.py +1011 -0
- scipy/fft/_pocketfft/tests/test_real_transforms.py +505 -0
- scipy/fft/_realtransforms.py +706 -0
- scipy/fft/_realtransforms_backend.py +63 -0
- scipy/fft/tests/__init__.py +0 -0
- scipy/fft/tests/mock_backend.py +96 -0
- scipy/fft/tests/test_backend.py +98 -0
- scipy/fft/tests/test_basic.py +504 -0
- scipy/fft/tests/test_fftlog.py +215 -0
- scipy/fft/tests/test_helper.py +558 -0
- scipy/fft/tests/test_multithreading.py +84 -0
- scipy/fft/tests/test_real_transforms.py +247 -0
- scipy/fftpack/__init__.py +103 -0
- scipy/fftpack/_basic.py +428 -0
- scipy/fftpack/_helper.py +115 -0
- scipy/fftpack/_pseudo_diffs.py +554 -0
- scipy/fftpack/_realtransforms.py +598 -0
- scipy/fftpack/basic.py +20 -0
- scipy/fftpack/convolve.cp313t-win_arm64.lib +0 -0
- scipy/fftpack/convolve.cp313t-win_arm64.pyd +0 -0
- scipy/fftpack/helper.py +19 -0
- scipy/fftpack/pseudo_diffs.py +22 -0
- scipy/fftpack/realtransforms.py +19 -0
- scipy/fftpack/tests/__init__.py +0 -0
- scipy/fftpack/tests/fftw_double_ref.npz +0 -0
- scipy/fftpack/tests/fftw_longdouble_ref.npz +0 -0
- scipy/fftpack/tests/fftw_single_ref.npz +0 -0
- scipy/fftpack/tests/test.npz +0 -0
- scipy/fftpack/tests/test_basic.py +877 -0
- scipy/fftpack/tests/test_helper.py +54 -0
- scipy/fftpack/tests/test_import.py +33 -0
- scipy/fftpack/tests/test_pseudo_diffs.py +388 -0
- scipy/fftpack/tests/test_real_transforms.py +836 -0
- scipy/integrate/__init__.py +122 -0
- scipy/integrate/_bvp.py +1160 -0
- scipy/integrate/_cubature.py +729 -0
- scipy/integrate/_dop.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_dop.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_ivp/__init__.py +8 -0
- scipy/integrate/_ivp/base.py +290 -0
- scipy/integrate/_ivp/bdf.py +478 -0
- scipy/integrate/_ivp/common.py +451 -0
- scipy/integrate/_ivp/dop853_coefficients.py +193 -0
- scipy/integrate/_ivp/ivp.py +755 -0
- scipy/integrate/_ivp/lsoda.py +224 -0
- scipy/integrate/_ivp/radau.py +572 -0
- scipy/integrate/_ivp/rk.py +601 -0
- scipy/integrate/_ivp/tests/__init__.py +0 -0
- scipy/integrate/_ivp/tests/test_ivp.py +1287 -0
- scipy/integrate/_ivp/tests/test_rk.py +37 -0
- scipy/integrate/_lebedev.py +5450 -0
- scipy/integrate/_lsoda.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_lsoda.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_ode.py +1395 -0
- scipy/integrate/_odepack.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_odepack.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_odepack_py.py +273 -0
- scipy/integrate/_quad_vec.py +674 -0
- scipy/integrate/_quadpack.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_quadpack.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_quadpack_py.py +1283 -0
- scipy/integrate/_quadrature.py +1336 -0
- scipy/integrate/_rules/__init__.py +12 -0
- scipy/integrate/_rules/_base.py +518 -0
- scipy/integrate/_rules/_gauss_kronrod.py +202 -0
- scipy/integrate/_rules/_gauss_legendre.py +62 -0
- scipy/integrate/_rules/_genz_malik.py +210 -0
- scipy/integrate/_tanhsinh.py +1385 -0
- scipy/integrate/_test_multivariate.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_test_multivariate.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_test_odeint_banded.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_test_odeint_banded.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/_vode.cp313t-win_arm64.lib +0 -0
- scipy/integrate/_vode.cp313t-win_arm64.pyd +0 -0
- scipy/integrate/dop.py +15 -0
- scipy/integrate/lsoda.py +15 -0
- scipy/integrate/odepack.py +17 -0
- scipy/integrate/quadpack.py +23 -0
- scipy/integrate/tests/__init__.py +0 -0
- scipy/integrate/tests/test__quad_vec.py +211 -0
- scipy/integrate/tests/test_banded_ode_solvers.py +305 -0
- scipy/integrate/tests/test_bvp.py +714 -0
- scipy/integrate/tests/test_cubature.py +1375 -0
- scipy/integrate/tests/test_integrate.py +840 -0
- scipy/integrate/tests/test_odeint_jac.py +74 -0
- scipy/integrate/tests/test_quadpack.py +680 -0
- scipy/integrate/tests/test_quadrature.py +730 -0
- scipy/integrate/tests/test_tanhsinh.py +1171 -0
- scipy/integrate/vode.py +15 -0
- scipy/interpolate/__init__.py +228 -0
- scipy/interpolate/_bary_rational.py +715 -0
- scipy/interpolate/_bsplines.py +2469 -0
- scipy/interpolate/_cubic.py +973 -0
- scipy/interpolate/_dfitpack.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_dfitpack.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_dierckx.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_dierckx.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_fitpack.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_fitpack.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_fitpack2.py +2397 -0
- scipy/interpolate/_fitpack_impl.py +811 -0
- scipy/interpolate/_fitpack_py.py +898 -0
- scipy/interpolate/_fitpack_repro.py +996 -0
- scipy/interpolate/_interpnd.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_interpnd.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_interpolate.py +2266 -0
- scipy/interpolate/_ndbspline.py +415 -0
- scipy/interpolate/_ndgriddata.py +329 -0
- scipy/interpolate/_pade.py +67 -0
- scipy/interpolate/_polyint.py +1025 -0
- scipy/interpolate/_ppoly.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_ppoly.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_rbf.py +290 -0
- scipy/interpolate/_rbfinterp.py +550 -0
- scipy/interpolate/_rbfinterp_pythran.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_rbfinterp_pythran.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/_rgi.py +764 -0
- scipy/interpolate/_rgi_cython.cp313t-win_arm64.lib +0 -0
- scipy/interpolate/_rgi_cython.cp313t-win_arm64.pyd +0 -0
- scipy/interpolate/dfitpack.py +24 -0
- scipy/interpolate/fitpack.py +31 -0
- scipy/interpolate/fitpack2.py +29 -0
- scipy/interpolate/interpnd.py +24 -0
- scipy/interpolate/interpolate.py +30 -0
- scipy/interpolate/ndgriddata.py +23 -0
- scipy/interpolate/polyint.py +24 -0
- scipy/interpolate/rbf.py +18 -0
- scipy/interpolate/tests/__init__.py +0 -0
- scipy/interpolate/tests/data/bug-1310.npz +0 -0
- scipy/interpolate/tests/data/estimate_gradients_hang.npy +0 -0
- scipy/interpolate/tests/data/gcvspl.npz +0 -0
- scipy/interpolate/tests/test_bary_rational.py +368 -0
- scipy/interpolate/tests/test_bsplines.py +3754 -0
- scipy/interpolate/tests/test_fitpack.py +519 -0
- scipy/interpolate/tests/test_fitpack2.py +1431 -0
- scipy/interpolate/tests/test_gil.py +64 -0
- scipy/interpolate/tests/test_interpnd.py +452 -0
- scipy/interpolate/tests/test_interpolate.py +2630 -0
- scipy/interpolate/tests/test_ndgriddata.py +308 -0
- scipy/interpolate/tests/test_pade.py +107 -0
- scipy/interpolate/tests/test_polyint.py +972 -0
- scipy/interpolate/tests/test_rbf.py +246 -0
- scipy/interpolate/tests/test_rbfinterp.py +534 -0
- scipy/interpolate/tests/test_rgi.py +1151 -0
- scipy/io/__init__.py +116 -0
- scipy/io/_fast_matrix_market/__init__.py +600 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp313t-win_arm64.lib +0 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp313t-win_arm64.pyd +0 -0
- scipy/io/_fortran.py +354 -0
- scipy/io/_harwell_boeing/__init__.py +7 -0
- scipy/io/_harwell_boeing/_fortran_format_parser.py +316 -0
- scipy/io/_harwell_boeing/hb.py +571 -0
- scipy/io/_harwell_boeing/tests/__init__.py +0 -0
- scipy/io/_harwell_boeing/tests/test_fortran_format.py +74 -0
- scipy/io/_harwell_boeing/tests/test_hb.py +70 -0
- scipy/io/_idl.py +917 -0
- scipy/io/_mmio.py +968 -0
- scipy/io/_netcdf.py +1104 -0
- scipy/io/_test_fortran.cp313t-win_arm64.lib +0 -0
- scipy/io/_test_fortran.cp313t-win_arm64.pyd +0 -0
- scipy/io/arff/__init__.py +28 -0
- scipy/io/arff/_arffread.py +873 -0
- scipy/io/arff/arffread.py +19 -0
- scipy/io/arff/tests/__init__.py +0 -0
- scipy/io/arff/tests/data/iris.arff +225 -0
- scipy/io/arff/tests/data/missing.arff +8 -0
- scipy/io/arff/tests/data/nodata.arff +11 -0
- scipy/io/arff/tests/data/quoted_nominal.arff +13 -0
- scipy/io/arff/tests/data/quoted_nominal_spaces.arff +13 -0
- scipy/io/arff/tests/data/test1.arff +10 -0
- scipy/io/arff/tests/data/test10.arff +8 -0
- scipy/io/arff/tests/data/test11.arff +11 -0
- scipy/io/arff/tests/data/test2.arff +15 -0
- scipy/io/arff/tests/data/test3.arff +6 -0
- scipy/io/arff/tests/data/test4.arff +11 -0
- scipy/io/arff/tests/data/test5.arff +26 -0
- scipy/io/arff/tests/data/test6.arff +12 -0
- scipy/io/arff/tests/data/test7.arff +15 -0
- scipy/io/arff/tests/data/test8.arff +12 -0
- scipy/io/arff/tests/data/test9.arff +14 -0
- scipy/io/arff/tests/test_arffread.py +421 -0
- scipy/io/harwell_boeing.py +17 -0
- scipy/io/idl.py +17 -0
- scipy/io/matlab/__init__.py +66 -0
- scipy/io/matlab/_byteordercodes.py +75 -0
- scipy/io/matlab/_mio.py +375 -0
- scipy/io/matlab/_mio4.py +632 -0
- scipy/io/matlab/_mio5.py +901 -0
- scipy/io/matlab/_mio5_params.py +281 -0
- scipy/io/matlab/_mio5_utils.cp313t-win_arm64.lib +0 -0
- scipy/io/matlab/_mio5_utils.cp313t-win_arm64.pyd +0 -0
- scipy/io/matlab/_mio_utils.cp313t-win_arm64.lib +0 -0
- scipy/io/matlab/_mio_utils.cp313t-win_arm64.pyd +0 -0
- scipy/io/matlab/_miobase.py +435 -0
- scipy/io/matlab/_streams.cp313t-win_arm64.lib +0 -0
- scipy/io/matlab/_streams.cp313t-win_arm64.pyd +0 -0
- scipy/io/matlab/byteordercodes.py +17 -0
- scipy/io/matlab/mio.py +16 -0
- scipy/io/matlab/mio4.py +17 -0
- scipy/io/matlab/mio5.py +19 -0
- scipy/io/matlab/mio5_params.py +18 -0
- scipy/io/matlab/mio5_utils.py +17 -0
- scipy/io/matlab/mio_utils.py +17 -0
- scipy/io/matlab/miobase.py +16 -0
- scipy/io/matlab/streams.py +16 -0
- scipy/io/matlab/tests/__init__.py +0 -0
- scipy/io/matlab/tests/data/bad_miuint32.mat +0 -0
- scipy/io/matlab/tests/data/bad_miutf8_array_name.mat +0 -0
- scipy/io/matlab/tests/data/big_endian.mat +0 -0
- scipy/io/matlab/tests/data/broken_utf8.mat +0 -0
- scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat +0 -0
- scipy/io/matlab/tests/data/corrupted_zlib_data.mat +0 -0
- scipy/io/matlab/tests/data/debigged_m4.mat +0 -0
- scipy/io/matlab/tests/data/japanese_utf8.txt +5 -0
- scipy/io/matlab/tests/data/little_endian.mat +0 -0
- scipy/io/matlab/tests/data/logical_sparse.mat +0 -0
- scipy/io/matlab/tests/data/malformed1.mat +0 -0
- scipy/io/matlab/tests/data/miuint32_for_miint32.mat +0 -0
- scipy/io/matlab/tests/data/miutf8_array_name.mat +0 -0
- scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat +0 -0
- scipy/io/matlab/tests/data/one_by_zero_char.mat +0 -0
- scipy/io/matlab/tests/data/parabola.mat +0 -0
- scipy/io/matlab/tests/data/single_empty_string.mat +0 -0
- scipy/io/matlab/tests/data/some_functions.mat +0 -0
- scipy/io/matlab/tests/data/sqr.mat +0 -0
- scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/test_empty_struct.mat +0 -0
- scipy/io/matlab/tests/data/test_mat4_le_floats.mat +0 -0
- scipy/io/matlab/tests/data/test_skip_variable.mat +0 -0
- scipy/io/matlab/tests/data/testbool_8_WIN64.mat +0 -0
- scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsimplecell.mat +0 -0
- scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat +0 -0
- scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/data/testvec_4_GLNX86.mat +0 -0
- scipy/io/matlab/tests/test_byteordercodes.py +29 -0
- scipy/io/matlab/tests/test_mio.py +1399 -0
- scipy/io/matlab/tests/test_mio5_utils.py +179 -0
- scipy/io/matlab/tests/test_mio_funcs.py +51 -0
- scipy/io/matlab/tests/test_mio_utils.py +45 -0
- scipy/io/matlab/tests/test_miobase.py +32 -0
- scipy/io/matlab/tests/test_pathological.py +33 -0
- scipy/io/matlab/tests/test_streams.py +241 -0
- scipy/io/mmio.py +17 -0
- scipy/io/netcdf.py +17 -0
- scipy/io/tests/__init__.py +0 -0
- scipy/io/tests/data/Transparent Busy.ani +0 -0
- scipy/io/tests/data/array_float32_1d.sav +0 -0
- scipy/io/tests/data/array_float32_2d.sav +0 -0
- scipy/io/tests/data/array_float32_3d.sav +0 -0
- scipy/io/tests/data/array_float32_4d.sav +0 -0
- scipy/io/tests/data/array_float32_5d.sav +0 -0
- scipy/io/tests/data/array_float32_6d.sav +0 -0
- scipy/io/tests/data/array_float32_7d.sav +0 -0
- scipy/io/tests/data/array_float32_8d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_1d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_2d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_3d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_4d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_5d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_6d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_7d.sav +0 -0
- scipy/io/tests/data/array_float32_pointer_8d.sav +0 -0
- scipy/io/tests/data/example_1.nc +0 -0
- scipy/io/tests/data/example_2.nc +0 -0
- scipy/io/tests/data/example_3_maskedvals.nc +0 -0
- scipy/io/tests/data/fortran-3x3d-2i.dat +0 -0
- scipy/io/tests/data/fortran-mixed.dat +0 -0
- scipy/io/tests/data/fortran-sf8-11x1x10.dat +0 -0
- scipy/io/tests/data/fortran-sf8-15x10x22.dat +0 -0
- scipy/io/tests/data/fortran-sf8-1x1x1.dat +0 -0
- scipy/io/tests/data/fortran-sf8-1x1x5.dat +0 -0
- scipy/io/tests/data/fortran-sf8-1x1x7.dat +0 -0
- scipy/io/tests/data/fortran-sf8-1x3x5.dat +0 -0
- scipy/io/tests/data/fortran-si4-11x1x10.dat +0 -0
- scipy/io/tests/data/fortran-si4-15x10x22.dat +0 -0
- scipy/io/tests/data/fortran-si4-1x1x1.dat +0 -0
- scipy/io/tests/data/fortran-si4-1x1x5.dat +0 -0
- scipy/io/tests/data/fortran-si4-1x1x7.dat +0 -0
- scipy/io/tests/data/fortran-si4-1x3x5.dat +0 -0
- scipy/io/tests/data/invalid_pointer.sav +0 -0
- scipy/io/tests/data/null_pointer.sav +0 -0
- scipy/io/tests/data/scalar_byte.sav +0 -0
- scipy/io/tests/data/scalar_byte_descr.sav +0 -0
- scipy/io/tests/data/scalar_complex32.sav +0 -0
- scipy/io/tests/data/scalar_complex64.sav +0 -0
- scipy/io/tests/data/scalar_float32.sav +0 -0
- scipy/io/tests/data/scalar_float64.sav +0 -0
- scipy/io/tests/data/scalar_heap_pointer.sav +0 -0
- scipy/io/tests/data/scalar_int16.sav +0 -0
- scipy/io/tests/data/scalar_int32.sav +0 -0
- scipy/io/tests/data/scalar_int64.sav +0 -0
- scipy/io/tests/data/scalar_string.sav +0 -0
- scipy/io/tests/data/scalar_uint16.sav +0 -0
- scipy/io/tests/data/scalar_uint32.sav +0 -0
- scipy/io/tests/data/scalar_uint64.sav +0 -0
- scipy/io/tests/data/struct_arrays.sav +0 -0
- scipy/io/tests/data/struct_arrays_byte_idl80.sav +0 -0
- scipy/io/tests/data/struct_arrays_replicated.sav +0 -0
- scipy/io/tests/data/struct_arrays_replicated_3d.sav +0 -0
- scipy/io/tests/data/struct_inherit.sav +0 -0
- scipy/io/tests/data/struct_pointer_arrays.sav +0 -0
- scipy/io/tests/data/struct_pointer_arrays_replicated.sav +0 -0
- scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav +0 -0
- scipy/io/tests/data/struct_pointers.sav +0 -0
- scipy/io/tests/data/struct_pointers_replicated.sav +0 -0
- scipy/io/tests/data/struct_pointers_replicated_3d.sav +0 -0
- scipy/io/tests/data/struct_scalars.sav +0 -0
- scipy/io/tests/data/struct_scalars_replicated.sav +0 -0
- scipy/io/tests/data/struct_scalars_replicated_3d.sav +0 -0
- scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav +0 -0
- scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav +0 -0
- scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav +0 -0
- scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav +0 -0
- scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav +0 -0
- scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav +0 -0
- scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav +0 -0
- scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav +0 -0
- scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav +0 -0
- scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav +0 -0
- scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav +0 -0
- scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav +0 -0
- scipy/io/tests/data/various_compressed.sav +0 -0
- scipy/io/tests/test_fortran.py +264 -0
- scipy/io/tests/test_idl.py +483 -0
- scipy/io/tests/test_mmio.py +831 -0
- scipy/io/tests/test_netcdf.py +550 -0
- scipy/io/tests/test_paths.py +93 -0
- scipy/io/tests/test_wavfile.py +501 -0
- scipy/io/wavfile.py +938 -0
- scipy/linalg/__init__.pxd +1 -0
- scipy/linalg/__init__.py +236 -0
- scipy/linalg/_basic.py +2146 -0
- scipy/linalg/_blas_subroutines.h +164 -0
- scipy/linalg/_cythonized_array_utils.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_cythonized_array_utils.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_cythonized_array_utils.pxd +40 -0
- scipy/linalg/_cythonized_array_utils.pyi +16 -0
- scipy/linalg/_decomp.py +1645 -0
- scipy/linalg/_decomp_cholesky.py +413 -0
- scipy/linalg/_decomp_cossin.py +236 -0
- scipy/linalg/_decomp_interpolative.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_decomp_interpolative.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_decomp_ldl.py +356 -0
- scipy/linalg/_decomp_lu.py +401 -0
- scipy/linalg/_decomp_lu_cython.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_decomp_lu_cython.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_decomp_lu_cython.pyi +6 -0
- scipy/linalg/_decomp_polar.py +113 -0
- scipy/linalg/_decomp_qr.py +494 -0
- scipy/linalg/_decomp_qz.py +452 -0
- scipy/linalg/_decomp_schur.py +336 -0
- scipy/linalg/_decomp_svd.py +545 -0
- scipy/linalg/_decomp_update.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_decomp_update.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_expm_frechet.py +417 -0
- scipy/linalg/_fblas.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_fblas.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_flapack.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_flapack.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_lapack_subroutines.h +1521 -0
- scipy/linalg/_linalg_pythran.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_linalg_pythran.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_matfuncs.py +1050 -0
- scipy/linalg/_matfuncs_expm.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_matfuncs_expm.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_matfuncs_expm.pyi +6 -0
- scipy/linalg/_matfuncs_inv_ssq.py +886 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +107 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_misc.py +191 -0
- scipy/linalg/_procrustes.py +113 -0
- scipy/linalg/_sketches.py +189 -0
- scipy/linalg/_solve_toeplitz.cp313t-win_arm64.lib +0 -0
- scipy/linalg/_solve_toeplitz.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/_solvers.py +862 -0
- scipy/linalg/_special_matrices.py +1322 -0
- scipy/linalg/_testutils.py +65 -0
- scipy/linalg/basic.py +23 -0
- scipy/linalg/blas.py +495 -0
- scipy/linalg/cython_blas.cp313t-win_arm64.lib +0 -0
- scipy/linalg/cython_blas.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/cython_blas.pxd +169 -0
- scipy/linalg/cython_blas.pyx +1432 -0
- scipy/linalg/cython_lapack.cp313t-win_arm64.lib +0 -0
- scipy/linalg/cython_lapack.cp313t-win_arm64.pyd +0 -0
- scipy/linalg/cython_lapack.pxd +1528 -0
- scipy/linalg/cython_lapack.pyx +12045 -0
- scipy/linalg/decomp.py +23 -0
- scipy/linalg/decomp_cholesky.py +21 -0
- scipy/linalg/decomp_lu.py +21 -0
- scipy/linalg/decomp_qr.py +20 -0
- scipy/linalg/decomp_schur.py +21 -0
- scipy/linalg/decomp_svd.py +21 -0
- scipy/linalg/interpolative.py +989 -0
- scipy/linalg/lapack.py +1081 -0
- scipy/linalg/matfuncs.py +23 -0
- scipy/linalg/misc.py +21 -0
- scipy/linalg/special_matrices.py +22 -0
- scipy/linalg/tests/__init__.py +0 -0
- scipy/linalg/tests/_cython_examples/extending.pyx +23 -0
- scipy/linalg/tests/_cython_examples/meson.build +34 -0
- scipy/linalg/tests/data/carex_15_data.npz +0 -0
- scipy/linalg/tests/data/carex_18_data.npz +0 -0
- scipy/linalg/tests/data/carex_19_data.npz +0 -0
- scipy/linalg/tests/data/carex_20_data.npz +0 -0
- scipy/linalg/tests/data/carex_6_data.npz +0 -0
- scipy/linalg/tests/data/gendare_20170120_data.npz +0 -0
- scipy/linalg/tests/test_basic.py +2074 -0
- scipy/linalg/tests/test_batch.py +588 -0
- scipy/linalg/tests/test_blas.py +1127 -0
- scipy/linalg/tests/test_cython_blas.py +118 -0
- scipy/linalg/tests/test_cython_lapack.py +22 -0
- scipy/linalg/tests/test_cythonized_array_utils.py +130 -0
- scipy/linalg/tests/test_decomp.py +3189 -0
- scipy/linalg/tests/test_decomp_cholesky.py +268 -0
- scipy/linalg/tests/test_decomp_cossin.py +314 -0
- scipy/linalg/tests/test_decomp_ldl.py +137 -0
- scipy/linalg/tests/test_decomp_lu.py +308 -0
- scipy/linalg/tests/test_decomp_polar.py +110 -0
- scipy/linalg/tests/test_decomp_update.py +1701 -0
- scipy/linalg/tests/test_extending.py +46 -0
- scipy/linalg/tests/test_fblas.py +607 -0
- scipy/linalg/tests/test_interpolative.py +232 -0
- scipy/linalg/tests/test_lapack.py +3620 -0
- scipy/linalg/tests/test_matfuncs.py +1125 -0
- scipy/linalg/tests/test_matmul_toeplitz.py +136 -0
- scipy/linalg/tests/test_procrustes.py +214 -0
- scipy/linalg/tests/test_sketches.py +118 -0
- scipy/linalg/tests/test_solve_toeplitz.py +150 -0
- scipy/linalg/tests/test_solvers.py +844 -0
- scipy/linalg/tests/test_special_matrices.py +636 -0
- scipy/misc/__init__.py +6 -0
- scipy/misc/common.py +6 -0
- scipy/misc/doccer.py +6 -0
- scipy/ndimage/__init__.py +174 -0
- scipy/ndimage/_ctest.cp313t-win_arm64.lib +0 -0
- scipy/ndimage/_ctest.cp313t-win_arm64.pyd +0 -0
- scipy/ndimage/_cytest.cp313t-win_arm64.lib +0 -0
- scipy/ndimage/_cytest.cp313t-win_arm64.pyd +0 -0
- scipy/ndimage/_delegators.py +303 -0
- scipy/ndimage/_filters.py +2422 -0
- scipy/ndimage/_fourier.py +306 -0
- scipy/ndimage/_interpolation.py +1033 -0
- scipy/ndimage/_measurements.py +1689 -0
- scipy/ndimage/_morphology.py +2634 -0
- scipy/ndimage/_nd_image.cp313t-win_arm64.lib +0 -0
- scipy/ndimage/_nd_image.cp313t-win_arm64.pyd +0 -0
- scipy/ndimage/_ndimage_api.py +16 -0
- scipy/ndimage/_ni_docstrings.py +214 -0
- scipy/ndimage/_ni_label.cp313t-win_arm64.lib +0 -0
- scipy/ndimage/_ni_label.cp313t-win_arm64.pyd +0 -0
- scipy/ndimage/_ni_support.py +139 -0
- scipy/ndimage/_rank_filter_1d.cp313t-win_arm64.lib +0 -0
- scipy/ndimage/_rank_filter_1d.cp313t-win_arm64.pyd +0 -0
- scipy/ndimage/_support_alternative_backends.py +84 -0
- scipy/ndimage/filters.py +27 -0
- scipy/ndimage/fourier.py +21 -0
- scipy/ndimage/interpolation.py +22 -0
- scipy/ndimage/measurements.py +24 -0
- scipy/ndimage/morphology.py +27 -0
- scipy/ndimage/tests/__init__.py +12 -0
- scipy/ndimage/tests/data/label_inputs.txt +21 -0
- scipy/ndimage/tests/data/label_results.txt +294 -0
- scipy/ndimage/tests/data/label_strels.txt +42 -0
- scipy/ndimage/tests/dots.png +0 -0
- scipy/ndimage/tests/test_c_api.py +102 -0
- scipy/ndimage/tests/test_datatypes.py +67 -0
- scipy/ndimage/tests/test_filters.py +3083 -0
- scipy/ndimage/tests/test_fourier.py +187 -0
- scipy/ndimage/tests/test_interpolation.py +1491 -0
- scipy/ndimage/tests/test_measurements.py +1592 -0
- scipy/ndimage/tests/test_morphology.py +2950 -0
- scipy/ndimage/tests/test_ni_support.py +78 -0
- scipy/ndimage/tests/test_splines.py +70 -0
- scipy/odr/__init__.py +131 -0
- scipy/odr/__odrpack.cp313t-win_arm64.lib +0 -0
- scipy/odr/__odrpack.cp313t-win_arm64.pyd +0 -0
- scipy/odr/_add_newdocs.py +34 -0
- scipy/odr/_models.py +315 -0
- scipy/odr/_odrpack.py +1154 -0
- scipy/odr/models.py +20 -0
- scipy/odr/odrpack.py +21 -0
- scipy/odr/tests/__init__.py +0 -0
- scipy/odr/tests/test_odr.py +607 -0
- scipy/optimize/__init__.pxd +1 -0
- scipy/optimize/__init__.py +460 -0
- scipy/optimize/_basinhopping.py +741 -0
- scipy/optimize/_bglu_dense.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_bglu_dense.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_bracket.py +706 -0
- scipy/optimize/_chandrupatla.py +551 -0
- scipy/optimize/_cobyla_py.py +297 -0
- scipy/optimize/_cobyqa_py.py +72 -0
- scipy/optimize/_constraints.py +598 -0
- scipy/optimize/_dcsrch.py +728 -0
- scipy/optimize/_differentiable_functions.py +835 -0
- scipy/optimize/_differentialevolution.py +1970 -0
- scipy/optimize/_direct.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_direct.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_direct_py.py +280 -0
- scipy/optimize/_dual_annealing.py +732 -0
- scipy/optimize/_elementwise.py +798 -0
- scipy/optimize/_group_columns.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_group_columns.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_hessian_update_strategy.py +479 -0
- scipy/optimize/_highspy/__init__.py +0 -0
- scipy/optimize/_highspy/_core.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_highspy/_core.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_highspy/_highs_options.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_highspy/_highs_options.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_highspy/_highs_wrapper.py +338 -0
- scipy/optimize/_isotonic.py +157 -0
- scipy/optimize/_lbfgsb.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_lbfgsb.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_lbfgsb_py.py +634 -0
- scipy/optimize/_linesearch.py +896 -0
- scipy/optimize/_linprog.py +733 -0
- scipy/optimize/_linprog_doc.py +1434 -0
- scipy/optimize/_linprog_highs.py +422 -0
- scipy/optimize/_linprog_ip.py +1141 -0
- scipy/optimize/_linprog_rs.py +572 -0
- scipy/optimize/_linprog_simplex.py +663 -0
- scipy/optimize/_linprog_util.py +1521 -0
- scipy/optimize/_lsap.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_lsap.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_lsq/__init__.py +5 -0
- scipy/optimize/_lsq/bvls.py +183 -0
- scipy/optimize/_lsq/common.py +731 -0
- scipy/optimize/_lsq/dogbox.py +345 -0
- scipy/optimize/_lsq/givens_elimination.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_lsq/givens_elimination.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_lsq/least_squares.py +1044 -0
- scipy/optimize/_lsq/lsq_linear.py +361 -0
- scipy/optimize/_lsq/trf.py +587 -0
- scipy/optimize/_lsq/trf_linear.py +249 -0
- scipy/optimize/_milp.py +394 -0
- scipy/optimize/_minimize.py +1199 -0
- scipy/optimize/_minpack.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_minpack.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_minpack_py.py +1178 -0
- scipy/optimize/_moduleTNC.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_moduleTNC.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_nnls.py +96 -0
- scipy/optimize/_nonlin.py +1634 -0
- scipy/optimize/_numdiff.py +963 -0
- scipy/optimize/_optimize.py +4169 -0
- scipy/optimize/_pava_pybind.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_pava_pybind.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_qap.py +760 -0
- scipy/optimize/_remove_redundancy.py +522 -0
- scipy/optimize/_root.py +732 -0
- scipy/optimize/_root_scalar.py +538 -0
- scipy/optimize/_shgo.py +1606 -0
- scipy/optimize/_shgo_lib/__init__.py +0 -0
- scipy/optimize/_shgo_lib/_complex.py +1225 -0
- scipy/optimize/_shgo_lib/_vertex.py +460 -0
- scipy/optimize/_slsqp_py.py +603 -0
- scipy/optimize/_slsqplib.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_slsqplib.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_spectral.py +260 -0
- scipy/optimize/_tnc.py +438 -0
- scipy/optimize/_trlib/__init__.py +12 -0
- scipy/optimize/_trlib/_trlib.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_trlib/_trlib.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_trustregion.py +318 -0
- scipy/optimize/_trustregion_constr/__init__.py +6 -0
- scipy/optimize/_trustregion_constr/canonical_constraint.py +390 -0
- scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +231 -0
- scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +584 -0
- scipy/optimize/_trustregion_constr/projections.py +411 -0
- scipy/optimize/_trustregion_constr/qp_subproblem.py +637 -0
- scipy/optimize/_trustregion_constr/report.py +49 -0
- scipy/optimize/_trustregion_constr/tests/__init__.py +0 -0
- scipy/optimize/_trustregion_constr/tests/test_canonical_constraint.py +296 -0
- scipy/optimize/_trustregion_constr/tests/test_nested_minimize.py +39 -0
- scipy/optimize/_trustregion_constr/tests/test_projections.py +214 -0
- scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +645 -0
- scipy/optimize/_trustregion_constr/tests/test_report.py +34 -0
- scipy/optimize/_trustregion_constr/tr_interior_point.py +361 -0
- scipy/optimize/_trustregion_dogleg.py +122 -0
- scipy/optimize/_trustregion_exact.py +437 -0
- scipy/optimize/_trustregion_krylov.py +65 -0
- scipy/optimize/_trustregion_ncg.py +126 -0
- scipy/optimize/_tstutils.py +972 -0
- scipy/optimize/_zeros.cp313t-win_arm64.lib +0 -0
- scipy/optimize/_zeros.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/_zeros_py.py +1475 -0
- scipy/optimize/cobyla.py +19 -0
- scipy/optimize/cython_optimize/__init__.py +133 -0
- scipy/optimize/cython_optimize/_zeros.cp313t-win_arm64.lib +0 -0
- scipy/optimize/cython_optimize/_zeros.cp313t-win_arm64.pyd +0 -0
- scipy/optimize/cython_optimize/_zeros.pxd +33 -0
- scipy/optimize/cython_optimize/c_zeros.pxd +26 -0
- scipy/optimize/cython_optimize.pxd +11 -0
- scipy/optimize/elementwise.py +38 -0
- scipy/optimize/lbfgsb.py +23 -0
- scipy/optimize/linesearch.py +18 -0
- scipy/optimize/minpack.py +27 -0
- scipy/optimize/minpack2.py +17 -0
- scipy/optimize/moduleTNC.py +19 -0
- scipy/optimize/nonlin.py +29 -0
- scipy/optimize/optimize.py +40 -0
- scipy/optimize/slsqp.py +22 -0
- scipy/optimize/tests/__init__.py +0 -0
- scipy/optimize/tests/_cython_examples/extending.pyx +43 -0
- scipy/optimize/tests/_cython_examples/meson.build +32 -0
- scipy/optimize/tests/test__basinhopping.py +535 -0
- scipy/optimize/tests/test__differential_evolution.py +1703 -0
- scipy/optimize/tests/test__dual_annealing.py +416 -0
- scipy/optimize/tests/test__linprog_clean_inputs.py +312 -0
- scipy/optimize/tests/test__numdiff.py +885 -0
- scipy/optimize/tests/test__remove_redundancy.py +228 -0
- scipy/optimize/tests/test__root.py +124 -0
- scipy/optimize/tests/test__shgo.py +1164 -0
- scipy/optimize/tests/test__spectral.py +226 -0
- scipy/optimize/tests/test_bracket.py +896 -0
- scipy/optimize/tests/test_chandrupatla.py +982 -0
- scipy/optimize/tests/test_cobyla.py +195 -0
- scipy/optimize/tests/test_cobyqa.py +252 -0
- scipy/optimize/tests/test_constraint_conversion.py +286 -0
- scipy/optimize/tests/test_constraints.py +255 -0
- scipy/optimize/tests/test_cython_optimize.py +92 -0
- scipy/optimize/tests/test_differentiable_functions.py +1025 -0
- scipy/optimize/tests/test_direct.py +321 -0
- scipy/optimize/tests/test_extending.py +28 -0
- scipy/optimize/tests/test_hessian_update_strategy.py +300 -0
- scipy/optimize/tests/test_isotonic_regression.py +167 -0
- scipy/optimize/tests/test_lbfgsb_hessinv.py +65 -0
- scipy/optimize/tests/test_lbfgsb_setulb.py +122 -0
- scipy/optimize/tests/test_least_squares.py +986 -0
- scipy/optimize/tests/test_linear_assignment.py +116 -0
- scipy/optimize/tests/test_linesearch.py +328 -0
- scipy/optimize/tests/test_linprog.py +2577 -0
- scipy/optimize/tests/test_lsq_common.py +297 -0
- scipy/optimize/tests/test_lsq_linear.py +287 -0
- scipy/optimize/tests/test_milp.py +459 -0
- scipy/optimize/tests/test_minimize_constrained.py +845 -0
- scipy/optimize/tests/test_minpack.py +1194 -0
- scipy/optimize/tests/test_nnls.py +469 -0
- scipy/optimize/tests/test_nonlin.py +572 -0
- scipy/optimize/tests/test_optimize.py +3344 -0
- scipy/optimize/tests/test_quadratic_assignment.py +455 -0
- scipy/optimize/tests/test_regression.py +40 -0
- scipy/optimize/tests/test_slsqp.py +645 -0
- scipy/optimize/tests/test_tnc.py +345 -0
- scipy/optimize/tests/test_trustregion.py +110 -0
- scipy/optimize/tests/test_trustregion_exact.py +351 -0
- scipy/optimize/tests/test_trustregion_krylov.py +170 -0
- scipy/optimize/tests/test_zeros.py +998 -0
- scipy/optimize/tnc.py +22 -0
- scipy/optimize/zeros.py +26 -0
- scipy/signal/__init__.py +316 -0
- scipy/signal/_arraytools.py +264 -0
- scipy/signal/_czt.py +575 -0
- scipy/signal/_delegators.py +568 -0
- scipy/signal/_filter_design.py +5893 -0
- scipy/signal/_fir_filter_design.py +1458 -0
- scipy/signal/_lti_conversion.py +534 -0
- scipy/signal/_ltisys.py +3546 -0
- scipy/signal/_max_len_seq.py +139 -0
- scipy/signal/_max_len_seq_inner.cp313t-win_arm64.lib +0 -0
- scipy/signal/_max_len_seq_inner.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_peak_finding.py +1310 -0
- scipy/signal/_peak_finding_utils.cp313t-win_arm64.lib +0 -0
- scipy/signal/_peak_finding_utils.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_polyutils.py +172 -0
- scipy/signal/_savitzky_golay.py +357 -0
- scipy/signal/_short_time_fft.py +2228 -0
- scipy/signal/_signal_api.py +30 -0
- scipy/signal/_signaltools.py +5309 -0
- scipy/signal/_sigtools.cp313t-win_arm64.lib +0 -0
- scipy/signal/_sigtools.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_sosfilt.cp313t-win_arm64.lib +0 -0
- scipy/signal/_sosfilt.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_spectral_py.py +2471 -0
- scipy/signal/_spline.cp313t-win_arm64.lib +0 -0
- scipy/signal/_spline.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_spline.pyi +34 -0
- scipy/signal/_spline_filters.py +848 -0
- scipy/signal/_support_alternative_backends.py +73 -0
- scipy/signal/_upfirdn.py +219 -0
- scipy/signal/_upfirdn_apply.cp313t-win_arm64.lib +0 -0
- scipy/signal/_upfirdn_apply.cp313t-win_arm64.pyd +0 -0
- scipy/signal/_waveforms.py +687 -0
- scipy/signal/_wavelets.py +29 -0
- scipy/signal/bsplines.py +21 -0
- scipy/signal/filter_design.py +28 -0
- scipy/signal/fir_filter_design.py +21 -0
- scipy/signal/lti_conversion.py +20 -0
- scipy/signal/ltisys.py +25 -0
- scipy/signal/signaltools.py +27 -0
- scipy/signal/spectral.py +21 -0
- scipy/signal/spline.py +18 -0
- scipy/signal/tests/__init__.py +0 -0
- scipy/signal/tests/_scipy_spectral_test_shim.py +311 -0
- scipy/signal/tests/mpsig.py +122 -0
- scipy/signal/tests/test_array_tools.py +111 -0
- scipy/signal/tests/test_bsplines.py +365 -0
- scipy/signal/tests/test_cont2discrete.py +424 -0
- scipy/signal/tests/test_czt.py +221 -0
- scipy/signal/tests/test_dltisys.py +599 -0
- scipy/signal/tests/test_filter_design.py +4744 -0
- scipy/signal/tests/test_fir_filter_design.py +851 -0
- scipy/signal/tests/test_ltisys.py +1225 -0
- scipy/signal/tests/test_max_len_seq.py +71 -0
- scipy/signal/tests/test_peak_finding.py +915 -0
- scipy/signal/tests/test_result_type.py +51 -0
- scipy/signal/tests/test_savitzky_golay.py +363 -0
- scipy/signal/tests/test_short_time_fft.py +1107 -0
- scipy/signal/tests/test_signaltools.py +4735 -0
- scipy/signal/tests/test_spectral.py +2141 -0
- scipy/signal/tests/test_splines.py +427 -0
- scipy/signal/tests/test_upfirdn.py +322 -0
- scipy/signal/tests/test_waveforms.py +400 -0
- scipy/signal/tests/test_wavelets.py +59 -0
- scipy/signal/tests/test_windows.py +987 -0
- scipy/signal/waveforms.py +20 -0
- scipy/signal/wavelets.py +17 -0
- scipy/signal/windows/__init__.py +52 -0
- scipy/signal/windows/_windows.py +2513 -0
- scipy/signal/windows/windows.py +23 -0
- scipy/sparse/__init__.py +350 -0
- scipy/sparse/_base.py +1613 -0
- scipy/sparse/_bsr.py +880 -0
- scipy/sparse/_compressed.py +1328 -0
- scipy/sparse/_construct.py +1454 -0
- scipy/sparse/_coo.py +1581 -0
- scipy/sparse/_csc.py +367 -0
- scipy/sparse/_csparsetools.cp313t-win_arm64.lib +0 -0
- scipy/sparse/_csparsetools.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/_csr.py +558 -0
- scipy/sparse/_data.py +569 -0
- scipy/sparse/_dia.py +677 -0
- scipy/sparse/_dok.py +669 -0
- scipy/sparse/_extract.py +178 -0
- scipy/sparse/_index.py +444 -0
- scipy/sparse/_lil.py +632 -0
- scipy/sparse/_matrix.py +169 -0
- scipy/sparse/_matrix_io.py +167 -0
- scipy/sparse/_sparsetools.cp313t-win_arm64.lib +0 -0
- scipy/sparse/_sparsetools.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/_spfuncs.py +76 -0
- scipy/sparse/_sputils.py +632 -0
- scipy/sparse/base.py +24 -0
- scipy/sparse/bsr.py +22 -0
- scipy/sparse/compressed.py +20 -0
- scipy/sparse/construct.py +38 -0
- scipy/sparse/coo.py +23 -0
- scipy/sparse/csc.py +22 -0
- scipy/sparse/csgraph/__init__.py +210 -0
- scipy/sparse/csgraph/_flow.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_flow.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_laplacian.py +563 -0
- scipy/sparse/csgraph/_matching.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_matching.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_reordering.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_reordering.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_shortest_path.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_shortest_path.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_tools.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_tools.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_traversal.cp313t-win_arm64.lib +0 -0
- scipy/sparse/csgraph/_traversal.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/csgraph/_validation.py +66 -0
- scipy/sparse/csgraph/tests/__init__.py +0 -0
- scipy/sparse/csgraph/tests/test_connected_components.py +119 -0
- scipy/sparse/csgraph/tests/test_conversions.py +61 -0
- scipy/sparse/csgraph/tests/test_flow.py +209 -0
- scipy/sparse/csgraph/tests/test_graph_laplacian.py +368 -0
- scipy/sparse/csgraph/tests/test_matching.py +307 -0
- scipy/sparse/csgraph/tests/test_pydata_sparse.py +197 -0
- scipy/sparse/csgraph/tests/test_reordering.py +70 -0
- scipy/sparse/csgraph/tests/test_shortest_path.py +540 -0
- scipy/sparse/csgraph/tests/test_spanning_tree.py +66 -0
- scipy/sparse/csgraph/tests/test_traversal.py +148 -0
- scipy/sparse/csr.py +22 -0
- scipy/sparse/data.py +18 -0
- scipy/sparse/dia.py +22 -0
- scipy/sparse/dok.py +22 -0
- scipy/sparse/extract.py +23 -0
- scipy/sparse/lil.py +22 -0
- scipy/sparse/linalg/__init__.py +148 -0
- scipy/sparse/linalg/_dsolve/__init__.py +71 -0
- scipy/sparse/linalg/_dsolve/_add_newdocs.py +147 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_dsolve/linsolve.py +882 -0
- scipy/sparse/linalg/_dsolve/tests/__init__.py +0 -0
- scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +928 -0
- scipy/sparse/linalg/_eigen/__init__.py +22 -0
- scipy/sparse/linalg/_eigen/_svds.py +540 -0
- scipy/sparse/linalg/_eigen/_svds_doc.py +382 -0
- scipy/sparse/linalg/_eigen/arpack/COPYING +45 -0
- scipy/sparse/linalg/_eigen/arpack/__init__.py +20 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_eigen/arpack/arpack.py +1706 -0
- scipy/sparse/linalg/_eigen/arpack/tests/__init__.py +0 -0
- scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py +717 -0
- scipy/sparse/linalg/_eigen/lobpcg/__init__.py +16 -0
- scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +1110 -0
- scipy/sparse/linalg/_eigen/lobpcg/tests/__init__.py +0 -0
- scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py +725 -0
- scipy/sparse/linalg/_eigen/tests/__init__.py +0 -0
- scipy/sparse/linalg/_eigen/tests/test_svds.py +886 -0
- scipy/sparse/linalg/_expm_multiply.py +816 -0
- scipy/sparse/linalg/_interface.py +920 -0
- scipy/sparse/linalg/_isolve/__init__.py +20 -0
- scipy/sparse/linalg/_isolve/_gcrotmk.py +503 -0
- scipy/sparse/linalg/_isolve/iterative.py +1051 -0
- scipy/sparse/linalg/_isolve/lgmres.py +230 -0
- scipy/sparse/linalg/_isolve/lsmr.py +486 -0
- scipy/sparse/linalg/_isolve/lsqr.py +589 -0
- scipy/sparse/linalg/_isolve/minres.py +372 -0
- scipy/sparse/linalg/_isolve/tests/__init__.py +0 -0
- scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py +183 -0
- scipy/sparse/linalg/_isolve/tests/test_iterative.py +809 -0
- scipy/sparse/linalg/_isolve/tests/test_lgmres.py +225 -0
- scipy/sparse/linalg/_isolve/tests/test_lsmr.py +185 -0
- scipy/sparse/linalg/_isolve/tests/test_lsqr.py +120 -0
- scipy/sparse/linalg/_isolve/tests/test_minres.py +97 -0
- scipy/sparse/linalg/_isolve/tests/test_utils.py +9 -0
- scipy/sparse/linalg/_isolve/tfqmr.py +179 -0
- scipy/sparse/linalg/_isolve/utils.py +121 -0
- scipy/sparse/linalg/_matfuncs.py +940 -0
- scipy/sparse/linalg/_norm.py +195 -0
- scipy/sparse/linalg/_onenormest.py +467 -0
- scipy/sparse/linalg/_propack/_cpropack.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_propack/_cpropack.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp313t-win_arm64.lib +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp313t-win_arm64.pyd +0 -0
- scipy/sparse/linalg/_special_sparse_arrays.py +949 -0
- scipy/sparse/linalg/_svdp.py +309 -0
- scipy/sparse/linalg/dsolve.py +22 -0
- scipy/sparse/linalg/eigen.py +21 -0
- scipy/sparse/linalg/interface.py +20 -0
- scipy/sparse/linalg/isolve.py +22 -0
- scipy/sparse/linalg/matfuncs.py +18 -0
- scipy/sparse/linalg/tests/__init__.py +0 -0
- scipy/sparse/linalg/tests/propack_test_data.npz +0 -0
- scipy/sparse/linalg/tests/test_expm_multiply.py +367 -0
- scipy/sparse/linalg/tests/test_interface.py +561 -0
- scipy/sparse/linalg/tests/test_matfuncs.py +592 -0
- scipy/sparse/linalg/tests/test_norm.py +154 -0
- scipy/sparse/linalg/tests/test_onenormest.py +252 -0
- scipy/sparse/linalg/tests/test_propack.py +165 -0
- scipy/sparse/linalg/tests/test_pydata_sparse.py +272 -0
- scipy/sparse/linalg/tests/test_special_sparse_arrays.py +337 -0
- scipy/sparse/sparsetools.py +17 -0
- scipy/sparse/spfuncs.py +17 -0
- scipy/sparse/sputils.py +17 -0
- scipy/sparse/tests/__init__.py +0 -0
- scipy/sparse/tests/data/csc_py2.npz +0 -0
- scipy/sparse/tests/data/csc_py3.npz +0 -0
- scipy/sparse/tests/test_arithmetic1d.py +341 -0
- scipy/sparse/tests/test_array_api.py +561 -0
- scipy/sparse/tests/test_base.py +5870 -0
- scipy/sparse/tests/test_common1d.py +447 -0
- scipy/sparse/tests/test_construct.py +872 -0
- scipy/sparse/tests/test_coo.py +1119 -0
- scipy/sparse/tests/test_csc.py +98 -0
- scipy/sparse/tests/test_csr.py +214 -0
- scipy/sparse/tests/test_dok.py +209 -0
- scipy/sparse/tests/test_extract.py +51 -0
- scipy/sparse/tests/test_indexing1d.py +603 -0
- scipy/sparse/tests/test_matrix_io.py +109 -0
- scipy/sparse/tests/test_minmax1d.py +128 -0
- scipy/sparse/tests/test_sparsetools.py +344 -0
- scipy/sparse/tests/test_spfuncs.py +97 -0
- scipy/sparse/tests/test_sputils.py +424 -0
- scipy/spatial/__init__.py +129 -0
- scipy/spatial/_ckdtree.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_ckdtree.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_distance_pybind.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_distance_pybind.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_distance_wrap.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_distance_wrap.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_geometric_slerp.py +238 -0
- scipy/spatial/_hausdorff.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_hausdorff.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_kdtree.py +920 -0
- scipy/spatial/_plotutils.py +274 -0
- scipy/spatial/_procrustes.py +132 -0
- scipy/spatial/_qhull.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_qhull.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_qhull.pyi +213 -0
- scipy/spatial/_spherical_voronoi.py +341 -0
- scipy/spatial/_voronoi.cp313t-win_arm64.lib +0 -0
- scipy/spatial/_voronoi.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/_voronoi.pyi +4 -0
- scipy/spatial/ckdtree.py +18 -0
- scipy/spatial/distance.py +3147 -0
- scipy/spatial/distance.pyi +210 -0
- scipy/spatial/kdtree.py +25 -0
- scipy/spatial/qhull.py +25 -0
- scipy/spatial/qhull_src/COPYING_QHULL.txt +39 -0
- scipy/spatial/tests/__init__.py +0 -0
- scipy/spatial/tests/data/cdist-X1.txt +10 -0
- scipy/spatial/tests/data/cdist-X2.txt +20 -0
- scipy/spatial/tests/data/degenerate_pointset.npz +0 -0
- scipy/spatial/tests/data/iris.txt +150 -0
- scipy/spatial/tests/data/pdist-boolean-inp.txt +20 -0
- scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-chebyshev-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-cityblock-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-correlation-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-correlation-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-cosine-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-cosine-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-double-inp.txt +20 -0
- scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-euclidean-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-hamming-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-jaccard-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-jensenshannon-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt +1 -0
- scipy/spatial/tests/data/pdist-seuclidean-ml.txt +1 -0
- scipy/spatial/tests/data/pdist-spearman-ml.txt +1 -0
- scipy/spatial/tests/data/random-bool-data.txt +100 -0
- scipy/spatial/tests/data/random-double-data.txt +100 -0
- scipy/spatial/tests/data/random-int-data.txt +100 -0
- scipy/spatial/tests/data/random-uint-data.txt +100 -0
- scipy/spatial/tests/data/selfdual-4d-polytope.txt +27 -0
- scipy/spatial/tests/test__plotutils.py +91 -0
- scipy/spatial/tests/test__procrustes.py +116 -0
- scipy/spatial/tests/test_distance.py +2389 -0
- scipy/spatial/tests/test_hausdorff.py +199 -0
- scipy/spatial/tests/test_kdtree.py +1536 -0
- scipy/spatial/tests/test_qhull.py +1313 -0
- scipy/spatial/tests/test_slerp.py +417 -0
- scipy/spatial/tests/test_spherical_voronoi.py +358 -0
- scipy/spatial/transform/__init__.py +31 -0
- scipy/spatial/transform/_rigid_transform.cp313t-win_arm64.lib +0 -0
- scipy/spatial/transform/_rigid_transform.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/transform/_rotation.cp313t-win_arm64.lib +0 -0
- scipy/spatial/transform/_rotation.cp313t-win_arm64.pyd +0 -0
- scipy/spatial/transform/_rotation_groups.py +140 -0
- scipy/spatial/transform/_rotation_spline.py +460 -0
- scipy/spatial/transform/rotation.py +21 -0
- scipy/spatial/transform/tests/__init__.py +0 -0
- scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
- scipy/spatial/transform/tests/test_rotation.py +2569 -0
- scipy/spatial/transform/tests/test_rotation_groups.py +169 -0
- scipy/spatial/transform/tests/test_rotation_spline.py +183 -0
- scipy/special/__init__.pxd +1 -0
- scipy/special/__init__.py +841 -0
- scipy/special/_add_newdocs.py +9961 -0
- scipy/special/_basic.py +3576 -0
- scipy/special/_comb.cp313t-win_arm64.lib +0 -0
- scipy/special/_comb.cp313t-win_arm64.pyd +0 -0
- scipy/special/_ellip_harm.py +214 -0
- scipy/special/_ellip_harm_2.cp313t-win_arm64.lib +0 -0
- scipy/special/_ellip_harm_2.cp313t-win_arm64.pyd +0 -0
- scipy/special/_gufuncs.cp313t-win_arm64.lib +0 -0
- scipy/special/_gufuncs.cp313t-win_arm64.pyd +0 -0
- scipy/special/_input_validation.py +17 -0
- scipy/special/_lambertw.py +149 -0
- scipy/special/_logsumexp.py +426 -0
- scipy/special/_mptestutils.py +453 -0
- scipy/special/_multiufuncs.py +610 -0
- scipy/special/_orthogonal.py +2592 -0
- scipy/special/_orthogonal.pyi +330 -0
- scipy/special/_precompute/__init__.py +0 -0
- scipy/special/_precompute/cosine_cdf.py +17 -0
- scipy/special/_precompute/expn_asy.py +54 -0
- scipy/special/_precompute/gammainc_asy.py +116 -0
- scipy/special/_precompute/gammainc_data.py +124 -0
- scipy/special/_precompute/hyp2f1_data.py +484 -0
- scipy/special/_precompute/lambertw.py +68 -0
- scipy/special/_precompute/loggamma.py +43 -0
- scipy/special/_precompute/struve_convergence.py +131 -0
- scipy/special/_precompute/utils.py +38 -0
- scipy/special/_precompute/wright_bessel.py +342 -0
- scipy/special/_precompute/wright_bessel_data.py +152 -0
- scipy/special/_precompute/wrightomega.py +41 -0
- scipy/special/_precompute/zetac.py +27 -0
- scipy/special/_sf_error.py +15 -0
- scipy/special/_specfun.cp313t-win_arm64.lib +0 -0
- scipy/special/_specfun.cp313t-win_arm64.pyd +0 -0
- scipy/special/_special_ufuncs.cp313t-win_arm64.lib +0 -0
- scipy/special/_special_ufuncs.cp313t-win_arm64.pyd +0 -0
- scipy/special/_spfun_stats.py +106 -0
- scipy/special/_spherical_bessel.py +397 -0
- scipy/special/_support_alternative_backends.py +295 -0
- scipy/special/_test_internal.cp313t-win_arm64.lib +0 -0
- scipy/special/_test_internal.cp313t-win_arm64.pyd +0 -0
- scipy/special/_test_internal.pyi +9 -0
- scipy/special/_testutils.py +321 -0
- scipy/special/_ufuncs.cp313t-win_arm64.lib +0 -0
- scipy/special/_ufuncs.cp313t-win_arm64.pyd +0 -0
- scipy/special/_ufuncs.pyi +522 -0
- scipy/special/_ufuncs.pyx +13173 -0
- scipy/special/_ufuncs_cxx.cp313t-win_arm64.lib +0 -0
- scipy/special/_ufuncs_cxx.cp313t-win_arm64.pyd +0 -0
- scipy/special/_ufuncs_cxx.pxd +142 -0
- scipy/special/_ufuncs_cxx.pyx +427 -0
- scipy/special/_ufuncs_cxx_defs.h +147 -0
- scipy/special/_ufuncs_defs.h +57 -0
- scipy/special/add_newdocs.py +15 -0
- scipy/special/basic.py +87 -0
- scipy/special/cython_special.cp313t-win_arm64.lib +0 -0
- scipy/special/cython_special.cp313t-win_arm64.pyd +0 -0
- scipy/special/cython_special.pxd +259 -0
- scipy/special/cython_special.pyi +3 -0
- scipy/special/orthogonal.py +45 -0
- scipy/special/sf_error.py +20 -0
- scipy/special/specfun.py +24 -0
- scipy/special/spfun_stats.py +17 -0
- scipy/special/tests/__init__.py +0 -0
- scipy/special/tests/_cython_examples/extending.pyx +12 -0
- scipy/special/tests/_cython_examples/meson.build +34 -0
- scipy/special/tests/data/__init__.py +0 -0
- scipy/special/tests/data/boost.npz +0 -0
- scipy/special/tests/data/gsl.npz +0 -0
- scipy/special/tests/data/local.npz +0 -0
- scipy/special/tests/test_basic.py +4815 -0
- scipy/special/tests/test_bdtr.py +112 -0
- scipy/special/tests/test_boost_ufuncs.py +64 -0
- scipy/special/tests/test_boxcox.py +125 -0
- scipy/special/tests/test_cdflib.py +712 -0
- scipy/special/tests/test_cdft_asymptotic.py +49 -0
- scipy/special/tests/test_cephes_intp_cast.py +29 -0
- scipy/special/tests/test_cosine_distr.py +83 -0
- scipy/special/tests/test_cython_special.py +363 -0
- scipy/special/tests/test_data.py +719 -0
- scipy/special/tests/test_dd.py +42 -0
- scipy/special/tests/test_digamma.py +45 -0
- scipy/special/tests/test_ellip_harm.py +278 -0
- scipy/special/tests/test_erfinv.py +89 -0
- scipy/special/tests/test_exponential_integrals.py +118 -0
- scipy/special/tests/test_extending.py +28 -0
- scipy/special/tests/test_faddeeva.py +85 -0
- scipy/special/tests/test_gamma.py +12 -0
- scipy/special/tests/test_gammainc.py +152 -0
- scipy/special/tests/test_hyp2f1.py +2566 -0
- scipy/special/tests/test_hypergeometric.py +234 -0
- scipy/special/tests/test_iv_ratio.py +249 -0
- scipy/special/tests/test_kolmogorov.py +491 -0
- scipy/special/tests/test_lambertw.py +109 -0
- scipy/special/tests/test_legendre.py +1518 -0
- scipy/special/tests/test_log1mexp.py +85 -0
- scipy/special/tests/test_loggamma.py +70 -0
- scipy/special/tests/test_logit.py +162 -0
- scipy/special/tests/test_logsumexp.py +469 -0
- scipy/special/tests/test_mpmath.py +2293 -0
- scipy/special/tests/test_nan_inputs.py +65 -0
- scipy/special/tests/test_ndtr.py +77 -0
- scipy/special/tests/test_ndtri_exp.py +94 -0
- scipy/special/tests/test_orthogonal.py +821 -0
- scipy/special/tests/test_orthogonal_eval.py +275 -0
- scipy/special/tests/test_owens_t.py +53 -0
- scipy/special/tests/test_pcf.py +24 -0
- scipy/special/tests/test_pdtr.py +48 -0
- scipy/special/tests/test_powm1.py +65 -0
- scipy/special/tests/test_precompute_expn_asy.py +24 -0
- scipy/special/tests/test_precompute_gammainc.py +108 -0
- scipy/special/tests/test_precompute_utils.py +36 -0
- scipy/special/tests/test_round.py +18 -0
- scipy/special/tests/test_sf_error.py +146 -0
- scipy/special/tests/test_sici.py +36 -0
- scipy/special/tests/test_specfun.py +48 -0
- scipy/special/tests/test_spence.py +32 -0
- scipy/special/tests/test_spfun_stats.py +61 -0
- scipy/special/tests/test_sph_harm.py +85 -0
- scipy/special/tests/test_spherical_bessel.py +400 -0
- scipy/special/tests/test_support_alternative_backends.py +248 -0
- scipy/special/tests/test_trig.py +72 -0
- scipy/special/tests/test_ufunc_signatures.py +46 -0
- scipy/special/tests/test_wright_bessel.py +205 -0
- scipy/special/tests/test_wrightomega.py +117 -0
- scipy/special/tests/test_zeta.py +301 -0
- scipy/stats/__init__.py +670 -0
- scipy/stats/_ansari_swilk_statistics.cp313t-win_arm64.lib +0 -0
- scipy/stats/_ansari_swilk_statistics.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_axis_nan_policy.py +692 -0
- scipy/stats/_biasedurn.cp313t-win_arm64.lib +0 -0
- scipy/stats/_biasedurn.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_biasedurn.pxd +27 -0
- scipy/stats/_binned_statistic.py +795 -0
- scipy/stats/_binomtest.py +375 -0
- scipy/stats/_bws_test.py +177 -0
- scipy/stats/_censored_data.py +459 -0
- scipy/stats/_common.py +5 -0
- scipy/stats/_constants.py +42 -0
- scipy/stats/_continued_fraction.py +387 -0
- scipy/stats/_continuous_distns.py +12486 -0
- scipy/stats/_correlation.py +210 -0
- scipy/stats/_covariance.py +636 -0
- scipy/stats/_crosstab.py +204 -0
- scipy/stats/_discrete_distns.py +2098 -0
- scipy/stats/_distn_infrastructure.py +4201 -0
- scipy/stats/_distr_params.py +299 -0
- scipy/stats/_distribution_infrastructure.py +5750 -0
- scipy/stats/_entropy.py +428 -0
- scipy/stats/_finite_differences.py +145 -0
- scipy/stats/_fit.py +1351 -0
- scipy/stats/_hypotests.py +2060 -0
- scipy/stats/_kde.py +732 -0
- scipy/stats/_ksstats.py +600 -0
- scipy/stats/_levy_stable/__init__.py +1231 -0
- scipy/stats/_levy_stable/levyst.cp313t-win_arm64.lib +0 -0
- scipy/stats/_levy_stable/levyst.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_mannwhitneyu.py +492 -0
- scipy/stats/_mgc.py +550 -0
- scipy/stats/_morestats.py +4626 -0
- scipy/stats/_mstats_basic.py +3658 -0
- scipy/stats/_mstats_extras.py +521 -0
- scipy/stats/_multicomp.py +449 -0
- scipy/stats/_multivariate.py +7281 -0
- scipy/stats/_new_distributions.py +452 -0
- scipy/stats/_odds_ratio.py +466 -0
- scipy/stats/_page_trend_test.py +486 -0
- scipy/stats/_probability_distribution.py +1964 -0
- scipy/stats/_qmc.py +2956 -0
- scipy/stats/_qmc_cy.cp313t-win_arm64.lib +0 -0
- scipy/stats/_qmc_cy.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_qmc_cy.pyi +54 -0
- scipy/stats/_qmvnt.py +454 -0
- scipy/stats/_qmvnt_cy.cp313t-win_arm64.lib +0 -0
- scipy/stats/_qmvnt_cy.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/__init__.py +4 -0
- scipy/stats/_rcont/rcont.cp313t-win_arm64.lib +0 -0
- scipy/stats/_rcont/rcont.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_relative_risk.py +263 -0
- scipy/stats/_resampling.py +2352 -0
- scipy/stats/_result_classes.py +40 -0
- scipy/stats/_sampling.py +1314 -0
- scipy/stats/_sensitivity_analysis.py +713 -0
- scipy/stats/_sobol.cp313t-win_arm64.lib +0 -0
- scipy/stats/_sobol.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_sobol.pyi +54 -0
- scipy/stats/_sobol_direction_numbers.npz +0 -0
- scipy/stats/_stats.cp313t-win_arm64.lib +0 -0
- scipy/stats/_stats.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_stats.pxd +10 -0
- scipy/stats/_stats_mstats_common.py +322 -0
- scipy/stats/_stats_py.py +11089 -0
- scipy/stats/_stats_pythran.cp313t-win_arm64.lib +0 -0
- scipy/stats/_stats_pythran.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_survival.py +683 -0
- scipy/stats/_tukeylambda_stats.py +199 -0
- scipy/stats/_unuran/__init__.py +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp313t-win_arm64.lib +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp313t-win_arm64.pyd +0 -0
- scipy/stats/_unuran/unuran_wrapper.pyi +179 -0
- scipy/stats/_variation.py +126 -0
- scipy/stats/_warnings_errors.py +38 -0
- scipy/stats/_wilcoxon.py +265 -0
- scipy/stats/biasedurn.py +16 -0
- scipy/stats/contingency.py +521 -0
- scipy/stats/distributions.py +24 -0
- scipy/stats/kde.py +18 -0
- scipy/stats/morestats.py +27 -0
- scipy/stats/mstats.py +140 -0
- scipy/stats/mstats_basic.py +42 -0
- scipy/stats/mstats_extras.py +25 -0
- scipy/stats/mvn.py +17 -0
- scipy/stats/qmc.py +236 -0
- scipy/stats/sampling.py +73 -0
- scipy/stats/stats.py +41 -0
- scipy/stats/tests/__init__.py +0 -0
- scipy/stats/tests/common_tests.py +356 -0
- scipy/stats/tests/data/_mvt.py +171 -0
- scipy/stats/tests/data/fisher_exact_results_from_r.py +607 -0
- scipy/stats/tests/data/jf_skew_t_gamlss_pdf_data.npy +0 -0
- scipy/stats/tests/data/levy_stable/stable-Z1-cdf-sample-data.npy +0 -0
- scipy/stats/tests/data/levy_stable/stable-Z1-pdf-sample-data.npy +0 -0
- scipy/stats/tests/data/levy_stable/stable-loc-scale-sample-data.npy +0 -0
- scipy/stats/tests/data/nist_anova/AtmWtAg.dat +108 -0
- scipy/stats/tests/data/nist_anova/SiRstv.dat +85 -0
- scipy/stats/tests/data/nist_anova/SmLs01.dat +249 -0
- scipy/stats/tests/data/nist_anova/SmLs02.dat +1869 -0
- scipy/stats/tests/data/nist_anova/SmLs03.dat +18069 -0
- scipy/stats/tests/data/nist_anova/SmLs04.dat +249 -0
- scipy/stats/tests/data/nist_anova/SmLs05.dat +1869 -0
- scipy/stats/tests/data/nist_anova/SmLs06.dat +18069 -0
- scipy/stats/tests/data/nist_anova/SmLs07.dat +249 -0
- scipy/stats/tests/data/nist_anova/SmLs08.dat +1869 -0
- scipy/stats/tests/data/nist_anova/SmLs09.dat +18069 -0
- scipy/stats/tests/data/nist_linregress/Norris.dat +97 -0
- scipy/stats/tests/data/rel_breitwigner_pdf_sample_data_ROOT.npy +0 -0
- scipy/stats/tests/data/studentized_range_mpmath_ref.json +1499 -0
- scipy/stats/tests/test_axis_nan_policy.py +1388 -0
- scipy/stats/tests/test_binned_statistic.py +568 -0
- scipy/stats/tests/test_censored_data.py +152 -0
- scipy/stats/tests/test_contingency.py +294 -0
- scipy/stats/tests/test_continued_fraction.py +173 -0
- scipy/stats/tests/test_continuous.py +2198 -0
- scipy/stats/tests/test_continuous_basic.py +1053 -0
- scipy/stats/tests/test_continuous_fit_censored.py +683 -0
- scipy/stats/tests/test_correlation.py +80 -0
- scipy/stats/tests/test_crosstab.py +115 -0
- scipy/stats/tests/test_discrete_basic.py +580 -0
- scipy/stats/tests/test_discrete_distns.py +700 -0
- scipy/stats/tests/test_distributions.py +10413 -0
- scipy/stats/tests/test_entropy.py +322 -0
- scipy/stats/tests/test_fast_gen_inversion.py +435 -0
- scipy/stats/tests/test_fit.py +1090 -0
- scipy/stats/tests/test_hypotests.py +1991 -0
- scipy/stats/tests/test_kdeoth.py +676 -0
- scipy/stats/tests/test_marray.py +289 -0
- scipy/stats/tests/test_mgc.py +217 -0
- scipy/stats/tests/test_morestats.py +3259 -0
- scipy/stats/tests/test_mstats_basic.py +2071 -0
- scipy/stats/tests/test_mstats_extras.py +172 -0
- scipy/stats/tests/test_multicomp.py +405 -0
- scipy/stats/tests/test_multivariate.py +4381 -0
- scipy/stats/tests/test_odds_ratio.py +148 -0
- scipy/stats/tests/test_qmc.py +1492 -0
- scipy/stats/tests/test_quantile.py +199 -0
- scipy/stats/tests/test_rank.py +345 -0
- scipy/stats/tests/test_relative_risk.py +95 -0
- scipy/stats/tests/test_resampling.py +2000 -0
- scipy/stats/tests/test_sampling.py +1450 -0
- scipy/stats/tests/test_sensitivity_analysis.py +310 -0
- scipy/stats/tests/test_stats.py +9707 -0
- scipy/stats/tests/test_survival.py +466 -0
- scipy/stats/tests/test_tukeylambda_stats.py +85 -0
- scipy/stats/tests/test_variation.py +216 -0
- scipy/version.py +12 -0
- scipy-1.16.2.dist-info/DELVEWHEEL +2 -0
- scipy-1.16.2.dist-info/LICENSE.txt +912 -0
- scipy-1.16.2.dist-info/METADATA +1061 -0
- scipy-1.16.2.dist-info/RECORD +1530 -0
- scipy-1.16.2.dist-info/WHEEL +4 -0
- scipy.libs/msvcp140-5f1c5dd31916990d94181e07bc3afb32.dll +0 -0
- scipy.libs/scipy_openblas-f3ac85b1f412f7e86514c923dc4058d1.dll +0 -0
@@ -0,0 +1,2577 @@
|
|
1
|
+
"""
|
2
|
+
Unit test for Linear Programming
|
3
|
+
"""
|
4
|
+
import sys
|
5
|
+
import platform
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
from numpy.exceptions import VisibleDeprecationWarning
|
9
|
+
from numpy.testing import (assert_, assert_allclose, assert_equal,
|
10
|
+
assert_array_less, assert_warns, suppress_warnings)
|
11
|
+
from pytest import raises as assert_raises
|
12
|
+
from scipy.optimize import linprog, OptimizeWarning
|
13
|
+
from scipy.optimize._numdiff import approx_derivative
|
14
|
+
from scipy.sparse.linalg import MatrixRankWarning
|
15
|
+
from scipy.linalg import LinAlgWarning
|
16
|
+
import scipy.sparse
|
17
|
+
import pytest
|
18
|
+
|
19
|
+
has_umfpack = True
|
20
|
+
try:
|
21
|
+
from scikits.umfpack import UmfpackWarning
|
22
|
+
except ImportError:
|
23
|
+
has_umfpack = False
|
24
|
+
|
25
|
+
has_cholmod = True
|
26
|
+
try:
|
27
|
+
import sksparse # noqa: F401
|
28
|
+
from sksparse.cholmod import cholesky as cholmod # noqa: F401
|
29
|
+
except ImportError:
|
30
|
+
has_cholmod = False
|
31
|
+
|
32
|
+
|
33
|
+
def _assert_iteration_limit_reached(res, maxiter):
|
34
|
+
assert_(not res.success, "Incorrectly reported success")
|
35
|
+
assert_(res.success < maxiter, "Incorrectly reported number of iterations")
|
36
|
+
assert_equal(res.status, 1, "Failed to report iteration limit reached")
|
37
|
+
|
38
|
+
|
39
|
+
def _assert_infeasible(res):
|
40
|
+
# res: linprog result object
|
41
|
+
assert_(not res.success, "incorrectly reported success")
|
42
|
+
assert_equal(res.status, 2, "failed to report infeasible status")
|
43
|
+
|
44
|
+
|
45
|
+
def _assert_unbounded(res):
|
46
|
+
# res: linprog result object
|
47
|
+
assert_(not res.success, "incorrectly reported success")
|
48
|
+
assert_equal(res.status, 3, "failed to report unbounded status")
|
49
|
+
|
50
|
+
|
51
|
+
def _assert_unable_to_find_basic_feasible_sol(res):
|
52
|
+
# res: linprog result object
|
53
|
+
|
54
|
+
# The status may be either 2 or 4 depending on why the feasible solution
|
55
|
+
# could not be found. If the underlying problem is expected to not have a
|
56
|
+
# feasible solution, _assert_infeasible should be used.
|
57
|
+
assert_(not res.success, "incorrectly reported success")
|
58
|
+
assert_(res.status in (2, 4), "failed to report optimization failure")
|
59
|
+
|
60
|
+
|
61
|
+
def _assert_success(res, desired_fun=None, desired_x=None,
|
62
|
+
rtol=1e-8, atol=1e-8):
|
63
|
+
# res: linprog result object
|
64
|
+
# desired_fun: desired objective function value or None
|
65
|
+
# desired_x: desired solution or None
|
66
|
+
if not res.success:
|
67
|
+
msg = f"linprog status {res.status}, message: {res.message}"
|
68
|
+
raise AssertionError(msg)
|
69
|
+
|
70
|
+
assert_equal(res.status, 0)
|
71
|
+
if desired_fun is not None:
|
72
|
+
assert_allclose(res.fun, desired_fun,
|
73
|
+
err_msg="converged to an unexpected objective value",
|
74
|
+
rtol=rtol, atol=atol)
|
75
|
+
if desired_x is not None:
|
76
|
+
assert_allclose(res.x, desired_x,
|
77
|
+
err_msg="converged to an unexpected solution",
|
78
|
+
rtol=rtol, atol=atol)
|
79
|
+
|
80
|
+
|
81
|
+
def magic_square(n):
|
82
|
+
"""
|
83
|
+
Generates a linear program for which integer solutions represent an
|
84
|
+
n x n magic square; binary decision variables represent the presence
|
85
|
+
(or absence) of an integer 1 to n^2 in each position of the square.
|
86
|
+
"""
|
87
|
+
|
88
|
+
rng = np.random.RandomState(0)
|
89
|
+
M = n * (n**2 + 1) / 2
|
90
|
+
|
91
|
+
numbers = np.arange(n**4) // n**2 + 1
|
92
|
+
|
93
|
+
numbers = numbers.reshape(n**2, n, n)
|
94
|
+
|
95
|
+
zeros = np.zeros((n**2, n, n))
|
96
|
+
|
97
|
+
A_list = []
|
98
|
+
b_list = []
|
99
|
+
|
100
|
+
# Rule 1: use every number exactly once
|
101
|
+
for i in range(n**2):
|
102
|
+
A_row = zeros.copy()
|
103
|
+
A_row[i, :, :] = 1
|
104
|
+
A_list.append(A_row.flatten())
|
105
|
+
b_list.append(1)
|
106
|
+
|
107
|
+
# Rule 2: Only one number per square
|
108
|
+
for i in range(n):
|
109
|
+
for j in range(n):
|
110
|
+
A_row = zeros.copy()
|
111
|
+
A_row[:, i, j] = 1
|
112
|
+
A_list.append(A_row.flatten())
|
113
|
+
b_list.append(1)
|
114
|
+
|
115
|
+
# Rule 3: sum of rows is M
|
116
|
+
for i in range(n):
|
117
|
+
A_row = zeros.copy()
|
118
|
+
A_row[:, i, :] = numbers[:, i, :]
|
119
|
+
A_list.append(A_row.flatten())
|
120
|
+
b_list.append(M)
|
121
|
+
|
122
|
+
# Rule 4: sum of columns is M
|
123
|
+
for i in range(n):
|
124
|
+
A_row = zeros.copy()
|
125
|
+
A_row[:, :, i] = numbers[:, :, i]
|
126
|
+
A_list.append(A_row.flatten())
|
127
|
+
b_list.append(M)
|
128
|
+
|
129
|
+
# Rule 5: sum of diagonals is M
|
130
|
+
A_row = zeros.copy()
|
131
|
+
A_row[:, range(n), range(n)] = numbers[:, range(n), range(n)]
|
132
|
+
A_list.append(A_row.flatten())
|
133
|
+
b_list.append(M)
|
134
|
+
A_row = zeros.copy()
|
135
|
+
A_row[:, range(n), range(-1, -n - 1, -1)] = \
|
136
|
+
numbers[:, range(n), range(-1, -n - 1, -1)]
|
137
|
+
A_list.append(A_row.flatten())
|
138
|
+
b_list.append(M)
|
139
|
+
|
140
|
+
A = np.array(np.vstack(A_list), dtype=float)
|
141
|
+
b = np.array(b_list, dtype=float)
|
142
|
+
c = rng.rand(A.shape[1])
|
143
|
+
|
144
|
+
return A, b, c, numbers, M
|
145
|
+
|
146
|
+
|
147
|
+
def lpgen_2d(m, n):
|
148
|
+
""" -> A b c LP test: m*n vars, m+n constraints
|
149
|
+
row sums == n/m, col sums == 1
|
150
|
+
https://gist.github.com/denis-bz/8647461
|
151
|
+
"""
|
152
|
+
rng = np.random.RandomState(0)
|
153
|
+
c = - rng.exponential(size=(m, n))
|
154
|
+
Arow = np.zeros((m, m * n))
|
155
|
+
brow = np.zeros(m)
|
156
|
+
for j in range(m):
|
157
|
+
j1 = j + 1
|
158
|
+
Arow[j, j * n:j1 * n] = 1
|
159
|
+
brow[j] = n / m
|
160
|
+
|
161
|
+
Acol = np.zeros((n, m * n))
|
162
|
+
bcol = np.zeros(n)
|
163
|
+
for j in range(n):
|
164
|
+
j1 = j + 1
|
165
|
+
Acol[j, j::n] = 1
|
166
|
+
bcol[j] = 1
|
167
|
+
|
168
|
+
A = np.vstack((Arow, Acol))
|
169
|
+
b = np.hstack((brow, bcol))
|
170
|
+
|
171
|
+
return A, b, c.ravel()
|
172
|
+
|
173
|
+
|
174
|
+
def very_random_gen(seed=0):
|
175
|
+
rng = np.random.RandomState(seed)
|
176
|
+
m_eq, m_ub, n = 10, 20, 50
|
177
|
+
c = rng.rand(n)-0.5
|
178
|
+
A_ub = rng.rand(m_ub, n)-0.5
|
179
|
+
b_ub = rng.rand(m_ub)-0.5
|
180
|
+
A_eq = rng.rand(m_eq, n)-0.5
|
181
|
+
b_eq = rng.rand(m_eq)-0.5
|
182
|
+
lb = -rng.rand(n)
|
183
|
+
ub = rng.rand(n)
|
184
|
+
lb[lb < -rng.rand()] = -np.inf
|
185
|
+
ub[ub > rng.rand()] = np.inf
|
186
|
+
bounds = np.vstack((lb, ub)).T
|
187
|
+
return c, A_ub, b_ub, A_eq, b_eq, bounds
|
188
|
+
|
189
|
+
|
190
|
+
def nontrivial_problem():
|
191
|
+
c = [-1, 8, 4, -6]
|
192
|
+
A_ub = [[-7, -7, 6, 9],
|
193
|
+
[1, -1, -3, 0],
|
194
|
+
[10, -10, -7, 7],
|
195
|
+
[6, -1, 3, 4]]
|
196
|
+
b_ub = [-3, 6, -6, 6]
|
197
|
+
A_eq = [[-10, 1, 1, -8]]
|
198
|
+
b_eq = [-4]
|
199
|
+
x_star = [101 / 1391, 1462 / 1391, 0, 752 / 1391]
|
200
|
+
f_star = 7083 / 1391
|
201
|
+
return c, A_ub, b_ub, A_eq, b_eq, x_star, f_star
|
202
|
+
|
203
|
+
|
204
|
+
def l1_regression_prob(seed=0, m=8, d=9, n=100):
|
205
|
+
'''
|
206
|
+
Training data is {(x0, y0), (x1, y2), ..., (xn-1, yn-1)}
|
207
|
+
x in R^d
|
208
|
+
y in R
|
209
|
+
n: number of training samples
|
210
|
+
d: dimension of x, i.e. x in R^d
|
211
|
+
phi: feature map R^d -> R^m
|
212
|
+
m: dimension of feature space
|
213
|
+
'''
|
214
|
+
rng = np.random.RandomState(seed)
|
215
|
+
phi = rng.normal(0, 1, size=(m, d)) # random feature mapping
|
216
|
+
w_true = rng.randn(m)
|
217
|
+
x = rng.normal(0, 1, size=(d, n)) # features
|
218
|
+
y = w_true @ (phi @ x) + rng.normal(0, 1e-5, size=n) # measurements
|
219
|
+
|
220
|
+
# construct the problem
|
221
|
+
c = np.ones(m+n)
|
222
|
+
c[:m] = 0
|
223
|
+
A_ub = scipy.sparse.lil_array((2*n, n+m))
|
224
|
+
idx = 0
|
225
|
+
for ii in range(n):
|
226
|
+
A_ub[idx, :m] = phi @ x[:, ii]
|
227
|
+
A_ub[idx, m+ii] = -1
|
228
|
+
A_ub[idx+1, :m] = -1*phi @ x[:, ii]
|
229
|
+
A_ub[idx+1, m+ii] = -1
|
230
|
+
idx += 2
|
231
|
+
A_ub = A_ub.tocsc()
|
232
|
+
b_ub = np.zeros(2*n)
|
233
|
+
b_ub[0::2] = y
|
234
|
+
b_ub[1::2] = -y
|
235
|
+
bnds = [(None, None)]*m + [(0, None)]*n
|
236
|
+
return c, A_ub, b_ub, bnds
|
237
|
+
|
238
|
+
|
239
|
+
def generic_callback_test(self):
|
240
|
+
# Check that callback is as advertised
|
241
|
+
last_cb = {}
|
242
|
+
|
243
|
+
def cb(res):
|
244
|
+
message = res.pop('message')
|
245
|
+
complete = res.pop('complete')
|
246
|
+
|
247
|
+
assert_(res.pop('phase') in (1, 2))
|
248
|
+
assert_(res.pop('status') in range(4))
|
249
|
+
assert_(isinstance(res.pop('nit'), int))
|
250
|
+
assert_(isinstance(complete, bool))
|
251
|
+
assert_(isinstance(message, str))
|
252
|
+
|
253
|
+
last_cb['x'] = res['x']
|
254
|
+
last_cb['fun'] = res['fun']
|
255
|
+
last_cb['slack'] = res['slack']
|
256
|
+
last_cb['con'] = res['con']
|
257
|
+
|
258
|
+
c = np.array([-3, -2])
|
259
|
+
A_ub = [[2, 1], [1, 1], [1, 0]]
|
260
|
+
b_ub = [10, 8, 4]
|
261
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, callback=cb, method=self.method)
|
262
|
+
|
263
|
+
_assert_success(res, desired_fun=-18.0, desired_x=[2, 6])
|
264
|
+
assert_allclose(last_cb['fun'], res['fun'])
|
265
|
+
assert_allclose(last_cb['x'], res['x'])
|
266
|
+
assert_allclose(last_cb['con'], res['con'])
|
267
|
+
assert_allclose(last_cb['slack'], res['slack'])
|
268
|
+
|
269
|
+
|
270
|
+
@pytest.mark.thread_unsafe
|
271
|
+
def test_unknown_solvers_and_options():
|
272
|
+
c = np.array([-3, -2])
|
273
|
+
A_ub = [[2, 1], [1, 1], [1, 0]]
|
274
|
+
b_ub = [10, 8, 4]
|
275
|
+
|
276
|
+
assert_raises(ValueError, linprog,
|
277
|
+
c, A_ub=A_ub, b_ub=b_ub, method='ekki-ekki-ekki')
|
278
|
+
assert_raises(ValueError, linprog,
|
279
|
+
c, A_ub=A_ub, b_ub=b_ub, method='highs-ekki')
|
280
|
+
message = "Unrecognized options detected: {'rr_method': 'ekki-ekki-ekki'}"
|
281
|
+
with pytest.warns(OptimizeWarning, match=message):
|
282
|
+
linprog(c, A_ub=A_ub, b_ub=b_ub,
|
283
|
+
options={"rr_method": 'ekki-ekki-ekki'})
|
284
|
+
|
285
|
+
|
286
|
+
def test_choose_solver():
|
287
|
+
# 'highs' chooses 'dual'
|
288
|
+
c = np.array([-3, -2])
|
289
|
+
A_ub = [[2, 1], [1, 1], [1, 0]]
|
290
|
+
b_ub = [10, 8, 4]
|
291
|
+
|
292
|
+
res = linprog(c, A_ub, b_ub, method='highs')
|
293
|
+
_assert_success(res, desired_fun=-18.0, desired_x=[2, 6])
|
294
|
+
|
295
|
+
|
296
|
+
@pytest.mark.thread_unsafe
|
297
|
+
def test_deprecation():
|
298
|
+
with pytest.warns(DeprecationWarning):
|
299
|
+
linprog(1, method='interior-point')
|
300
|
+
with pytest.warns(DeprecationWarning):
|
301
|
+
linprog(1, method='revised simplex')
|
302
|
+
with pytest.warns(DeprecationWarning):
|
303
|
+
linprog(1, method='simplex')
|
304
|
+
|
305
|
+
|
306
|
+
def test_highs_status_message():
|
307
|
+
res = linprog(1, method='highs')
|
308
|
+
msg = "Optimization terminated successfully. (HiGHS Status 7:"
|
309
|
+
assert res.status == 0
|
310
|
+
assert res.message.startswith(msg)
|
311
|
+
|
312
|
+
A, b, c, numbers, M = magic_square(6)
|
313
|
+
bounds = [(0, 1)] * len(c)
|
314
|
+
integrality = [1] * len(c)
|
315
|
+
options = {"time_limit": 0.1}
|
316
|
+
res = linprog(c=c, A_eq=A, b_eq=b, bounds=bounds, method='highs',
|
317
|
+
options=options, integrality=integrality)
|
318
|
+
msg = "Time limit reached. (HiGHS Status 13:"
|
319
|
+
assert res.status == 1
|
320
|
+
assert res.message.startswith(msg)
|
321
|
+
|
322
|
+
options = {"maxiter": 10}
|
323
|
+
res = linprog(c=c, A_eq=A, b_eq=b, bounds=bounds, method='highs-ds',
|
324
|
+
options=options)
|
325
|
+
msg = "Iteration limit reached. (HiGHS Status 14:"
|
326
|
+
assert res.status == 1
|
327
|
+
assert res.message.startswith(msg)
|
328
|
+
|
329
|
+
res = linprog(1, bounds=(1, -1), method='highs')
|
330
|
+
msg = "The problem is infeasible. (HiGHS Status 8:"
|
331
|
+
assert res.status == 2
|
332
|
+
assert res.message.startswith(msg)
|
333
|
+
|
334
|
+
res = linprog(-1, method='highs')
|
335
|
+
msg = "The problem is unbounded. (HiGHS Status 10:"
|
336
|
+
assert res.status == 3
|
337
|
+
assert res.message.startswith(msg)
|
338
|
+
|
339
|
+
from scipy.optimize._linprog_highs import _highs_to_scipy_status_message
|
340
|
+
status, message = _highs_to_scipy_status_message(58, "Hello!")
|
341
|
+
msg = "The HiGHS status code was not recognized. (HiGHS Status 58:"
|
342
|
+
assert status == 4
|
343
|
+
assert message.startswith(msg)
|
344
|
+
|
345
|
+
status, message = _highs_to_scipy_status_message(None, None)
|
346
|
+
msg = "HiGHS did not provide a status code. (HiGHS Status None: None)"
|
347
|
+
assert status == 4
|
348
|
+
assert message.startswith(msg)
|
349
|
+
|
350
|
+
|
351
|
+
def test_bug_17380():
|
352
|
+
linprog([1, 1], A_ub=[[-1, 0]], b_ub=[-2.5], integrality=[1, 1])
|
353
|
+
|
354
|
+
|
355
|
+
A_ub = None
|
356
|
+
b_ub = None
|
357
|
+
A_eq = None
|
358
|
+
b_eq = None
|
359
|
+
bounds = None
|
360
|
+
|
361
|
+
################
|
362
|
+
# Common Tests #
|
363
|
+
################
|
364
|
+
|
365
|
+
|
366
|
+
class LinprogCommonTests:
|
367
|
+
"""
|
368
|
+
Base class for `linprog` tests. Generally, each test will be performed
|
369
|
+
once for every derived class of LinprogCommonTests, each of which will
|
370
|
+
typically change self.options and/or self.method. Effectively, these tests
|
371
|
+
are run for many combination of method (simplex, revised simplex, and
|
372
|
+
interior point) and options (such as pivoting rule or sparse treatment).
|
373
|
+
"""
|
374
|
+
|
375
|
+
##################
|
376
|
+
# Targeted Tests #
|
377
|
+
##################
|
378
|
+
|
379
|
+
def test_callback(self):
|
380
|
+
generic_callback_test(self)
|
381
|
+
|
382
|
+
def test_disp(self):
|
383
|
+
# test that display option does not break anything.
|
384
|
+
A, b, c = lpgen_2d(20, 20)
|
385
|
+
res = linprog(c, A_ub=A, b_ub=b, method=self.method,
|
386
|
+
options={"disp": True})
|
387
|
+
_assert_success(res, desired_fun=-64.049494229)
|
388
|
+
|
389
|
+
def test_docstring_example(self):
|
390
|
+
# Example from linprog docstring.
|
391
|
+
c = [-1, 4]
|
392
|
+
A = [[-3, 1], [1, 2]]
|
393
|
+
b = [6, 4]
|
394
|
+
x0_bounds = (None, None)
|
395
|
+
x1_bounds = (-3, None)
|
396
|
+
res = linprog(c, A_ub=A, b_ub=b, bounds=(x0_bounds, x1_bounds),
|
397
|
+
options=self.options, method=self.method)
|
398
|
+
_assert_success(res, desired_fun=-22)
|
399
|
+
|
400
|
+
def test_type_error(self):
|
401
|
+
# (presumably) checks that linprog recognizes type errors
|
402
|
+
# This is tested more carefully in test__linprog_clean_inputs.py
|
403
|
+
c = [1]
|
404
|
+
A_eq = [[1]]
|
405
|
+
b_eq = "hello"
|
406
|
+
assert_raises(TypeError, linprog,
|
407
|
+
c, A_eq=A_eq, b_eq=b_eq,
|
408
|
+
method=self.method, options=self.options)
|
409
|
+
|
410
|
+
def test_aliasing_b_ub(self):
|
411
|
+
# (presumably) checks that linprog does not modify b_ub
|
412
|
+
# This is tested more carefully in test__linprog_clean_inputs.py
|
413
|
+
c = np.array([1.0])
|
414
|
+
A_ub = np.array([[1.0]])
|
415
|
+
b_ub_orig = np.array([3.0])
|
416
|
+
b_ub = b_ub_orig.copy()
|
417
|
+
bounds = (-4.0, np.inf)
|
418
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
419
|
+
method=self.method, options=self.options)
|
420
|
+
_assert_success(res, desired_fun=-4, desired_x=[-4])
|
421
|
+
assert_allclose(b_ub_orig, b_ub)
|
422
|
+
|
423
|
+
def test_aliasing_b_eq(self):
|
424
|
+
# (presumably) checks that linprog does not modify b_eq
|
425
|
+
# This is tested more carefully in test__linprog_clean_inputs.py
|
426
|
+
c = np.array([1.0])
|
427
|
+
A_eq = np.array([[1.0]])
|
428
|
+
b_eq_orig = np.array([3.0])
|
429
|
+
b_eq = b_eq_orig.copy()
|
430
|
+
bounds = (-4.0, np.inf)
|
431
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
432
|
+
method=self.method, options=self.options)
|
433
|
+
_assert_success(res, desired_fun=3, desired_x=[3])
|
434
|
+
assert_allclose(b_eq_orig, b_eq)
|
435
|
+
|
436
|
+
def test_non_ndarray_args(self):
|
437
|
+
# (presumably) checks that linprog accepts list in place of arrays
|
438
|
+
# This is tested more carefully in test__linprog_clean_inputs.py
|
439
|
+
c = [1.0]
|
440
|
+
A_ub = [[1.0]]
|
441
|
+
b_ub = [3.0]
|
442
|
+
A_eq = [[1.0]]
|
443
|
+
b_eq = [2.0]
|
444
|
+
bounds = (-1.0, 10.0)
|
445
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
446
|
+
method=self.method, options=self.options)
|
447
|
+
_assert_success(res, desired_fun=2, desired_x=[2])
|
448
|
+
|
449
|
+
@pytest.mark.thread_unsafe
|
450
|
+
def test_unknown_options(self):
|
451
|
+
c = np.array([-3, -2])
|
452
|
+
A_ub = [[2, 1], [1, 1], [1, 0]]
|
453
|
+
b_ub = [10, 8, 4]
|
454
|
+
|
455
|
+
def f(c, A_ub=None, b_ub=None, A_eq=None,
|
456
|
+
b_eq=None, bounds=None, options=None):
|
457
|
+
linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
458
|
+
method=self.method, options=options)
|
459
|
+
|
460
|
+
o = {key: self.options[key] for key in self.options}
|
461
|
+
o['spam'] = 42
|
462
|
+
|
463
|
+
assert_warns(OptimizeWarning, f,
|
464
|
+
c, A_ub=A_ub, b_ub=b_ub, options=o)
|
465
|
+
|
466
|
+
@pytest.mark.thread_unsafe
|
467
|
+
def test_integrality_without_highs(self):
|
468
|
+
# ensure that using `integrality` parameter without `method='highs'`
|
469
|
+
# raises warning and produces correct solution to relaxed problem
|
470
|
+
# source: https://en.wikipedia.org/wiki/Integer_programming#Example
|
471
|
+
A_ub = np.array([[-1, 1], [3, 2], [2, 3]])
|
472
|
+
b_ub = np.array([1, 12, 12])
|
473
|
+
c = -np.array([0, 1])
|
474
|
+
|
475
|
+
bounds = [(0, np.inf)] * len(c)
|
476
|
+
integrality = [1] * len(c)
|
477
|
+
|
478
|
+
with np.testing.assert_warns(OptimizeWarning):
|
479
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds,
|
480
|
+
method=self.method, integrality=integrality)
|
481
|
+
|
482
|
+
np.testing.assert_allclose(res.x, [1.8, 2.8])
|
483
|
+
np.testing.assert_allclose(res.fun, -2.8)
|
484
|
+
|
485
|
+
def test_invalid_inputs(self):
|
486
|
+
|
487
|
+
def f(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None, bounds=None):
|
488
|
+
linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
489
|
+
method=self.method, options=self.options)
|
490
|
+
|
491
|
+
# Test ill-formatted bounds
|
492
|
+
assert_raises(ValueError, f, [1, 2, 3], bounds=[(1, 2), (3, 4)])
|
493
|
+
with np.testing.suppress_warnings() as sup:
|
494
|
+
sup.filter(VisibleDeprecationWarning, "Creating an ndarray from ragged")
|
495
|
+
assert_raises(ValueError, f, [1, 2, 3], bounds=[(1, 2), (3, 4), (3, 4, 5)])
|
496
|
+
assert_raises(ValueError, f, [1, 2, 3], bounds=[(1, -2), (1, 2)])
|
497
|
+
|
498
|
+
# Test other invalid inputs
|
499
|
+
assert_raises(ValueError, f, [1, 2], A_ub=[[1, 2]], b_ub=[1, 2])
|
500
|
+
assert_raises(ValueError, f, [1, 2], A_ub=[[1]], b_ub=[1])
|
501
|
+
assert_raises(ValueError, f, [1, 2], A_eq=[[1, 2]], b_eq=[1, 2])
|
502
|
+
assert_raises(ValueError, f, [1, 2], A_eq=[[1]], b_eq=[1])
|
503
|
+
assert_raises(ValueError, f, [1, 2], A_eq=[1], b_eq=1)
|
504
|
+
|
505
|
+
# this last check doesn't make sense for sparse presolve
|
506
|
+
if ("_sparse_presolve" in self.options and
|
507
|
+
self.options["_sparse_presolve"]):
|
508
|
+
return
|
509
|
+
# there aren't 3-D sparse matrices
|
510
|
+
|
511
|
+
assert_raises(ValueError, f, [1, 2], A_ub=np.zeros((1, 1, 3)), b_eq=1)
|
512
|
+
|
513
|
+
def test_sparse_constraints(self):
|
514
|
+
# gh-13559: improve error message for sparse inputs when unsupported
|
515
|
+
def f(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None, bounds=None):
|
516
|
+
linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
517
|
+
method=self.method, options=self.options)
|
518
|
+
|
519
|
+
rng = np.random.RandomState(0)
|
520
|
+
m = 100
|
521
|
+
n = 150
|
522
|
+
A_eq = scipy.sparse.random_array((m, n), density=0.5)
|
523
|
+
x_valid = rng.randn(n)
|
524
|
+
c = rng.randn(n)
|
525
|
+
ub = x_valid + rng.rand(n)
|
526
|
+
lb = x_valid - rng.rand(n)
|
527
|
+
bounds = np.column_stack((lb, ub))
|
528
|
+
b_eq = A_eq @ x_valid
|
529
|
+
|
530
|
+
if self.method in {'simplex', 'revised simplex'}:
|
531
|
+
# simplex and revised simplex should raise error
|
532
|
+
with assert_raises(ValueError, match=f"Method '{self.method}' "
|
533
|
+
"does not support sparse constraint matrices."):
|
534
|
+
linprog(c=c, A_eq=A_eq, b_eq=b_eq, bounds=bounds,
|
535
|
+
method=self.method, options=self.options)
|
536
|
+
else:
|
537
|
+
# other methods should succeed
|
538
|
+
options = {**self.options}
|
539
|
+
if self.method in {'interior-point'}:
|
540
|
+
options['sparse'] = True
|
541
|
+
|
542
|
+
res = linprog(c=c, A_eq=A_eq, b_eq=b_eq, bounds=bounds,
|
543
|
+
method=self.method, options=options)
|
544
|
+
assert res.success
|
545
|
+
|
546
|
+
def test_maxiter(self):
|
547
|
+
# test iteration limit w/ Enzo example
|
548
|
+
c = [4, 8, 3, 0, 0, 0]
|
549
|
+
A = [
|
550
|
+
[2, 5, 3, -1, 0, 0],
|
551
|
+
[3, 2.5, 8, 0, -1, 0],
|
552
|
+
[8, 10, 4, 0, 0, -1]]
|
553
|
+
b = [185, 155, 600]
|
554
|
+
np.random.seed(0)
|
555
|
+
maxiter = 3
|
556
|
+
res = linprog(c, A_eq=A, b_eq=b, method=self.method,
|
557
|
+
options={"maxiter": maxiter})
|
558
|
+
_assert_iteration_limit_reached(res, maxiter)
|
559
|
+
assert_equal(res.nit, maxiter)
|
560
|
+
|
561
|
+
def test_bounds_fixed(self):
|
562
|
+
|
563
|
+
# Test fixed bounds (upper equal to lower)
|
564
|
+
# If presolve option True, test if solution found in presolve (i.e.
|
565
|
+
# number of iterations is 0).
|
566
|
+
do_presolve = self.options.get('presolve', True)
|
567
|
+
|
568
|
+
res = linprog([1], bounds=(1, 1),
|
569
|
+
method=self.method, options=self.options)
|
570
|
+
_assert_success(res, 1, 1)
|
571
|
+
if do_presolve:
|
572
|
+
assert_equal(res.nit, 0)
|
573
|
+
|
574
|
+
res = linprog([1, 2, 3], bounds=[(5, 5), (-1, -1), (3, 3)],
|
575
|
+
method=self.method, options=self.options)
|
576
|
+
_assert_success(res, 12, [5, -1, 3])
|
577
|
+
if do_presolve:
|
578
|
+
assert_equal(res.nit, 0)
|
579
|
+
|
580
|
+
res = linprog([1, 1], bounds=[(1, 1), (1, 3)],
|
581
|
+
method=self.method, options=self.options)
|
582
|
+
_assert_success(res, 2, [1, 1])
|
583
|
+
if do_presolve:
|
584
|
+
assert_equal(res.nit, 0)
|
585
|
+
|
586
|
+
res = linprog([1, 1, 2], A_eq=[[1, 0, 0], [0, 1, 0]], b_eq=[1, 7],
|
587
|
+
bounds=[(-5, 5), (0, 10), (3.5, 3.5)],
|
588
|
+
method=self.method, options=self.options)
|
589
|
+
_assert_success(res, 15, [1, 7, 3.5])
|
590
|
+
if do_presolve:
|
591
|
+
assert_equal(res.nit, 0)
|
592
|
+
|
593
|
+
def test_bounds_infeasible(self):
|
594
|
+
|
595
|
+
# Test ill-valued bounds (upper less than lower)
|
596
|
+
# If presolve option True, test if solution found in presolve (i.e.
|
597
|
+
# number of iterations is 0).
|
598
|
+
do_presolve = self.options.get('presolve', True)
|
599
|
+
|
600
|
+
res = linprog([1], bounds=(1, -2), method=self.method, options=self.options)
|
601
|
+
_assert_infeasible(res)
|
602
|
+
if do_presolve:
|
603
|
+
assert_equal(res.nit, 0)
|
604
|
+
|
605
|
+
res = linprog([1], bounds=[(1, -2)], method=self.method, options=self.options)
|
606
|
+
_assert_infeasible(res)
|
607
|
+
if do_presolve:
|
608
|
+
assert_equal(res.nit, 0)
|
609
|
+
|
610
|
+
res = linprog([1, 2, 3], bounds=[(5, 0), (1, 2), (3, 4)],
|
611
|
+
method=self.method, options=self.options)
|
612
|
+
_assert_infeasible(res)
|
613
|
+
if do_presolve:
|
614
|
+
assert_equal(res.nit, 0)
|
615
|
+
|
616
|
+
@pytest.mark.thread_unsafe
|
617
|
+
def test_bounds_infeasible_2(self):
|
618
|
+
|
619
|
+
# Test ill-valued bounds (lower inf, upper -inf)
|
620
|
+
# If presolve option True, test if solution found in presolve (i.e.
|
621
|
+
# number of iterations is 0).
|
622
|
+
# For the simplex method, the cases do not result in an
|
623
|
+
# infeasible status, but in a RuntimeWarning. This is a
|
624
|
+
# consequence of having _presolve() take care of feasibility
|
625
|
+
# checks. See issue gh-11618.
|
626
|
+
do_presolve = self.options.get('presolve', True)
|
627
|
+
simplex_without_presolve = not do_presolve and self.method == 'simplex'
|
628
|
+
|
629
|
+
c = [1, 2, 3]
|
630
|
+
bounds_1 = [(1, 2), (np.inf, np.inf), (3, 4)]
|
631
|
+
bounds_2 = [(1, 2), (-np.inf, -np.inf), (3, 4)]
|
632
|
+
|
633
|
+
if simplex_without_presolve:
|
634
|
+
def g(c, bounds):
|
635
|
+
res = linprog(c, bounds=bounds,
|
636
|
+
method=self.method, options=self.options)
|
637
|
+
return res
|
638
|
+
|
639
|
+
with pytest.warns(RuntimeWarning):
|
640
|
+
with pytest.raises(IndexError):
|
641
|
+
g(c, bounds=bounds_1)
|
642
|
+
|
643
|
+
with pytest.warns(RuntimeWarning):
|
644
|
+
with pytest.raises(IndexError):
|
645
|
+
g(c, bounds=bounds_2)
|
646
|
+
else:
|
647
|
+
res = linprog(c=c, bounds=bounds_1,
|
648
|
+
method=self.method, options=self.options)
|
649
|
+
_assert_infeasible(res)
|
650
|
+
if do_presolve:
|
651
|
+
assert_equal(res.nit, 0)
|
652
|
+
res = linprog(c=c, bounds=bounds_2,
|
653
|
+
method=self.method, options=self.options)
|
654
|
+
_assert_infeasible(res)
|
655
|
+
if do_presolve:
|
656
|
+
assert_equal(res.nit, 0)
|
657
|
+
|
658
|
+
def test_empty_constraint_1(self):
|
659
|
+
c = [-1, -2]
|
660
|
+
res = linprog(c, method=self.method, options=self.options)
|
661
|
+
_assert_unbounded(res)
|
662
|
+
|
663
|
+
def test_empty_constraint_2(self):
|
664
|
+
c = [-1, 1, -1, 1]
|
665
|
+
bounds = [(0, np.inf), (-np.inf, 0), (-1, 1), (-1, 1)]
|
666
|
+
res = linprog(c, bounds=bounds,
|
667
|
+
method=self.method, options=self.options)
|
668
|
+
_assert_unbounded(res)
|
669
|
+
# Unboundedness detected in presolve requires no iterations
|
670
|
+
if self.options.get('presolve', True):
|
671
|
+
assert_equal(res.nit, 0)
|
672
|
+
|
673
|
+
def test_empty_constraint_3(self):
|
674
|
+
c = [1, -1, 1, -1]
|
675
|
+
bounds = [(0, np.inf), (-np.inf, 0), (-1, 1), (-1, 1)]
|
676
|
+
res = linprog(c, bounds=bounds,
|
677
|
+
method=self.method, options=self.options)
|
678
|
+
_assert_success(res, desired_x=[0, 0, -1, 1], desired_fun=-2)
|
679
|
+
|
680
|
+
def test_inequality_constraints(self):
|
681
|
+
# Minimize linear function subject to linear inequality constraints.
|
682
|
+
# http://www.dam.brown.edu/people/huiwang/classes/am121/Archive/simplex_121_c.pdf
|
683
|
+
c = np.array([3, 2]) * -1 # maximize
|
684
|
+
A_ub = [[2, 1],
|
685
|
+
[1, 1],
|
686
|
+
[1, 0]]
|
687
|
+
b_ub = [10, 8, 4]
|
688
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
689
|
+
method=self.method, options=self.options)
|
690
|
+
_assert_success(res, desired_fun=-18, desired_x=[2, 6])
|
691
|
+
|
692
|
+
def test_inequality_constraints2(self):
|
693
|
+
# Minimize linear function subject to linear inequality constraints.
|
694
|
+
# http://www.statslab.cam.ac.uk/~ff271/teaching/opt/notes/notes8.pdf
|
695
|
+
# (dead link)
|
696
|
+
c = [6, 3]
|
697
|
+
A_ub = [[0, 3],
|
698
|
+
[-1, -1],
|
699
|
+
[-2, 1]]
|
700
|
+
b_ub = [2, -1, -1]
|
701
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
702
|
+
method=self.method, options=self.options)
|
703
|
+
_assert_success(res, desired_fun=5, desired_x=[2 / 3, 1 / 3])
|
704
|
+
|
705
|
+
def test_bounds_simple(self):
|
706
|
+
c = [1, 2]
|
707
|
+
bounds = (1, 2)
|
708
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
709
|
+
method=self.method, options=self.options)
|
710
|
+
_assert_success(res, desired_x=[1, 1])
|
711
|
+
|
712
|
+
bounds = [(1, 2), (1, 2)]
|
713
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
714
|
+
method=self.method, options=self.options)
|
715
|
+
_assert_success(res, desired_x=[1, 1])
|
716
|
+
|
717
|
+
def test_bounded_below_only_1(self):
|
718
|
+
c = np.array([1.0])
|
719
|
+
A_eq = np.array([[1.0]])
|
720
|
+
b_eq = np.array([3.0])
|
721
|
+
bounds = (1.0, None)
|
722
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
723
|
+
method=self.method, options=self.options)
|
724
|
+
_assert_success(res, desired_fun=3, desired_x=[3])
|
725
|
+
|
726
|
+
def test_bounded_below_only_2(self):
|
727
|
+
c = np.ones(3)
|
728
|
+
A_eq = np.eye(3)
|
729
|
+
b_eq = np.array([1, 2, 3])
|
730
|
+
bounds = (0.5, np.inf)
|
731
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
732
|
+
method=self.method, options=self.options)
|
733
|
+
_assert_success(res, desired_x=b_eq, desired_fun=np.sum(b_eq))
|
734
|
+
|
735
|
+
def test_bounded_above_only_1(self):
|
736
|
+
c = np.array([1.0])
|
737
|
+
A_eq = np.array([[1.0]])
|
738
|
+
b_eq = np.array([3.0])
|
739
|
+
bounds = (None, 10.0)
|
740
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
741
|
+
method=self.method, options=self.options)
|
742
|
+
_assert_success(res, desired_fun=3, desired_x=[3])
|
743
|
+
|
744
|
+
def test_bounded_above_only_2(self):
|
745
|
+
c = np.ones(3)
|
746
|
+
A_eq = np.eye(3)
|
747
|
+
b_eq = np.array([1, 2, 3])
|
748
|
+
bounds = (-np.inf, 4)
|
749
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
750
|
+
method=self.method, options=self.options)
|
751
|
+
_assert_success(res, desired_x=b_eq, desired_fun=np.sum(b_eq))
|
752
|
+
|
753
|
+
def test_bounds_infinity(self):
|
754
|
+
c = np.ones(3)
|
755
|
+
A_eq = np.eye(3)
|
756
|
+
b_eq = np.array([1, 2, 3])
|
757
|
+
bounds = (-np.inf, np.inf)
|
758
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
759
|
+
method=self.method, options=self.options)
|
760
|
+
_assert_success(res, desired_x=b_eq, desired_fun=np.sum(b_eq))
|
761
|
+
|
762
|
+
def test_bounds_mixed(self):
|
763
|
+
# Problem has one unbounded variable and
|
764
|
+
# another with a negative lower bound.
|
765
|
+
c = np.array([-1, 4]) * -1 # maximize
|
766
|
+
A_ub = np.array([[-3, 1],
|
767
|
+
[1, 2]], dtype=np.float64)
|
768
|
+
b_ub = [6, 4]
|
769
|
+
x0_bounds = (-np.inf, np.inf)
|
770
|
+
x1_bounds = (-3, np.inf)
|
771
|
+
bounds = (x0_bounds, x1_bounds)
|
772
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
773
|
+
method=self.method, options=self.options)
|
774
|
+
_assert_success(res, desired_fun=-80 / 7, desired_x=[-8 / 7, 18 / 7])
|
775
|
+
|
776
|
+
def test_bounds_equal_but_infeasible(self):
|
777
|
+
c = [-4, 1]
|
778
|
+
A_ub = [[7, -2], [0, 1], [2, -2]]
|
779
|
+
b_ub = [14, 0, 3]
|
780
|
+
bounds = [(2, 2), (0, None)]
|
781
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
782
|
+
method=self.method, options=self.options)
|
783
|
+
_assert_infeasible(res)
|
784
|
+
|
785
|
+
def test_bounds_equal_but_infeasible2(self):
|
786
|
+
c = [-4, 1]
|
787
|
+
A_eq = [[7, -2], [0, 1], [2, -2]]
|
788
|
+
b_eq = [14, 0, 3]
|
789
|
+
bounds = [(2, 2), (0, None)]
|
790
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
791
|
+
method=self.method, options=self.options)
|
792
|
+
_assert_infeasible(res)
|
793
|
+
|
794
|
+
def test_bounds_equal_no_presolve(self):
|
795
|
+
# There was a bug when a lower and upper bound were equal but
|
796
|
+
# presolve was not on to eliminate the variable. The bound
|
797
|
+
# was being converted to an equality constraint, but the bound
|
798
|
+
# was not eliminated, leading to issues in postprocessing.
|
799
|
+
c = [1, 2]
|
800
|
+
A_ub = [[1, 2], [1.1, 2.2]]
|
801
|
+
b_ub = [4, 8]
|
802
|
+
bounds = [(1, 2), (2, 2)]
|
803
|
+
|
804
|
+
o = {key: self.options[key] for key in self.options}
|
805
|
+
o["presolve"] = False
|
806
|
+
|
807
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
808
|
+
method=self.method, options=o)
|
809
|
+
_assert_infeasible(res)
|
810
|
+
|
811
|
+
def test_zero_column_1(self):
|
812
|
+
m, n = 3, 4
|
813
|
+
rng = np.random.RandomState(0)
|
814
|
+
c = rng.rand(n)
|
815
|
+
c[1] = 1
|
816
|
+
A_eq = rng.rand(m, n)
|
817
|
+
A_eq[:, 1] = 0
|
818
|
+
b_eq = rng.rand(m)
|
819
|
+
A_ub = [[1, 0, 1, 1]]
|
820
|
+
b_ub = 3
|
821
|
+
bounds = [(-10, 10), (-10, 10), (-10, None), (None, None)]
|
822
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
823
|
+
method=self.method, options=self.options)
|
824
|
+
_assert_success(res, desired_fun=-9.7087836730413404)
|
825
|
+
|
826
|
+
def test_zero_column_2(self):
|
827
|
+
if self.method in {'highs-ds', 'highs-ipm'}:
|
828
|
+
# See upstream issue https://github.com/ERGO-Code/HiGHS/issues/648
|
829
|
+
pytest.xfail()
|
830
|
+
|
831
|
+
rng = np.random.RandomState(0)
|
832
|
+
m, n = 2, 4
|
833
|
+
c = rng.rand(n)
|
834
|
+
c[1] = -1
|
835
|
+
A_eq = rng.rand(m, n)
|
836
|
+
A_eq[:, 1] = 0
|
837
|
+
b_eq = rng.rand(m)
|
838
|
+
|
839
|
+
A_ub = rng.rand(m, n)
|
840
|
+
A_ub[:, 1] = 0
|
841
|
+
b_ub = rng.rand(m)
|
842
|
+
bounds = (None, None)
|
843
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
844
|
+
method=self.method, options=self.options)
|
845
|
+
_assert_unbounded(res)
|
846
|
+
# Unboundedness detected in presolve
|
847
|
+
if self.options.get('presolve', True) and "highs" not in self.method:
|
848
|
+
# HiGHS detects unboundedness or infeasibility in presolve
|
849
|
+
# It needs an iteration of simplex to be sure of unboundedness
|
850
|
+
# Other solvers report that the problem is unbounded if feasible
|
851
|
+
assert_equal(res.nit, 0)
|
852
|
+
|
853
|
+
def test_zero_row_1(self):
|
854
|
+
c = [1, 2, 3]
|
855
|
+
A_eq = [[0, 0, 0], [1, 1, 1], [0, 0, 0]]
|
856
|
+
b_eq = [0, 3, 0]
|
857
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
858
|
+
method=self.method, options=self.options)
|
859
|
+
_assert_success(res, desired_fun=3)
|
860
|
+
|
861
|
+
def test_zero_row_2(self):
|
862
|
+
A_ub = [[0, 0, 0], [1, 1, 1], [0, 0, 0]]
|
863
|
+
b_ub = [0, 3, 0]
|
864
|
+
c = [1, 2, 3]
|
865
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
866
|
+
method=self.method, options=self.options)
|
867
|
+
_assert_success(res, desired_fun=0)
|
868
|
+
|
869
|
+
def test_zero_row_3(self):
|
870
|
+
m, n = 2, 4
|
871
|
+
rng = np.random.RandomState(1234)
|
872
|
+
c = rng.rand(n)
|
873
|
+
A_eq = rng.rand(m, n)
|
874
|
+
A_eq[0, :] = 0
|
875
|
+
b_eq = rng.rand(m)
|
876
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
877
|
+
method=self.method, options=self.options)
|
878
|
+
_assert_infeasible(res)
|
879
|
+
|
880
|
+
# Infeasibility detected in presolve
|
881
|
+
if self.options.get('presolve', True):
|
882
|
+
assert_equal(res.nit, 0)
|
883
|
+
|
884
|
+
def test_zero_row_4(self):
|
885
|
+
m, n = 2, 4
|
886
|
+
rng = np.random.RandomState(1234)
|
887
|
+
c = rng.rand(n)
|
888
|
+
A_ub = rng.rand(m, n)
|
889
|
+
A_ub[0, :] = 0
|
890
|
+
b_ub = -rng.rand(m)
|
891
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
892
|
+
method=self.method, options=self.options)
|
893
|
+
_assert_infeasible(res)
|
894
|
+
|
895
|
+
# Infeasibility detected in presolve
|
896
|
+
if self.options.get('presolve', True):
|
897
|
+
assert_equal(res.nit, 0)
|
898
|
+
|
899
|
+
def test_singleton_row_eq_1(self):
|
900
|
+
c = [1, 1, 1, 2]
|
901
|
+
A_eq = [[1, 0, 0, 0], [0, 2, 0, 0], [1, 0, 0, 0], [1, 1, 1, 1]]
|
902
|
+
b_eq = [1, 2, 2, 4]
|
903
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
904
|
+
method=self.method, options=self.options)
|
905
|
+
_assert_infeasible(res)
|
906
|
+
|
907
|
+
# Infeasibility detected in presolve
|
908
|
+
if self.options.get('presolve', True):
|
909
|
+
assert_equal(res.nit, 0)
|
910
|
+
|
911
|
+
def test_singleton_row_eq_2(self):
|
912
|
+
c = [1, 1, 1, 2]
|
913
|
+
A_eq = [[1, 0, 0, 0], [0, 2, 0, 0], [1, 0, 0, 0], [1, 1, 1, 1]]
|
914
|
+
b_eq = [1, 2, 1, 4]
|
915
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
916
|
+
method=self.method, options=self.options)
|
917
|
+
_assert_success(res, desired_fun=4)
|
918
|
+
|
919
|
+
def test_singleton_row_ub_1(self):
|
920
|
+
c = [1, 1, 1, 2]
|
921
|
+
A_ub = [[1, 0, 0, 0], [0, 2, 0, 0], [-1, 0, 0, 0], [1, 1, 1, 1]]
|
922
|
+
b_ub = [1, 2, -2, 4]
|
923
|
+
bounds = [(None, None), (0, None), (0, None), (0, None)]
|
924
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
925
|
+
method=self.method, options=self.options)
|
926
|
+
_assert_infeasible(res)
|
927
|
+
|
928
|
+
# Infeasibility detected in presolve
|
929
|
+
if self.options.get('presolve', True):
|
930
|
+
assert_equal(res.nit, 0)
|
931
|
+
|
932
|
+
def test_singleton_row_ub_2(self):
|
933
|
+
c = [1, 1, 1, 2]
|
934
|
+
A_ub = [[1, 0, 0, 0], [0, 2, 0, 0], [-1, 0, 0, 0], [1, 1, 1, 1]]
|
935
|
+
b_ub = [1, 2, -0.5, 4]
|
936
|
+
bounds = [(None, None), (0, None), (0, None), (0, None)]
|
937
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
938
|
+
method=self.method, options=self.options)
|
939
|
+
_assert_success(res, desired_fun=0.5)
|
940
|
+
|
941
|
+
def test_infeasible(self):
|
942
|
+
# Test linprog response to an infeasible problem
|
943
|
+
c = [-1, -1]
|
944
|
+
A_ub = [[1, 0],
|
945
|
+
[0, 1],
|
946
|
+
[-1, -1]]
|
947
|
+
b_ub = [2, 2, -5]
|
948
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
949
|
+
method=self.method, options=self.options)
|
950
|
+
_assert_infeasible(res)
|
951
|
+
|
952
|
+
def test_infeasible_inequality_bounds(self):
|
953
|
+
c = [1]
|
954
|
+
A_ub = [[2]]
|
955
|
+
b_ub = 4
|
956
|
+
bounds = (5, 6)
|
957
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
958
|
+
method=self.method, options=self.options)
|
959
|
+
_assert_infeasible(res)
|
960
|
+
|
961
|
+
# Infeasibility detected in presolve
|
962
|
+
if self.options.get('presolve', True):
|
963
|
+
assert_equal(res.nit, 0)
|
964
|
+
|
965
|
+
def test_unbounded(self):
|
966
|
+
# Test linprog response to an unbounded problem
|
967
|
+
c = np.array([1, 1]) * -1 # maximize
|
968
|
+
A_ub = [[-1, 1],
|
969
|
+
[-1, -1]]
|
970
|
+
b_ub = [-1, -2]
|
971
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
972
|
+
method=self.method, options=self.options)
|
973
|
+
_assert_unbounded(res)
|
974
|
+
|
975
|
+
def test_unbounded_below_no_presolve_corrected(self):
|
976
|
+
c = [1]
|
977
|
+
bounds = [(None, 1)]
|
978
|
+
|
979
|
+
o = {key: self.options[key] for key in self.options}
|
980
|
+
o["presolve"] = False
|
981
|
+
|
982
|
+
res = linprog(c=c, bounds=bounds,
|
983
|
+
method=self.method,
|
984
|
+
options=o)
|
985
|
+
if self.method == "revised simplex":
|
986
|
+
# Revised simplex has a special pathway for no constraints.
|
987
|
+
assert_equal(res.status, 5)
|
988
|
+
else:
|
989
|
+
_assert_unbounded(res)
|
990
|
+
|
991
|
+
def test_unbounded_no_nontrivial_constraints_1(self):
|
992
|
+
"""
|
993
|
+
Test whether presolve pathway for detecting unboundedness after
|
994
|
+
constraint elimination is working.
|
995
|
+
"""
|
996
|
+
c = np.array([0, 0, 0, 1, -1, -1])
|
997
|
+
A_ub = np.array([[1, 0, 0, 0, 0, 0],
|
998
|
+
[0, 1, 0, 0, 0, 0],
|
999
|
+
[0, 0, 0, 0, 0, -1]])
|
1000
|
+
b_ub = np.array([2, -2, 0])
|
1001
|
+
bounds = [(None, None), (None, None), (None, None),
|
1002
|
+
(-1, 1), (-1, 1), (0, None)]
|
1003
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1004
|
+
method=self.method, options=self.options)
|
1005
|
+
_assert_unbounded(res)
|
1006
|
+
if not self.method.lower().startswith("highs"):
|
1007
|
+
assert_equal(res.x[-1], np.inf)
|
1008
|
+
assert_equal(res.message[:36],
|
1009
|
+
"The problem is (trivially) unbounded")
|
1010
|
+
|
1011
|
+
def test_unbounded_no_nontrivial_constraints_2(self):
|
1012
|
+
"""
|
1013
|
+
Test whether presolve pathway for detecting unboundedness after
|
1014
|
+
constraint elimination is working.
|
1015
|
+
"""
|
1016
|
+
c = np.array([0, 0, 0, 1, -1, 1])
|
1017
|
+
A_ub = np.array([[1, 0, 0, 0, 0, 0],
|
1018
|
+
[0, 1, 0, 0, 0, 0],
|
1019
|
+
[0, 0, 0, 0, 0, 1]])
|
1020
|
+
b_ub = np.array([2, -2, 0])
|
1021
|
+
bounds = [(None, None), (None, None), (None, None),
|
1022
|
+
(-1, 1), (-1, 1), (None, 0)]
|
1023
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1024
|
+
method=self.method, options=self.options)
|
1025
|
+
_assert_unbounded(res)
|
1026
|
+
if not self.method.lower().startswith("highs"):
|
1027
|
+
assert_equal(res.x[-1], -np.inf)
|
1028
|
+
assert_equal(res.message[:36],
|
1029
|
+
"The problem is (trivially) unbounded")
|
1030
|
+
|
1031
|
+
def test_cyclic_recovery(self):
|
1032
|
+
# Test linprogs recovery from cycling using the Klee-Minty problem
|
1033
|
+
# Klee-Minty https://www.math.ubc.ca/~israel/m340/kleemin3.pdf
|
1034
|
+
c = np.array([100, 10, 1]) * -1 # maximize
|
1035
|
+
A_ub = [[1, 0, 0],
|
1036
|
+
[20, 1, 0],
|
1037
|
+
[200, 20, 1]]
|
1038
|
+
b_ub = [1, 100, 10000]
|
1039
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1040
|
+
method=self.method, options=self.options)
|
1041
|
+
_assert_success(res, desired_x=[0, 0, 10000], atol=5e-6, rtol=1e-7)
|
1042
|
+
|
1043
|
+
def test_cyclic_bland(self):
|
1044
|
+
# Test the effect of Bland's rule on a cycling problem
|
1045
|
+
c = np.array([-10, 57, 9, 24.])
|
1046
|
+
A_ub = np.array([[0.5, -5.5, -2.5, 9],
|
1047
|
+
[0.5, -1.5, -0.5, 1],
|
1048
|
+
[1, 0, 0, 0]])
|
1049
|
+
b_ub = [0, 0, 1]
|
1050
|
+
|
1051
|
+
# copy the existing options dictionary but change maxiter
|
1052
|
+
maxiter = 100
|
1053
|
+
o = {key: val for key, val in self.options.items()}
|
1054
|
+
o['maxiter'] = maxiter
|
1055
|
+
|
1056
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1057
|
+
method=self.method, options=o)
|
1058
|
+
|
1059
|
+
if self.method == 'simplex' and not self.options.get('bland'):
|
1060
|
+
# simplex cycles without Bland's rule
|
1061
|
+
_assert_iteration_limit_reached(res, o['maxiter'])
|
1062
|
+
else:
|
1063
|
+
# other methods, including simplex with Bland's rule, succeed
|
1064
|
+
_assert_success(res, desired_x=[1, 0, 1, 0])
|
1065
|
+
# note that revised simplex skips this test because it may or may not
|
1066
|
+
# cycle depending on the initial basis
|
1067
|
+
|
1068
|
+
def test_remove_redundancy_infeasibility(self):
|
1069
|
+
# mostly a test of redundancy removal, which is carefully tested in
|
1070
|
+
# test__remove_redundancy.py
|
1071
|
+
m, n = 10, 10
|
1072
|
+
rng = np.random.RandomState(0)
|
1073
|
+
c = rng.rand(n)
|
1074
|
+
A_eq = rng.rand(m, n)
|
1075
|
+
b_eq = rng.rand(m)
|
1076
|
+
A_eq[-1, :] = 2 * A_eq[-2, :]
|
1077
|
+
b_eq[-1] *= -1
|
1078
|
+
with suppress_warnings() as sup:
|
1079
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1080
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1081
|
+
method=self.method, options=self.options)
|
1082
|
+
_assert_infeasible(res)
|
1083
|
+
|
1084
|
+
#################
|
1085
|
+
# General Tests #
|
1086
|
+
#################
|
1087
|
+
|
1088
|
+
def test_nontrivial_problem(self):
|
1089
|
+
# Problem involves all constraint types,
|
1090
|
+
# negative resource limits, and rounding issues.
|
1091
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
1092
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1093
|
+
method=self.method, options=self.options)
|
1094
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
1095
|
+
|
1096
|
+
def test_lpgen_problem(self):
|
1097
|
+
# Test linprog with a rather large problem (400 variables,
|
1098
|
+
# 40 constraints) generated by https://gist.github.com/denis-bz/8647461
|
1099
|
+
A_ub, b_ub, c = lpgen_2d(20, 20)
|
1100
|
+
|
1101
|
+
with suppress_warnings() as sup:
|
1102
|
+
sup.filter(OptimizeWarning, "Solving system with option 'sym_pos'")
|
1103
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1104
|
+
sup.filter(LinAlgWarning)
|
1105
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1106
|
+
method=self.method, options=self.options)
|
1107
|
+
_assert_success(res, desired_fun=-64.049494229)
|
1108
|
+
|
1109
|
+
def test_network_flow(self):
|
1110
|
+
# A network flow problem with supply and demand at nodes
|
1111
|
+
# and with costs along directed edges.
|
1112
|
+
# https://www.princeton.edu/~rvdb/542/lectures/lec10.pdf
|
1113
|
+
c = [2, 4, 9, 11, 4, 3, 8, 7, 0, 15, 16, 18]
|
1114
|
+
n, p = -1, 1
|
1115
|
+
A_eq = [
|
1116
|
+
[n, n, p, 0, p, 0, 0, 0, 0, p, 0, 0],
|
1117
|
+
[p, 0, 0, p, 0, p, 0, 0, 0, 0, 0, 0],
|
1118
|
+
[0, 0, n, n, 0, 0, 0, 0, 0, 0, 0, 0],
|
1119
|
+
[0, 0, 0, 0, 0, 0, p, p, 0, 0, p, 0],
|
1120
|
+
[0, 0, 0, 0, n, n, n, 0, p, 0, 0, 0],
|
1121
|
+
[0, 0, 0, 0, 0, 0, 0, n, n, 0, 0, p],
|
1122
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, n, n, n]]
|
1123
|
+
b_eq = [0, 19, -16, 33, 0, 0, -36]
|
1124
|
+
with suppress_warnings() as sup:
|
1125
|
+
sup.filter(LinAlgWarning)
|
1126
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1127
|
+
method=self.method, options=self.options)
|
1128
|
+
_assert_success(res, desired_fun=755, atol=1e-6, rtol=1e-7)
|
1129
|
+
|
1130
|
+
def test_network_flow_limited_capacity(self):
|
1131
|
+
# A network flow problem with supply and demand at nodes
|
1132
|
+
# and with costs and capacities along directed edges.
|
1133
|
+
# http://blog.sommer-forst.de/2013/04/10/
|
1134
|
+
c = [2, 2, 1, 3, 1]
|
1135
|
+
bounds = [
|
1136
|
+
[0, 4],
|
1137
|
+
[0, 2],
|
1138
|
+
[0, 2],
|
1139
|
+
[0, 3],
|
1140
|
+
[0, 5]]
|
1141
|
+
n, p = -1, 1
|
1142
|
+
A_eq = [
|
1143
|
+
[n, n, 0, 0, 0],
|
1144
|
+
[p, 0, n, n, 0],
|
1145
|
+
[0, p, p, 0, n],
|
1146
|
+
[0, 0, 0, p, p]]
|
1147
|
+
b_eq = [-4, 0, 0, 4]
|
1148
|
+
|
1149
|
+
with suppress_warnings() as sup:
|
1150
|
+
# this is an UmfpackWarning but I had trouble importing it
|
1151
|
+
if has_umfpack:
|
1152
|
+
sup.filter(UmfpackWarning)
|
1153
|
+
sup.filter(RuntimeWarning, "scipy.linalg.solve\nIll...")
|
1154
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1155
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
1156
|
+
sup.filter(LinAlgWarning)
|
1157
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1158
|
+
method=self.method, options=self.options)
|
1159
|
+
_assert_success(res, desired_fun=14)
|
1160
|
+
|
1161
|
+
def test_simplex_algorithm_wikipedia_example(self):
|
1162
|
+
# https://en.wikipedia.org/wiki/Simplex_algorithm#Example
|
1163
|
+
c = [-2, -3, -4]
|
1164
|
+
A_ub = [
|
1165
|
+
[3, 2, 1],
|
1166
|
+
[2, 5, 3]]
|
1167
|
+
b_ub = [10, 15]
|
1168
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1169
|
+
method=self.method, options=self.options)
|
1170
|
+
_assert_success(res, desired_fun=-20)
|
1171
|
+
|
1172
|
+
def test_enzo_example(self):
|
1173
|
+
# https://github.com/scipy/scipy/issues/1779 lp2.py
|
1174
|
+
#
|
1175
|
+
# Translated from Octave code at:
|
1176
|
+
# http://www.ecs.shimane-u.ac.jp/~kyoshida/lpeng.htm
|
1177
|
+
# and placed under MIT licence by Enzo Michelangeli
|
1178
|
+
# with permission explicitly granted by the original author,
|
1179
|
+
# Prof. Kazunobu Yoshida
|
1180
|
+
c = [4, 8, 3, 0, 0, 0]
|
1181
|
+
A_eq = [
|
1182
|
+
[2, 5, 3, -1, 0, 0],
|
1183
|
+
[3, 2.5, 8, 0, -1, 0],
|
1184
|
+
[8, 10, 4, 0, 0, -1]]
|
1185
|
+
b_eq = [185, 155, 600]
|
1186
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1187
|
+
method=self.method, options=self.options)
|
1188
|
+
_assert_success(res, desired_fun=317.5,
|
1189
|
+
desired_x=[66.25, 0, 17.5, 0, 183.75, 0],
|
1190
|
+
atol=6e-6, rtol=1e-7)
|
1191
|
+
|
1192
|
+
def test_enzo_example_b(self):
|
1193
|
+
# rescued from https://github.com/scipy/scipy/pull/218
|
1194
|
+
c = [2.8, 6.3, 10.8, -2.8, -6.3, -10.8]
|
1195
|
+
A_eq = [[-1, -1, -1, 0, 0, 0],
|
1196
|
+
[0, 0, 0, 1, 1, 1],
|
1197
|
+
[1, 0, 0, 1, 0, 0],
|
1198
|
+
[0, 1, 0, 0, 1, 0],
|
1199
|
+
[0, 0, 1, 0, 0, 1]]
|
1200
|
+
b_eq = [-0.5, 0.4, 0.3, 0.3, 0.3]
|
1201
|
+
|
1202
|
+
with suppress_warnings() as sup:
|
1203
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1204
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1205
|
+
method=self.method, options=self.options)
|
1206
|
+
_assert_success(res, desired_fun=-1.77,
|
1207
|
+
desired_x=[0.3, 0.2, 0.0, 0.0, 0.1, 0.3])
|
1208
|
+
|
1209
|
+
def test_enzo_example_c_with_degeneracy(self):
|
1210
|
+
# rescued from https://github.com/scipy/scipy/pull/218
|
1211
|
+
m = 20
|
1212
|
+
c = -np.ones(m)
|
1213
|
+
tmp = 2 * np.pi * np.arange(1, m + 1) / (m + 1)
|
1214
|
+
A_eq = np.vstack((np.cos(tmp) - 1, np.sin(tmp)))
|
1215
|
+
b_eq = [0, 0]
|
1216
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1217
|
+
method=self.method, options=self.options)
|
1218
|
+
_assert_success(res, desired_fun=0, desired_x=np.zeros(m))
|
1219
|
+
|
1220
|
+
def test_enzo_example_c_with_unboundedness(self):
|
1221
|
+
# rescued from https://github.com/scipy/scipy/pull/218
|
1222
|
+
m = 50
|
1223
|
+
c = -np.ones(m)
|
1224
|
+
tmp = 2 * np.pi * np.arange(m) / (m + 1)
|
1225
|
+
# This test relies on `cos(0) -1 == sin(0)`, so ensure that's true
|
1226
|
+
# (SIMD code or -ffast-math may cause spurious failures otherwise)
|
1227
|
+
row0 = np.cos(tmp) - 1
|
1228
|
+
row0[0] = 0.0
|
1229
|
+
row1 = np.sin(tmp)
|
1230
|
+
row1[0] = 0.0
|
1231
|
+
A_eq = np.vstack((row0, row1))
|
1232
|
+
b_eq = [0, 0]
|
1233
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1234
|
+
method=self.method, options=self.options)
|
1235
|
+
_assert_unbounded(res)
|
1236
|
+
|
1237
|
+
def test_enzo_example_c_with_infeasibility(self):
|
1238
|
+
# rescued from https://github.com/scipy/scipy/pull/218
|
1239
|
+
m = 50
|
1240
|
+
c = -np.ones(m)
|
1241
|
+
tmp = 2 * np.pi * np.arange(m) / (m + 1)
|
1242
|
+
A_eq = np.vstack((np.cos(tmp) - 1, np.sin(tmp)))
|
1243
|
+
b_eq = [1, 1]
|
1244
|
+
|
1245
|
+
o = {key: self.options[key] for key in self.options}
|
1246
|
+
o["presolve"] = False
|
1247
|
+
|
1248
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1249
|
+
method=self.method, options=o)
|
1250
|
+
_assert_infeasible(res)
|
1251
|
+
|
1252
|
+
def test_basic_artificial_vars(self):
|
1253
|
+
# Problem is chosen to test two phase simplex methods when at the end
|
1254
|
+
# of phase 1 some artificial variables remain in the basis.
|
1255
|
+
# Also, for `method='simplex'`, the row in the tableau corresponding
|
1256
|
+
# with the artificial variables is not all zero.
|
1257
|
+
c = np.array([-0.1, -0.07, 0.004, 0.004, 0.004, 0.004])
|
1258
|
+
A_ub = np.array([[1.0, 0, 0, 0, 0, 0], [-1.0, 0, 0, 0, 0, 0],
|
1259
|
+
[0, -1.0, 0, 0, 0, 0], [0, 1.0, 0, 0, 0, 0],
|
1260
|
+
[1.0, 1.0, 0, 0, 0, 0]])
|
1261
|
+
b_ub = np.array([3.0, 3.0, 3.0, 3.0, 20.0])
|
1262
|
+
A_eq = np.array([[1.0, 0, -1, 1, -1, 1], [0, -1.0, -1, 1, -1, 1]])
|
1263
|
+
b_eq = np.array([0, 0])
|
1264
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1265
|
+
method=self.method, options=self.options)
|
1266
|
+
_assert_success(res, desired_fun=0, desired_x=np.zeros_like(c),
|
1267
|
+
atol=2e-6)
|
1268
|
+
|
1269
|
+
def test_optimize_result(self):
|
1270
|
+
# check all fields in OptimizeResult
|
1271
|
+
c, A_ub, b_ub, A_eq, b_eq, bounds = very_random_gen(0)
|
1272
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
1273
|
+
bounds=bounds, method=self.method, options=self.options)
|
1274
|
+
assert_(res.success)
|
1275
|
+
assert_(res.nit)
|
1276
|
+
assert_(not res.status)
|
1277
|
+
if 'highs' not in self.method:
|
1278
|
+
# HiGHS status/message tested separately
|
1279
|
+
assert_(res.message == "Optimization terminated successfully.")
|
1280
|
+
assert_allclose(c @ res.x, res.fun)
|
1281
|
+
assert_allclose(b_eq - A_eq @ res.x, res.con, atol=1e-11)
|
1282
|
+
assert_allclose(b_ub - A_ub @ res.x, res.slack, atol=1e-11)
|
1283
|
+
for key in ['eqlin', 'ineqlin', 'lower', 'upper']:
|
1284
|
+
if key in res.keys():
|
1285
|
+
assert isinstance(res[key]['marginals'], np.ndarray)
|
1286
|
+
assert isinstance(res[key]['residual'], np.ndarray)
|
1287
|
+
|
1288
|
+
#################
|
1289
|
+
# Bug Fix Tests #
|
1290
|
+
#################
|
1291
|
+
|
1292
|
+
def test_bug_5400(self):
|
1293
|
+
# https://github.com/scipy/scipy/issues/5400
|
1294
|
+
bounds = [
|
1295
|
+
(0, None),
|
1296
|
+
(0, 100), (0, 100), (0, 100), (0, 100), (0, 100), (0, 100),
|
1297
|
+
(0, 900), (0, 900), (0, 900), (0, 900), (0, 900), (0, 900),
|
1298
|
+
(0, None), (0, None), (0, None), (0, None), (0, None), (0, None)]
|
1299
|
+
|
1300
|
+
f = 1 / 9
|
1301
|
+
g = -1e4
|
1302
|
+
h = -3.1
|
1303
|
+
A_ub = np.array([
|
1304
|
+
[1, -2.99, 0, 0, -3, 0, 0, 0, -1, -1, 0, -1, -1, 1, 1, 0, 0, 0, 0],
|
1305
|
+
[1, 0, -2.9, h, 0, -3, 0, -1, 0, 0, -1, 0, -1, 0, 0, 1, 1, 0, 0],
|
1306
|
+
[1, 0, 0, h, 0, 0, -3, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, 1, 1],
|
1307
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1308
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1309
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1310
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1311
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1312
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1313
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1314
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1315
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1316
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
|
1317
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
|
1318
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
1319
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0],
|
1320
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0],
|
1321
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0],
|
1322
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0],
|
1323
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0],
|
1324
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1],
|
1325
|
+
[0, 1.99, -1, -1, 0, 0, 0, -1, f, f, 0, 0, 0, g, 0, 0, 0, 0, 0],
|
1326
|
+
[0, 0, 0, 0, 2, -1, -1, 0, 0, 0, -1, f, f, 0, g, 0, 0, 0, 0],
|
1327
|
+
[0, -1, 1.9, 2.1, 0, 0, 0, f, -1, -1, 0, 0, 0, 0, 0, g, 0, 0, 0],
|
1328
|
+
[0, 0, 0, 0, -1, 2, -1, 0, 0, 0, f, -1, f, 0, 0, 0, g, 0, 0],
|
1329
|
+
[0, -1, -1, 2.1, 0, 0, 0, f, f, -1, 0, 0, 0, 0, 0, 0, 0, g, 0],
|
1330
|
+
[0, 0, 0, 0, -1, -1, 2, 0, 0, 0, f, f, -1, 0, 0, 0, 0, 0, g]])
|
1331
|
+
|
1332
|
+
b_ub = np.array([
|
1333
|
+
0.0, 0, 0, 100, 100, 100, 100, 100, 100, 900, 900, 900, 900, 900,
|
1334
|
+
900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
1335
|
+
|
1336
|
+
c = np.array([-1.0, 1, 1, 1, 1, 1, 1, 1, 1,
|
1337
|
+
1, 1, 1, 1, 0, 0, 0, 0, 0, 0])
|
1338
|
+
with suppress_warnings() as sup:
|
1339
|
+
sup.filter(OptimizeWarning,
|
1340
|
+
"Solving system with option 'sym_pos'")
|
1341
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1342
|
+
sup.filter(LinAlgWarning)
|
1343
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1344
|
+
method=self.method, options=self.options)
|
1345
|
+
_assert_success(res, desired_fun=-106.63507541835018)
|
1346
|
+
|
1347
|
+
def test_bug_6139(self):
|
1348
|
+
# linprog(method='simplex') fails to find a basic feasible solution
|
1349
|
+
# if phase 1 pseudo-objective function is outside the provided tol.
|
1350
|
+
# https://github.com/scipy/scipy/issues/6139
|
1351
|
+
|
1352
|
+
# Note: This is not strictly a bug as the default tolerance determines
|
1353
|
+
# if a result is "close enough" to zero and should not be expected
|
1354
|
+
# to work for all cases.
|
1355
|
+
|
1356
|
+
c = np.array([1, 1, 1])
|
1357
|
+
A_eq = np.array([[1., 0., 0.], [-1000., 0., - 1000.]])
|
1358
|
+
b_eq = np.array([5.00000000e+00, -1.00000000e+04])
|
1359
|
+
A_ub = -np.array([[0., 1000000., 1010000.]])
|
1360
|
+
b_ub = -np.array([10000000.])
|
1361
|
+
bounds = (None, None)
|
1362
|
+
|
1363
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1364
|
+
method=self.method, options=self.options)
|
1365
|
+
|
1366
|
+
_assert_success(res, desired_fun=14.95,
|
1367
|
+
desired_x=np.array([5, 4.95, 5]))
|
1368
|
+
|
1369
|
+
def test_bug_6690(self):
|
1370
|
+
# linprog simplex used to violate bound constraint despite reporting
|
1371
|
+
# success.
|
1372
|
+
# https://github.com/scipy/scipy/issues/6690
|
1373
|
+
|
1374
|
+
A_eq = np.array([[0, 0, 0, 0.93, 0, 0.65, 0, 0, 0.83, 0]])
|
1375
|
+
b_eq = np.array([0.9626])
|
1376
|
+
A_ub = np.array([
|
1377
|
+
[0, 0, 0, 1.18, 0, 0, 0, -0.2, 0, -0.22],
|
1378
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
1379
|
+
[0, 0, 0, 0.43, 0, 0, 0, 0, 0, 0],
|
1380
|
+
[0, -1.22, -0.25, 0, 0, 0, -2.06, 0, 0, 1.37],
|
1381
|
+
[0, 0, 0, 0, 0, 0, 0, -0.25, 0, 0]
|
1382
|
+
])
|
1383
|
+
b_ub = np.array([0.615, 0, 0.172, -0.869, -0.022])
|
1384
|
+
bounds = np.array([
|
1385
|
+
[-0.84, -0.97, 0.34, 0.4, -0.33, -0.74, 0.47, 0.09, -1.45, -0.73],
|
1386
|
+
[0.37, 0.02, 2.86, 0.86, 1.18, 0.5, 1.76, 0.17, 0.32, -0.15]
|
1387
|
+
]).T
|
1388
|
+
c = np.array([
|
1389
|
+
-1.64, 0.7, 1.8, -1.06, -1.16, 0.26, 2.13, 1.53, 0.66, 0.28
|
1390
|
+
])
|
1391
|
+
|
1392
|
+
with suppress_warnings() as sup:
|
1393
|
+
if has_umfpack:
|
1394
|
+
sup.filter(UmfpackWarning)
|
1395
|
+
sup.filter(OptimizeWarning,
|
1396
|
+
"Solving system with option 'cholesky'")
|
1397
|
+
sup.filter(OptimizeWarning, "Solving system with option 'sym_pos'")
|
1398
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1399
|
+
sup.filter(LinAlgWarning)
|
1400
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1401
|
+
method=self.method, options=self.options)
|
1402
|
+
|
1403
|
+
desired_fun = -1.19099999999
|
1404
|
+
desired_x = np.array([0.3700, -0.9700, 0.3400, 0.4000, 1.1800,
|
1405
|
+
0.5000, 0.4700, 0.0900, 0.3200, -0.7300])
|
1406
|
+
_assert_success(res, desired_fun=desired_fun, desired_x=desired_x)
|
1407
|
+
|
1408
|
+
# Add small tol value to ensure arrays are less than or equal.
|
1409
|
+
atol = 1e-6
|
1410
|
+
assert_array_less(bounds[:, 0] - atol, res.x)
|
1411
|
+
assert_array_less(res.x, bounds[:, 1] + atol)
|
1412
|
+
|
1413
|
+
def test_bug_7044(self):
|
1414
|
+
# linprog simplex failed to "identify correct constraints" (?)
|
1415
|
+
# leading to a non-optimal solution if A is rank-deficient.
|
1416
|
+
# https://github.com/scipy/scipy/issues/7044
|
1417
|
+
|
1418
|
+
A_eq, b_eq, c, _, _ = magic_square(3)
|
1419
|
+
with suppress_warnings() as sup:
|
1420
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1421
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1422
|
+
sup.filter(LinAlgWarning)
|
1423
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1424
|
+
method=self.method, options=self.options)
|
1425
|
+
|
1426
|
+
desired_fun = 1.730550597
|
1427
|
+
_assert_success(res, desired_fun=desired_fun)
|
1428
|
+
assert_allclose(A_eq.dot(res.x), b_eq)
|
1429
|
+
assert_array_less(np.zeros(res.x.size) - 1e-5, res.x)
|
1430
|
+
|
1431
|
+
def test_bug_7237(self):
|
1432
|
+
# https://github.com/scipy/scipy/issues/7237
|
1433
|
+
# linprog simplex "explodes" when the pivot value is very
|
1434
|
+
# close to zero.
|
1435
|
+
|
1436
|
+
c = np.array([-1, 0, 0, 0, 0, 0, 0, 0, 0])
|
1437
|
+
A_ub = np.array([
|
1438
|
+
[1., -724., 911., -551., -555., -896., 478., -80., -293.],
|
1439
|
+
[1., 566., 42., 937., 233., 883., 392., -909., 57.],
|
1440
|
+
[1., -208., -894., 539., 321., 532., -924., 942., 55.],
|
1441
|
+
[1., 857., -859., 83., 462., -265., -971., 826., 482.],
|
1442
|
+
[1., 314., -424., 245., -424., 194., -443., -104., -429.],
|
1443
|
+
[1., 540., 679., 361., 149., -827., 876., 633., 302.],
|
1444
|
+
[0., -1., -0., -0., -0., -0., -0., -0., -0.],
|
1445
|
+
[0., -0., -1., -0., -0., -0., -0., -0., -0.],
|
1446
|
+
[0., -0., -0., -1., -0., -0., -0., -0., -0.],
|
1447
|
+
[0., -0., -0., -0., -1., -0., -0., -0., -0.],
|
1448
|
+
[0., -0., -0., -0., -0., -1., -0., -0., -0.],
|
1449
|
+
[0., -0., -0., -0., -0., -0., -1., -0., -0.],
|
1450
|
+
[0., -0., -0., -0., -0., -0., -0., -1., -0.],
|
1451
|
+
[0., -0., -0., -0., -0., -0., -0., -0., -1.],
|
1452
|
+
[0., 1., 0., 0., 0., 0., 0., 0., 0.],
|
1453
|
+
[0., 0., 1., 0., 0., 0., 0., 0., 0.],
|
1454
|
+
[0., 0., 0., 1., 0., 0., 0., 0., 0.],
|
1455
|
+
[0., 0., 0., 0., 1., 0., 0., 0., 0.],
|
1456
|
+
[0., 0., 0., 0., 0., 1., 0., 0., 0.],
|
1457
|
+
[0., 0., 0., 0., 0., 0., 1., 0., 0.],
|
1458
|
+
[0., 0., 0., 0., 0., 0., 0., 1., 0.],
|
1459
|
+
[0., 0., 0., 0., 0., 0., 0., 0., 1.]
|
1460
|
+
])
|
1461
|
+
b_ub = np.array([
|
1462
|
+
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
|
1463
|
+
0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1.])
|
1464
|
+
A_eq = np.array([[0., 1., 1., 1., 1., 1., 1., 1., 1.]])
|
1465
|
+
b_eq = np.array([[1.]])
|
1466
|
+
bounds = [(None, None)] * 9
|
1467
|
+
|
1468
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1469
|
+
method=self.method, options=self.options)
|
1470
|
+
_assert_success(res, desired_fun=108.568535, atol=1e-6)
|
1471
|
+
|
1472
|
+
def test_bug_8174(self):
|
1473
|
+
# https://github.com/scipy/scipy/issues/8174
|
1474
|
+
# The simplex method sometimes "explodes" if the pivot value is very
|
1475
|
+
# close to zero.
|
1476
|
+
A_ub = np.array([
|
1477
|
+
[22714, 1008, 13380, -2713.5, -1116],
|
1478
|
+
[-4986, -1092, -31220, 17386.5, 684],
|
1479
|
+
[-4986, 0, 0, -2713.5, 0],
|
1480
|
+
[22714, 0, 0, 17386.5, 0]])
|
1481
|
+
b_ub = np.zeros(A_ub.shape[0])
|
1482
|
+
c = -np.ones(A_ub.shape[1])
|
1483
|
+
bounds = [(0, 1)] * A_ub.shape[1]
|
1484
|
+
with suppress_warnings() as sup:
|
1485
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1486
|
+
sup.filter(LinAlgWarning)
|
1487
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1488
|
+
method=self.method, options=self.options)
|
1489
|
+
|
1490
|
+
if self.options.get('tol', 1e-9) < 1e-10 and self.method == 'simplex':
|
1491
|
+
_assert_unable_to_find_basic_feasible_sol(res)
|
1492
|
+
else:
|
1493
|
+
_assert_success(res, desired_fun=-2.0080717488789235, atol=1e-6)
|
1494
|
+
|
1495
|
+
def test_bug_8174_2(self):
|
1496
|
+
# Test supplementary example from issue 8174.
|
1497
|
+
# https://github.com/scipy/scipy/issues/8174
|
1498
|
+
# https://stackoverflow.com/questions/47717012/linprog-in-scipy-optimize-checking-solution
|
1499
|
+
c = np.array([1, 0, 0, 0, 0, 0, 0])
|
1500
|
+
A_ub = -np.identity(7)
|
1501
|
+
b_ub = np.array([[-2], [-2], [-2], [-2], [-2], [-2], [-2]])
|
1502
|
+
A_eq = np.array([
|
1503
|
+
[1, 1, 1, 1, 1, 1, 0],
|
1504
|
+
[0.3, 1.3, 0.9, 0, 0, 0, -1],
|
1505
|
+
[0.3, 0, 0, 0, 0, 0, -2/3],
|
1506
|
+
[0, 0.65, 0, 0, 0, 0, -1/15],
|
1507
|
+
[0, 0, 0.3, 0, 0, 0, -1/15]
|
1508
|
+
])
|
1509
|
+
b_eq = np.array([[100], [0], [0], [0], [0]])
|
1510
|
+
|
1511
|
+
with suppress_warnings() as sup:
|
1512
|
+
if has_umfpack:
|
1513
|
+
sup.filter(UmfpackWarning)
|
1514
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1515
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1516
|
+
method=self.method, options=self.options)
|
1517
|
+
_assert_success(res, desired_fun=43.3333333331385)
|
1518
|
+
|
1519
|
+
def test_bug_8561(self):
|
1520
|
+
# Test that pivot row is chosen correctly when using Bland's rule
|
1521
|
+
# This was originally written for the simplex method with
|
1522
|
+
# Bland's rule only, but it doesn't hurt to test all methods/options
|
1523
|
+
# https://github.com/scipy/scipy/issues/8561
|
1524
|
+
c = np.array([7, 0, -4, 1.5, 1.5])
|
1525
|
+
A_ub = np.array([
|
1526
|
+
[4, 5.5, 1.5, 1.0, -3.5],
|
1527
|
+
[1, -2.5, -2, 2.5, 0.5],
|
1528
|
+
[3, -0.5, 4, -12.5, -7],
|
1529
|
+
[-1, 4.5, 2, -3.5, -2],
|
1530
|
+
[5.5, 2, -4.5, -1, 9.5]])
|
1531
|
+
b_ub = np.array([0, 0, 0, 0, 1])
|
1532
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, options=self.options,
|
1533
|
+
method=self.method)
|
1534
|
+
_assert_success(res, desired_x=[0, 0, 19, 16/3, 29/3])
|
1535
|
+
|
1536
|
+
def test_bug_8662(self):
|
1537
|
+
# linprog simplex used to report incorrect optimal results
|
1538
|
+
# https://github.com/scipy/scipy/issues/8662
|
1539
|
+
c = [-10, 10, 6, 3]
|
1540
|
+
A_ub = [[8, -8, -4, 6],
|
1541
|
+
[-8, 8, 4, -6],
|
1542
|
+
[-4, 4, 8, -4],
|
1543
|
+
[3, -3, -3, -10]]
|
1544
|
+
b_ub = [9, -9, -9, -4]
|
1545
|
+
bounds = [(0, None), (0, None), (0, None), (0, None)]
|
1546
|
+
desired_fun = 36.0000000000
|
1547
|
+
|
1548
|
+
with suppress_warnings() as sup:
|
1549
|
+
if has_umfpack:
|
1550
|
+
sup.filter(UmfpackWarning)
|
1551
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1552
|
+
sup.filter(LinAlgWarning)
|
1553
|
+
res1 = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1554
|
+
method=self.method, options=self.options)
|
1555
|
+
|
1556
|
+
# Set boundary condition as a constraint
|
1557
|
+
A_ub.append([0, 0, -1, 0])
|
1558
|
+
b_ub.append(0)
|
1559
|
+
bounds[2] = (None, None)
|
1560
|
+
|
1561
|
+
with suppress_warnings() as sup:
|
1562
|
+
if has_umfpack:
|
1563
|
+
sup.filter(UmfpackWarning)
|
1564
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
1565
|
+
sup.filter(LinAlgWarning)
|
1566
|
+
res2 = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1567
|
+
method=self.method, options=self.options)
|
1568
|
+
rtol = 1e-5
|
1569
|
+
_assert_success(res1, desired_fun=desired_fun, rtol=rtol)
|
1570
|
+
_assert_success(res2, desired_fun=desired_fun, rtol=rtol)
|
1571
|
+
|
1572
|
+
def test_bug_8663(self):
|
1573
|
+
# exposed a bug in presolve
|
1574
|
+
# https://github.com/scipy/scipy/issues/8663
|
1575
|
+
c = [1, 5]
|
1576
|
+
A_eq = [[0, -7]]
|
1577
|
+
b_eq = [-6]
|
1578
|
+
bounds = [(0, None), (None, None)]
|
1579
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1580
|
+
method=self.method, options=self.options)
|
1581
|
+
_assert_success(res, desired_x=[0, 6./7], desired_fun=5*6./7)
|
1582
|
+
|
1583
|
+
def test_bug_8664(self):
|
1584
|
+
# interior-point has trouble with this when presolve is off
|
1585
|
+
# tested for interior-point with presolve off in TestLinprogIPSpecific
|
1586
|
+
# https://github.com/scipy/scipy/issues/8664
|
1587
|
+
c = [4]
|
1588
|
+
A_ub = [[2], [5]]
|
1589
|
+
b_ub = [4, 4]
|
1590
|
+
A_eq = [[0], [-8], [9]]
|
1591
|
+
b_eq = [3, 2, 10]
|
1592
|
+
with suppress_warnings() as sup:
|
1593
|
+
sup.filter(RuntimeWarning)
|
1594
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
1595
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1596
|
+
method=self.method, options=self.options)
|
1597
|
+
_assert_infeasible(res)
|
1598
|
+
|
1599
|
+
def test_bug_8973(self):
|
1600
|
+
"""
|
1601
|
+
Test whether bug described at:
|
1602
|
+
https://github.com/scipy/scipy/issues/8973
|
1603
|
+
was fixed.
|
1604
|
+
"""
|
1605
|
+
c = np.array([0, 0, 0, 1, -1])
|
1606
|
+
A_ub = np.array([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0]])
|
1607
|
+
b_ub = np.array([2, -2])
|
1608
|
+
bounds = [(None, None), (None, None), (None, None), (-1, 1), (-1, 1)]
|
1609
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1610
|
+
method=self.method, options=self.options)
|
1611
|
+
# solution vector x is not unique
|
1612
|
+
_assert_success(res, desired_fun=-2)
|
1613
|
+
# HiGHS IPM had an issue where the following wasn't true!
|
1614
|
+
assert_equal(c @ res.x, res.fun)
|
1615
|
+
|
1616
|
+
def test_bug_8973_2(self):
|
1617
|
+
"""
|
1618
|
+
Additional test for:
|
1619
|
+
https://github.com/scipy/scipy/issues/8973
|
1620
|
+
suggested in
|
1621
|
+
https://github.com/scipy/scipy/pull/8985
|
1622
|
+
review by @antonior92
|
1623
|
+
"""
|
1624
|
+
c = np.zeros(1)
|
1625
|
+
A_ub = np.array([[1]])
|
1626
|
+
b_ub = np.array([-2])
|
1627
|
+
bounds = (None, None)
|
1628
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1629
|
+
method=self.method, options=self.options)
|
1630
|
+
_assert_success(res, desired_x=[-2], desired_fun=0)
|
1631
|
+
|
1632
|
+
def test_bug_10124(self):
|
1633
|
+
"""
|
1634
|
+
Test for linprog docstring problem
|
1635
|
+
'disp'=True caused revised simplex failure
|
1636
|
+
"""
|
1637
|
+
c = np.zeros(1)
|
1638
|
+
A_ub = np.array([[1]])
|
1639
|
+
b_ub = np.array([-2])
|
1640
|
+
bounds = (None, None)
|
1641
|
+
c = [-1, 4]
|
1642
|
+
A_ub = [[-3, 1], [1, 2]]
|
1643
|
+
b_ub = [6, 4]
|
1644
|
+
bounds = [(None, None), (-3, None)]
|
1645
|
+
o = {"disp": True}
|
1646
|
+
o.update(self.options)
|
1647
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1648
|
+
method=self.method, options=o)
|
1649
|
+
_assert_success(res, desired_x=[10, -3], desired_fun=-22)
|
1650
|
+
|
1651
|
+
def test_bug_10349(self):
|
1652
|
+
"""
|
1653
|
+
Test for redundancy removal tolerance issue
|
1654
|
+
https://github.com/scipy/scipy/issues/10349
|
1655
|
+
"""
|
1656
|
+
A_eq = np.array([[1, 1, 0, 0, 0, 0],
|
1657
|
+
[0, 0, 1, 1, 0, 0],
|
1658
|
+
[0, 0, 0, 0, 1, 1],
|
1659
|
+
[1, 0, 1, 0, 0, 0],
|
1660
|
+
[0, 0, 0, 1, 1, 0],
|
1661
|
+
[0, 1, 0, 0, 0, 1]])
|
1662
|
+
b_eq = np.array([221, 210, 10, 141, 198, 102])
|
1663
|
+
c = np.concatenate((0, 1, np.zeros(4)), axis=None)
|
1664
|
+
with suppress_warnings() as sup:
|
1665
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
1666
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1667
|
+
method=self.method, options=self.options)
|
1668
|
+
_assert_success(res, desired_x=[129, 92, 12, 198, 0, 10], desired_fun=92)
|
1669
|
+
|
1670
|
+
@pytest.mark.skipif(sys.platform == 'darwin',
|
1671
|
+
reason=("Failing on some local macOS builds, "
|
1672
|
+
"see gh-13846"))
|
1673
|
+
def test_bug_10466(self):
|
1674
|
+
"""
|
1675
|
+
Test that autoscale fixes poorly-scaled problem
|
1676
|
+
"""
|
1677
|
+
c = [-8., -0., -8., -0., -8., -0., -0., -0., -0., -0., -0., -0., -0.]
|
1678
|
+
A_eq = [[1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
|
1679
|
+
[0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
|
1680
|
+
[0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
|
1681
|
+
[1., 0., 1., 0., 1., 0., -1., 0., 0., 0., 0., 0., 0.],
|
1682
|
+
[1., 0., 1., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0.],
|
1683
|
+
[1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
|
1684
|
+
[1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
|
1685
|
+
[1., 0., 1., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0.],
|
1686
|
+
[0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0.],
|
1687
|
+
[0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 1.]]
|
1688
|
+
|
1689
|
+
b_eq = [3.14572800e+08, 4.19430400e+08, 5.24288000e+08,
|
1690
|
+
1.00663296e+09, 1.07374182e+09, 1.07374182e+09,
|
1691
|
+
1.07374182e+09, 1.07374182e+09, 1.07374182e+09,
|
1692
|
+
1.07374182e+09]
|
1693
|
+
|
1694
|
+
o = {}
|
1695
|
+
# HiGHS methods don't use autoscale option
|
1696
|
+
if not self.method.startswith("highs"):
|
1697
|
+
o = {"autoscale": True}
|
1698
|
+
o.update(self.options)
|
1699
|
+
|
1700
|
+
with suppress_warnings() as sup:
|
1701
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
1702
|
+
if has_umfpack:
|
1703
|
+
sup.filter(UmfpackWarning)
|
1704
|
+
sup.filter(RuntimeWarning, "scipy.linalg.solve\nIll...")
|
1705
|
+
sup.filter(RuntimeWarning, "divide by zero encountered...")
|
1706
|
+
sup.filter(RuntimeWarning, "overflow encountered...")
|
1707
|
+
sup.filter(RuntimeWarning, "invalid value encountered...")
|
1708
|
+
sup.filter(LinAlgWarning, "Ill-conditioned matrix...")
|
1709
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1710
|
+
method=self.method, options=o)
|
1711
|
+
assert_allclose(res.fun, -8589934560)
|
1712
|
+
|
1713
|
+
|
1714
|
+
#########################
|
1715
|
+
# Method-specific Tests #
|
1716
|
+
#########################
|
1717
|
+
|
1718
|
+
|
1719
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
1720
|
+
class LinprogSimplexTests(LinprogCommonTests):
|
1721
|
+
method = "simplex"
|
1722
|
+
|
1723
|
+
|
1724
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
1725
|
+
class LinprogIPTests(LinprogCommonTests):
|
1726
|
+
method = "interior-point"
|
1727
|
+
|
1728
|
+
def test_bug_10466(self):
|
1729
|
+
pytest.skip("Test is failing, but solver is deprecated.")
|
1730
|
+
|
1731
|
+
|
1732
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
1733
|
+
class LinprogRSTests(LinprogCommonTests):
|
1734
|
+
method = "revised simplex"
|
1735
|
+
|
1736
|
+
# Revised simplex does not reliably solve these problems.
|
1737
|
+
# Failure is intermittent due to the random choice of elements to complete
|
1738
|
+
# the basis after phase 1 terminates. In any case, linprog exists
|
1739
|
+
# gracefully, reporting numerical difficulties. I do not think this should
|
1740
|
+
# prevent revised simplex from being merged, as it solves the problems
|
1741
|
+
# most of the time and solves a broader range of problems than the existing
|
1742
|
+
# simplex implementation.
|
1743
|
+
# I believe that the root cause is the same for all three and that this
|
1744
|
+
# same issue prevents revised simplex from solving many other problems
|
1745
|
+
# reliably. Somehow the pivoting rule allows the algorithm to pivot into
|
1746
|
+
# a singular basis. I haven't been able to find a reference that
|
1747
|
+
# acknowledges this possibility, suggesting that there is a bug. On the
|
1748
|
+
# other hand, the pivoting rule is quite simple, and I can't find a
|
1749
|
+
# mistake, which suggests that this is a possibility with the pivoting
|
1750
|
+
# rule. Hopefully, a better pivoting rule will fix the issue.
|
1751
|
+
|
1752
|
+
def test_bug_5400(self):
|
1753
|
+
pytest.skip("Intermittent failure acceptable.")
|
1754
|
+
|
1755
|
+
def test_bug_8662(self):
|
1756
|
+
pytest.skip("Intermittent failure acceptable.")
|
1757
|
+
|
1758
|
+
def test_network_flow(self):
|
1759
|
+
pytest.skip("Intermittent failure acceptable.")
|
1760
|
+
|
1761
|
+
|
1762
|
+
class LinprogHiGHSTests(LinprogCommonTests):
|
1763
|
+
def test_callback(self):
|
1764
|
+
# this is the problem from test_callback
|
1765
|
+
def cb(res):
|
1766
|
+
return None
|
1767
|
+
c = np.array([-3, -2])
|
1768
|
+
A_ub = [[2, 1], [1, 1], [1, 0]]
|
1769
|
+
b_ub = [10, 8, 4]
|
1770
|
+
assert_raises(NotImplementedError, linprog, c, A_ub=A_ub, b_ub=b_ub,
|
1771
|
+
callback=cb, method=self.method)
|
1772
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, method=self.method)
|
1773
|
+
_assert_success(res, desired_fun=-18.0, desired_x=[2, 6])
|
1774
|
+
|
1775
|
+
@pytest.mark.thread_unsafe
|
1776
|
+
@pytest.mark.parametrize("options",
|
1777
|
+
[{"maxiter": -1},
|
1778
|
+
{"disp": -1},
|
1779
|
+
{"presolve": -1},
|
1780
|
+
{"time_limit": -1},
|
1781
|
+
{"dual_feasibility_tolerance": -1},
|
1782
|
+
{"primal_feasibility_tolerance": -1},
|
1783
|
+
{"ipm_optimality_tolerance": -1},
|
1784
|
+
{"simplex_dual_edge_weight_strategy": "ekki"},
|
1785
|
+
])
|
1786
|
+
def test_invalid_option_values(self, options):
|
1787
|
+
def f(options):
|
1788
|
+
linprog(1, method=self.method, options=options)
|
1789
|
+
options.update(self.options)
|
1790
|
+
assert_warns(OptimizeWarning, f, options=options)
|
1791
|
+
|
1792
|
+
def test_crossover(self):
|
1793
|
+
A_eq, b_eq, c, _, _ = magic_square(4)
|
1794
|
+
bounds = (0, 1)
|
1795
|
+
res = linprog(c, A_eq=A_eq, b_eq=b_eq,
|
1796
|
+
bounds=bounds, method=self.method, options=self.options)
|
1797
|
+
# there should be nonzero crossover iterations for IPM (only)
|
1798
|
+
assert_equal(res.crossover_nit == 0, self.method != "highs-ipm")
|
1799
|
+
|
1800
|
+
@pytest.mark.fail_slow(10)
|
1801
|
+
def test_marginals(self):
|
1802
|
+
# Ensure lagrange multipliers are correct by comparing the derivative
|
1803
|
+
# w.r.t. b_ub/b_eq/ub/lb to the reported duals.
|
1804
|
+
c, A_ub, b_ub, A_eq, b_eq, bounds = very_random_gen(seed=0)
|
1805
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
1806
|
+
bounds=bounds, method=self.method, options=self.options)
|
1807
|
+
lb, ub = bounds.T
|
1808
|
+
|
1809
|
+
# sensitivity w.r.t. b_ub
|
1810
|
+
def f_bub(x):
|
1811
|
+
return linprog(c, A_ub, x, A_eq, b_eq, bounds,
|
1812
|
+
method=self.method).fun
|
1813
|
+
|
1814
|
+
dfdbub = approx_derivative(f_bub, b_ub, method='3-point', f0=res.fun)
|
1815
|
+
assert_allclose(res.ineqlin.marginals, dfdbub)
|
1816
|
+
|
1817
|
+
# sensitivity w.r.t. b_eq
|
1818
|
+
def f_beq(x):
|
1819
|
+
return linprog(c, A_ub, b_ub, A_eq, x, bounds,
|
1820
|
+
method=self.method).fun
|
1821
|
+
|
1822
|
+
dfdbeq = approx_derivative(f_beq, b_eq, method='3-point', f0=res.fun)
|
1823
|
+
assert_allclose(res.eqlin.marginals, dfdbeq)
|
1824
|
+
|
1825
|
+
# sensitivity w.r.t. lb
|
1826
|
+
def f_lb(x):
|
1827
|
+
bounds = np.array([x, ub]).T
|
1828
|
+
return linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1829
|
+
method=self.method).fun
|
1830
|
+
|
1831
|
+
with np.errstate(invalid='ignore'):
|
1832
|
+
# approx_derivative has trouble where lb is infinite
|
1833
|
+
dfdlb = approx_derivative(f_lb, lb, method='3-point', f0=res.fun)
|
1834
|
+
dfdlb[~np.isfinite(lb)] = 0
|
1835
|
+
|
1836
|
+
assert_allclose(res.lower.marginals, dfdlb)
|
1837
|
+
|
1838
|
+
# sensitivity w.r.t. ub
|
1839
|
+
def f_ub(x):
|
1840
|
+
bounds = np.array([lb, x]).T
|
1841
|
+
return linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
1842
|
+
method=self.method).fun
|
1843
|
+
|
1844
|
+
with np.errstate(invalid='ignore'):
|
1845
|
+
dfdub = approx_derivative(f_ub, ub, method='3-point', f0=res.fun)
|
1846
|
+
dfdub[~np.isfinite(ub)] = 0
|
1847
|
+
|
1848
|
+
assert_allclose(res.upper.marginals, dfdub)
|
1849
|
+
|
1850
|
+
def test_dual_feasibility(self):
|
1851
|
+
# Ensure solution is dual feasible using marginals
|
1852
|
+
c, A_ub, b_ub, A_eq, b_eq, bounds = very_random_gen(seed=42)
|
1853
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
1854
|
+
bounds=bounds, method=self.method, options=self.options)
|
1855
|
+
|
1856
|
+
# KKT dual feasibility equation from Theorem 1 from
|
1857
|
+
# http://www.personal.psu.edu/cxg286/LPKKT.pdf
|
1858
|
+
resid = (-c + A_ub.T @ res.ineqlin.marginals +
|
1859
|
+
A_eq.T @ res.eqlin.marginals +
|
1860
|
+
res.upper.marginals +
|
1861
|
+
res.lower.marginals)
|
1862
|
+
assert_allclose(resid, 0, atol=1e-12)
|
1863
|
+
|
1864
|
+
def test_complementary_slackness(self):
|
1865
|
+
# Ensure that the complementary slackness condition is satisfied.
|
1866
|
+
c, A_ub, b_ub, A_eq, b_eq, bounds = very_random_gen(seed=42)
|
1867
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
1868
|
+
bounds=bounds, method=self.method, options=self.options)
|
1869
|
+
|
1870
|
+
# KKT complementary slackness equation from Theorem 1 from
|
1871
|
+
# http://www.personal.psu.edu/cxg286/LPKKT.pdf modified for
|
1872
|
+
# non-zero RHS
|
1873
|
+
assert np.allclose(res.ineqlin.marginals @ (b_ub - A_ub @ res.x), 0)
|
1874
|
+
|
1875
|
+
@pytest.mark.xfail(reason='Upstream / Wrapper issue, see gh-20589')
|
1876
|
+
def test_bug_20336(self):
|
1877
|
+
"""
|
1878
|
+
Test that `linprog` now solves a poorly-scaled problem
|
1879
|
+
"""
|
1880
|
+
boundaries = [(10000.0, 9010000.0), (0.0, None), (10000.0, None),
|
1881
|
+
(0.0, 84.62623413258109), (10000.0, None), (10000.0, None),
|
1882
|
+
(10000.0, None), (10000.0, None), (10000.0, None),
|
1883
|
+
(10000.0, None), (10000.0, None), (10000.0, None),
|
1884
|
+
(10000.0, None), (None, None), (None, None), (None, None),
|
1885
|
+
(None, None), (None, None), (None, None), (None, None),
|
1886
|
+
(None, None), (None, None), (None, None), (None, None),
|
1887
|
+
(None, None), (None, None), (None, None), (None, None),
|
1888
|
+
(None, None), (None, None), (None, None), (None, None),
|
1889
|
+
(None, None)]
|
1890
|
+
eq_entries = [-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0,
|
1891
|
+
-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 0.001,
|
1892
|
+
-0.001, 3.7337777768059636e-10, 3.7337777768059636e-10, 1.0, -1.0,
|
1893
|
+
0.001, -0.001, 3.7337777768059636e-10, 3.7337777768059636e-10,
|
1894
|
+
1.0, -1.0, 0.001, -0.001, 3.7337777768059636e-10,
|
1895
|
+
3.7337777768059636e-10, 1.0, -1.0, 0.001, -0.001,
|
1896
|
+
3.7337777768059636e-10, 3.7337777768059636e-10, 1.0, -1.0, 0.001,
|
1897
|
+
-0.001, 3.7337777768059636e-10, 3.7337777768059636e-10, 1.0, -1.0,
|
1898
|
+
0.001, -0.001, 3.7337777768059636e-10, 3.7337777768059636e-10,
|
1899
|
+
1.0, -1.0, 0.001, -0.001, 3.7337777768059636e-10,
|
1900
|
+
3.7337777768059636e-10, 1.0, -1.0, 0.001, -0.001,
|
1901
|
+
3.7337777768059636e-10, 3.7337777768059636e-10, 1.0, -1.0, 0.001,
|
1902
|
+
-0.001, 3.7337777768059636e-10, 3.7337777768059636e-10, 1.0,
|
1903
|
+
-1.0, 0.001, -0.001, 3.7337777768059636e-10,
|
1904
|
+
3.7337777768059636e-10, 1.0, -1.0]
|
1905
|
+
eq_indizes = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
|
1906
|
+
11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 16,
|
1907
|
+
16, 16, 17, 17, 18, 18, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21,
|
1908
|
+
22, 22, 22, 22, 23, 23, 24, 24, 24, 24, 25, 25, 26, 26, 26, 26,
|
1909
|
+
27, 27, 28, 28, 28, 28, 29, 29, 30, 30, 30, 30, 31, 31]
|
1910
|
+
eq_vars = [15, 14, 17, 16, 19, 18, 21, 20, 23, 22, 25, 24, 27, 26, 29, 28, 31,
|
1911
|
+
30, 13, 1, 0, 32, 3, 14, 13, 4, 0, 4, 0, 32, 31, 2, 12, 2, 12, 16,
|
1912
|
+
15, 5, 4, 5, 4, 18, 17, 6, 5, 6, 5, 20, 19, 7, 6, 7, 6, 22, 21, 8,
|
1913
|
+
7, 8, 7, 24, 23, 9, 8, 9, 8, 26, 25, 10, 9, 10, 9, 28, 27, 11, 10,
|
1914
|
+
11, 10, 30, 29, 12, 11, 12, 11]
|
1915
|
+
eq_values = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9000000.0, 0.0,
|
1916
|
+
0.006587392118285457, -5032.197406716549, 0.0041860502789104696,
|
1917
|
+
-7918.93439542944, 0.0063205763583549035, -5244.625751707402,
|
1918
|
+
0.006053760598424349, -5475.7793929428, 0.005786944838493795,
|
1919
|
+
-5728.248403917573, 0.0055201290785632405, -6005.123623538355,
|
1920
|
+
0.005253313318632687, -6310.123825488683, 0.004986497558702133,
|
1921
|
+
-6647.763714796453, 0.004719681798771578, -7023.578908071522,
|
1922
|
+
0.004452866038841024, -7444.431798646482]
|
1923
|
+
coefficients = [0.0, 0.0, 0.0, -0.011816666666666668, 0.0, 0.0, 0.0, 0.0, 0.0,
|
1924
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
1925
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
1926
|
+
np_eq_entries = np.asarray(eq_entries, dtype=np.float64)
|
1927
|
+
np_eq_indizes = np.asarray(eq_indizes, dtype=np.int32)
|
1928
|
+
np_eq_vars = np.asarray(eq_vars, dtype=np.int32)
|
1929
|
+
|
1930
|
+
a_eq= scipy.sparse.csr_array((np_eq_entries,(np_eq_indizes, np_eq_vars)),
|
1931
|
+
shape=(32, 33))
|
1932
|
+
b_eq = np.asarray(eq_values, dtype=np.float64)
|
1933
|
+
c = np.asarray(coefficients, dtype=np.float64)
|
1934
|
+
|
1935
|
+
result = scipy.optimize.linprog(c, A_ub=None, b_ub=None, A_eq=a_eq, b_eq=b_eq,
|
1936
|
+
bounds=boundaries)
|
1937
|
+
assert result.status==0
|
1938
|
+
x = result.x
|
1939
|
+
n_r_x = np.linalg.norm(a_eq @ x - b_eq)
|
1940
|
+
n_r = np.linalg.norm(result.eqlin.residual)
|
1941
|
+
assert_allclose(n_r, n_r_x)
|
1942
|
+
|
1943
|
+
|
1944
|
+
################################
|
1945
|
+
# Simplex Option-Specific Tests#
|
1946
|
+
################################
|
1947
|
+
|
1948
|
+
|
1949
|
+
class TestLinprogSimplexDefault(LinprogSimplexTests):
|
1950
|
+
|
1951
|
+
def setup_method(self):
|
1952
|
+
self.options = {}
|
1953
|
+
|
1954
|
+
def test_bug_5400(self):
|
1955
|
+
pytest.skip("Simplex fails on this problem.")
|
1956
|
+
|
1957
|
+
def test_bug_7237_low_tol(self):
|
1958
|
+
# Fails if the tolerance is too strict. Here, we test that
|
1959
|
+
# even if the solution is wrong, the appropriate error is raised.
|
1960
|
+
pytest.skip("Simplex fails on this problem.")
|
1961
|
+
|
1962
|
+
@pytest.mark.thread_unsafe
|
1963
|
+
def test_bug_8174_low_tol(self):
|
1964
|
+
# Fails if the tolerance is too strict. Here, we test that
|
1965
|
+
# even if the solution is wrong, the appropriate warning is issued.
|
1966
|
+
self.options.update({'tol': 1e-12})
|
1967
|
+
with pytest.warns(OptimizeWarning):
|
1968
|
+
super().test_bug_8174()
|
1969
|
+
|
1970
|
+
|
1971
|
+
class TestLinprogSimplexBland(LinprogSimplexTests):
|
1972
|
+
|
1973
|
+
def setup_method(self):
|
1974
|
+
self.options = {'bland': True}
|
1975
|
+
|
1976
|
+
def test_bug_5400(self):
|
1977
|
+
pytest.skip("Simplex fails on this problem.")
|
1978
|
+
|
1979
|
+
@pytest.mark.thread_unsafe
|
1980
|
+
def test_bug_8174_low_tol(self):
|
1981
|
+
# Fails if the tolerance is too strict. Here, we test that
|
1982
|
+
# even if the solution is wrong, the appropriate error is raised.
|
1983
|
+
self.options.update({'tol': 1e-12})
|
1984
|
+
with pytest.raises(AssertionError):
|
1985
|
+
with pytest.warns(OptimizeWarning):
|
1986
|
+
super().test_bug_8174()
|
1987
|
+
|
1988
|
+
|
1989
|
+
class TestLinprogSimplexNoPresolve(LinprogSimplexTests):
|
1990
|
+
|
1991
|
+
def setup_method(self):
|
1992
|
+
self.options = {'presolve': False}
|
1993
|
+
|
1994
|
+
is_32_bit = np.intp(0).itemsize < 8
|
1995
|
+
is_linux = sys.platform.startswith('linux')
|
1996
|
+
|
1997
|
+
@pytest.mark.xfail(
|
1998
|
+
condition=is_32_bit and is_linux,
|
1999
|
+
reason='Fails with warning on 32-bit linux')
|
2000
|
+
def test_bug_5400(self):
|
2001
|
+
super().test_bug_5400()
|
2002
|
+
|
2003
|
+
def test_bug_6139_low_tol(self):
|
2004
|
+
# Linprog(method='simplex') fails to find a basic feasible solution
|
2005
|
+
# if phase 1 pseudo-objective function is outside the provided tol.
|
2006
|
+
# https://github.com/scipy/scipy/issues/6139
|
2007
|
+
# Without ``presolve`` eliminating such rows the result is incorrect.
|
2008
|
+
self.options.update({'tol': 1e-12})
|
2009
|
+
with pytest.raises(AssertionError, match='linprog status 4'):
|
2010
|
+
return super().test_bug_6139()
|
2011
|
+
|
2012
|
+
def test_bug_7237_low_tol(self):
|
2013
|
+
pytest.skip("Simplex fails on this problem.")
|
2014
|
+
|
2015
|
+
@pytest.mark.thread_unsafe
|
2016
|
+
def test_bug_8174_low_tol(self):
|
2017
|
+
# Fails if the tolerance is too strict. Here, we test that
|
2018
|
+
# even if the solution is wrong, the appropriate warning is issued.
|
2019
|
+
self.options.update({'tol': 1e-12})
|
2020
|
+
with pytest.warns(OptimizeWarning):
|
2021
|
+
super().test_bug_8174()
|
2022
|
+
|
2023
|
+
def test_unbounded_no_nontrivial_constraints_1(self):
|
2024
|
+
pytest.skip("Tests behavior specific to presolve")
|
2025
|
+
|
2026
|
+
def test_unbounded_no_nontrivial_constraints_2(self):
|
2027
|
+
pytest.skip("Tests behavior specific to presolve")
|
2028
|
+
|
2029
|
+
|
2030
|
+
#######################################
|
2031
|
+
# Interior-Point Option-Specific Tests#
|
2032
|
+
#######################################
|
2033
|
+
|
2034
|
+
|
2035
|
+
class TestLinprogIPDense(LinprogIPTests):
|
2036
|
+
options = {"sparse": False}
|
2037
|
+
|
2038
|
+
# see https://github.com/scipy/scipy/issues/20216 for skip reason
|
2039
|
+
@pytest.mark.skipif(
|
2040
|
+
sys.platform == 'darwin',
|
2041
|
+
reason="Fails on some macOS builds for reason not relevant to test"
|
2042
|
+
)
|
2043
|
+
def test_bug_6139(self):
|
2044
|
+
super().test_bug_6139()
|
2045
|
+
|
2046
|
+
if has_cholmod:
|
2047
|
+
class TestLinprogIPSparseCholmod(LinprogIPTests):
|
2048
|
+
options = {"sparse": True, "cholesky": True}
|
2049
|
+
|
2050
|
+
|
2051
|
+
if has_umfpack:
|
2052
|
+
class TestLinprogIPSparseUmfpack(LinprogIPTests):
|
2053
|
+
options = {"sparse": True, "cholesky": False}
|
2054
|
+
|
2055
|
+
def test_network_flow_limited_capacity(self):
|
2056
|
+
pytest.skip("Failing due to numerical issues on some platforms.")
|
2057
|
+
|
2058
|
+
|
2059
|
+
class TestLinprogIPSparse(LinprogIPTests):
|
2060
|
+
options = {"sparse": True, "cholesky": False, "sym_pos": False}
|
2061
|
+
|
2062
|
+
@pytest.mark.skipif(
|
2063
|
+
sys.platform == 'darwin',
|
2064
|
+
reason="Fails on macOS x86 Accelerate builds (gh-20510)"
|
2065
|
+
)
|
2066
|
+
@pytest.mark.xfail_on_32bit("This test is sensitive to machine epsilon level "
|
2067
|
+
"perturbations in linear system solution in "
|
2068
|
+
"_linprog_ip._sym_solve.")
|
2069
|
+
def test_bug_6139(self):
|
2070
|
+
super().test_bug_6139()
|
2071
|
+
|
2072
|
+
@pytest.mark.xfail(reason='Fails with ATLAS, see gh-7877')
|
2073
|
+
def test_bug_6690(self):
|
2074
|
+
# Test defined in base class, but can't mark as xfail there
|
2075
|
+
super().test_bug_6690()
|
2076
|
+
|
2077
|
+
def test_magic_square_sparse_no_presolve(self):
|
2078
|
+
# test linprog with a problem with a rank-deficient A_eq matrix
|
2079
|
+
A_eq, b_eq, c, _, _ = magic_square(3)
|
2080
|
+
bounds = (0, 1)
|
2081
|
+
|
2082
|
+
with suppress_warnings() as sup:
|
2083
|
+
if has_umfpack:
|
2084
|
+
sup.filter(UmfpackWarning)
|
2085
|
+
sup.filter(MatrixRankWarning, "Matrix is exactly singular")
|
2086
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
2087
|
+
|
2088
|
+
o = {key: self.options[key] for key in self.options}
|
2089
|
+
o["presolve"] = False
|
2090
|
+
|
2091
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2092
|
+
method=self.method, options=o)
|
2093
|
+
_assert_success(res, desired_fun=1.730550597)
|
2094
|
+
|
2095
|
+
def test_sparse_solve_options(self):
|
2096
|
+
# checking that problem is solved with all column permutation options
|
2097
|
+
A_eq, b_eq, c, _, _ = magic_square(3)
|
2098
|
+
with suppress_warnings() as sup:
|
2099
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
2100
|
+
sup.filter(OptimizeWarning, "Invalid permc_spec option")
|
2101
|
+
o = {key: self.options[key] for key in self.options}
|
2102
|
+
permc_specs = ('NATURAL', 'MMD_ATA', 'MMD_AT_PLUS_A',
|
2103
|
+
'COLAMD', 'ekki-ekki-ekki')
|
2104
|
+
# 'ekki-ekki-ekki' raises warning about invalid permc_spec option
|
2105
|
+
# and uses default
|
2106
|
+
for permc_spec in permc_specs:
|
2107
|
+
o["permc_spec"] = permc_spec
|
2108
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2109
|
+
method=self.method, options=o)
|
2110
|
+
_assert_success(res, desired_fun=1.730550597)
|
2111
|
+
|
2112
|
+
|
2113
|
+
class TestLinprogIPSparsePresolve(LinprogIPTests):
|
2114
|
+
options = {"sparse": True, "_sparse_presolve": True}
|
2115
|
+
|
2116
|
+
@pytest.mark.skipif(
|
2117
|
+
sys.platform == 'darwin',
|
2118
|
+
reason="Fails on macOS x86 Accelerate builds (gh-20510)"
|
2119
|
+
)
|
2120
|
+
@pytest.mark.xfail_on_32bit("This test is sensitive to machine epsilon level "
|
2121
|
+
"perturbations in linear system solution in "
|
2122
|
+
"_linprog_ip._sym_solve.")
|
2123
|
+
def test_bug_6139(self):
|
2124
|
+
super().test_bug_6139()
|
2125
|
+
|
2126
|
+
def test_enzo_example_c_with_infeasibility(self):
|
2127
|
+
pytest.skip('_sparse_presolve=True incompatible with presolve=False')
|
2128
|
+
|
2129
|
+
@pytest.mark.xfail(reason='Fails with ATLAS, see gh-7877')
|
2130
|
+
def test_bug_6690(self):
|
2131
|
+
# Test defined in base class, but can't mark as xfail there
|
2132
|
+
super().test_bug_6690()
|
2133
|
+
|
2134
|
+
|
2135
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
2136
|
+
class TestLinprogIPSpecific:
|
2137
|
+
method = "interior-point"
|
2138
|
+
# the following tests don't need to be performed separately for
|
2139
|
+
# sparse presolve, sparse after presolve, and dense
|
2140
|
+
|
2141
|
+
def test_solver_select(self):
|
2142
|
+
# check that default solver is selected as expected
|
2143
|
+
if has_cholmod:
|
2144
|
+
options = {'sparse': True, 'cholesky': True}
|
2145
|
+
elif has_umfpack:
|
2146
|
+
options = {'sparse': True, 'cholesky': False}
|
2147
|
+
else:
|
2148
|
+
options = {'sparse': True, 'cholesky': False, 'sym_pos': False}
|
2149
|
+
A, b, c = lpgen_2d(20, 20)
|
2150
|
+
res1 = linprog(c, A_ub=A, b_ub=b, method=self.method, options=options)
|
2151
|
+
res2 = linprog(c, A_ub=A, b_ub=b, method=self.method) # default solver
|
2152
|
+
assert_allclose(res1.fun, res2.fun,
|
2153
|
+
err_msg="linprog default solver unexpected result",
|
2154
|
+
rtol=2e-15, atol=1e-15)
|
2155
|
+
|
2156
|
+
def test_unbounded_below_no_presolve_original(self):
|
2157
|
+
# formerly caused segfault in TravisCI w/ "cholesky":True
|
2158
|
+
c = [-1]
|
2159
|
+
bounds = [(None, 1)]
|
2160
|
+
res = linprog(c=c, bounds=bounds,
|
2161
|
+
method=self.method,
|
2162
|
+
options={"presolve": False, "cholesky": True})
|
2163
|
+
_assert_success(res, desired_fun=-1)
|
2164
|
+
|
2165
|
+
def test_cholesky(self):
|
2166
|
+
# use cholesky factorization and triangular solves
|
2167
|
+
A, b, c = lpgen_2d(20, 20)
|
2168
|
+
res = linprog(c, A_ub=A, b_ub=b, method=self.method,
|
2169
|
+
options={"cholesky": True}) # only for dense
|
2170
|
+
_assert_success(res, desired_fun=-64.049494229)
|
2171
|
+
|
2172
|
+
def test_alternate_initial_point(self):
|
2173
|
+
# use "improved" initial point
|
2174
|
+
A, b, c = lpgen_2d(20, 20)
|
2175
|
+
with suppress_warnings() as sup:
|
2176
|
+
sup.filter(RuntimeWarning, "scipy.linalg.solve\nIll...")
|
2177
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
2178
|
+
sup.filter(LinAlgWarning, "Ill-conditioned matrix...")
|
2179
|
+
res = linprog(c, A_ub=A, b_ub=b, method=self.method,
|
2180
|
+
options={"ip": True, "disp": True})
|
2181
|
+
# ip code is independent of sparse/dense
|
2182
|
+
_assert_success(res, desired_fun=-64.049494229)
|
2183
|
+
|
2184
|
+
def test_bug_8664(self):
|
2185
|
+
# interior-point has trouble with this when presolve is off
|
2186
|
+
c = [4]
|
2187
|
+
A_ub = [[2], [5]]
|
2188
|
+
b_ub = [4, 4]
|
2189
|
+
A_eq = [[0], [-8], [9]]
|
2190
|
+
b_eq = [3, 2, 10]
|
2191
|
+
with suppress_warnings() as sup:
|
2192
|
+
sup.filter(RuntimeWarning)
|
2193
|
+
sup.filter(OptimizeWarning, "Solving system with option...")
|
2194
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2195
|
+
method=self.method, options={"presolve": False})
|
2196
|
+
assert_(not res.success, "Incorrectly reported success")
|
2197
|
+
|
2198
|
+
|
2199
|
+
########################################
|
2200
|
+
# Revised Simplex Option-Specific Tests#
|
2201
|
+
########################################
|
2202
|
+
|
2203
|
+
|
2204
|
+
class TestLinprogRSCommon(LinprogRSTests):
|
2205
|
+
options = {}
|
2206
|
+
|
2207
|
+
def test_cyclic_bland(self):
|
2208
|
+
pytest.skip("Intermittent failure acceptable.")
|
2209
|
+
|
2210
|
+
def test_nontrivial_problem_with_guess(self):
|
2211
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2212
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2213
|
+
method=self.method, options=self.options, x0=x_star)
|
2214
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
2215
|
+
assert_equal(res.nit, 0)
|
2216
|
+
|
2217
|
+
def test_nontrivial_problem_with_unbounded_variables(self):
|
2218
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2219
|
+
bounds = [(None, None), (None, None), (0, None), (None, None)]
|
2220
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2221
|
+
method=self.method, options=self.options, x0=x_star)
|
2222
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
2223
|
+
assert_equal(res.nit, 0)
|
2224
|
+
|
2225
|
+
def test_nontrivial_problem_with_bounded_variables(self):
|
2226
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2227
|
+
bounds = [(None, 1), (1, None), (0, None), (.4, .6)]
|
2228
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2229
|
+
method=self.method, options=self.options, x0=x_star)
|
2230
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
2231
|
+
assert_equal(res.nit, 0)
|
2232
|
+
|
2233
|
+
def test_nontrivial_problem_with_negative_unbounded_variable(self):
|
2234
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2235
|
+
b_eq = [4]
|
2236
|
+
x_star = np.array([-219/385, 582/385, 0, 4/10])
|
2237
|
+
f_star = 3951/385
|
2238
|
+
bounds = [(None, None), (1, None), (0, None), (.4, .6)]
|
2239
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2240
|
+
method=self.method, options=self.options, x0=x_star)
|
2241
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
2242
|
+
assert_equal(res.nit, 0)
|
2243
|
+
|
2244
|
+
def test_nontrivial_problem_with_bad_guess(self):
|
2245
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2246
|
+
bad_guess = [1, 2, 3, .5]
|
2247
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2248
|
+
method=self.method, options=self.options, x0=bad_guess)
|
2249
|
+
assert_equal(res.status, 6)
|
2250
|
+
|
2251
|
+
def test_redundant_constraints_with_guess(self):
|
2252
|
+
A, b, c, _, _ = magic_square(3)
|
2253
|
+
p = np.random.rand(*c.shape)
|
2254
|
+
with suppress_warnings() as sup:
|
2255
|
+
sup.filter(OptimizeWarning, "A_eq does not appear...")
|
2256
|
+
sup.filter(RuntimeWarning, "invalid value encountered")
|
2257
|
+
sup.filter(LinAlgWarning)
|
2258
|
+
res = linprog(c, A_eq=A, b_eq=b, method=self.method)
|
2259
|
+
res2 = linprog(c, A_eq=A, b_eq=b, method=self.method, x0=res.x)
|
2260
|
+
res3 = linprog(c + p, A_eq=A, b_eq=b, method=self.method, x0=res.x)
|
2261
|
+
_assert_success(res2, desired_fun=1.730550597)
|
2262
|
+
assert_equal(res2.nit, 0)
|
2263
|
+
_assert_success(res3)
|
2264
|
+
assert_(res3.nit < res.nit) # hot start reduces iterations
|
2265
|
+
|
2266
|
+
|
2267
|
+
class TestLinprogRSBland(LinprogRSTests):
|
2268
|
+
options = {"pivot": "bland"}
|
2269
|
+
|
2270
|
+
|
2271
|
+
############################################
|
2272
|
+
# HiGHS-Simplex-Dual Option-Specific Tests #
|
2273
|
+
############################################
|
2274
|
+
|
2275
|
+
|
2276
|
+
class TestLinprogHiGHSSimplexDual(LinprogHiGHSTests):
|
2277
|
+
method = "highs-ds"
|
2278
|
+
options = {}
|
2279
|
+
|
2280
|
+
def test_lad_regression(self):
|
2281
|
+
'''
|
2282
|
+
The scaled model should be optimal, i.e. not produce unscaled model
|
2283
|
+
infeasible. See https://github.com/ERGO-Code/HiGHS/issues/494.
|
2284
|
+
'''
|
2285
|
+
# Test to ensure gh-13610 is resolved (mismatch between HiGHS scaled
|
2286
|
+
# and unscaled model statuses)
|
2287
|
+
c, A_ub, b_ub, bnds = l1_regression_prob()
|
2288
|
+
res = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bnds,
|
2289
|
+
method=self.method, options=self.options)
|
2290
|
+
assert_equal(res.status, 0)
|
2291
|
+
assert_(res.x is not None)
|
2292
|
+
assert_(np.all(res.slack > -1e-6))
|
2293
|
+
assert_(np.all(res.x <= [np.inf if ub is None else ub
|
2294
|
+
for lb, ub in bnds]))
|
2295
|
+
assert_(np.all(res.x >= [-np.inf if lb is None else lb - 1e-7
|
2296
|
+
for lb, ub in bnds]))
|
2297
|
+
|
2298
|
+
|
2299
|
+
###################################
|
2300
|
+
# HiGHS-IPM Option-Specific Tests #
|
2301
|
+
###################################
|
2302
|
+
|
2303
|
+
|
2304
|
+
class TestLinprogHiGHSIPM(LinprogHiGHSTests):
|
2305
|
+
method = "highs-ipm"
|
2306
|
+
options = {}
|
2307
|
+
|
2308
|
+
|
2309
|
+
###################################
|
2310
|
+
# HiGHS-MIP Option-Specific Tests #
|
2311
|
+
###################################
|
2312
|
+
|
2313
|
+
|
2314
|
+
class TestLinprogHiGHSMIP:
|
2315
|
+
method = "highs"
|
2316
|
+
options = {}
|
2317
|
+
|
2318
|
+
@pytest.mark.fail_slow(10)
|
2319
|
+
@pytest.mark.xfail(condition=(sys.maxsize < 2 ** 32 and
|
2320
|
+
platform.system() == "Linux"),
|
2321
|
+
run=False,
|
2322
|
+
reason="gh-16347")
|
2323
|
+
def test_mip1(self):
|
2324
|
+
# solve non-relaxed magic square problem (finally!)
|
2325
|
+
# also check that values are all integers - they don't always
|
2326
|
+
# come out of HiGHS that way
|
2327
|
+
n = 4
|
2328
|
+
A, b, c, numbers, M = magic_square(n)
|
2329
|
+
bounds = [(0, 1)] * len(c)
|
2330
|
+
integrality = [1] * len(c)
|
2331
|
+
|
2332
|
+
res = linprog(c=c*0, A_eq=A, b_eq=b, bounds=bounds,
|
2333
|
+
method=self.method, integrality=integrality)
|
2334
|
+
|
2335
|
+
s = (numbers.flatten() * res.x).reshape(n**2, n, n)
|
2336
|
+
square = np.sum(s, axis=0)
|
2337
|
+
np.testing.assert_allclose(square.sum(axis=0), M)
|
2338
|
+
np.testing.assert_allclose(square.sum(axis=1), M)
|
2339
|
+
np.testing.assert_allclose(np.diag(square).sum(), M)
|
2340
|
+
np.testing.assert_allclose(np.diag(square[:, ::-1]).sum(), M)
|
2341
|
+
|
2342
|
+
np.testing.assert_allclose(res.x, np.round(res.x), atol=1e-12)
|
2343
|
+
|
2344
|
+
def test_mip2(self):
|
2345
|
+
# solve MIP with inequality constraints and all integer constraints
|
2346
|
+
# source: slide 5,
|
2347
|
+
# https://www.cs.upc.edu/~erodri/webpage/cps/theory/lp/milp/slides.pdf
|
2348
|
+
|
2349
|
+
# use all array inputs to test gh-16681 (integrality couldn't be array)
|
2350
|
+
A_ub = np.array([[2, -2], [-8, 10]])
|
2351
|
+
b_ub = np.array([-1, 13])
|
2352
|
+
c = -np.array([1, 1])
|
2353
|
+
|
2354
|
+
bounds = np.array([(0, np.inf)] * len(c))
|
2355
|
+
integrality = np.ones_like(c)
|
2356
|
+
|
2357
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds,
|
2358
|
+
method=self.method, integrality=integrality)
|
2359
|
+
|
2360
|
+
np.testing.assert_allclose(res.x, [1, 2])
|
2361
|
+
np.testing.assert_allclose(res.fun, -3)
|
2362
|
+
|
2363
|
+
def test_mip3(self):
|
2364
|
+
# solve MIP with inequality constraints and all integer constraints
|
2365
|
+
# source: https://en.wikipedia.org/wiki/Integer_programming#Example
|
2366
|
+
A_ub = np.array([[-1, 1], [3, 2], [2, 3]])
|
2367
|
+
b_ub = np.array([1, 12, 12])
|
2368
|
+
c = -np.array([0, 1])
|
2369
|
+
|
2370
|
+
bounds = [(0, np.inf)] * len(c)
|
2371
|
+
integrality = [1] * len(c)
|
2372
|
+
|
2373
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds,
|
2374
|
+
method=self.method, integrality=integrality)
|
2375
|
+
|
2376
|
+
np.testing.assert_allclose(res.fun, -2)
|
2377
|
+
# two optimal solutions possible, just need one of them
|
2378
|
+
assert np.allclose(res.x, [1, 2]) or np.allclose(res.x, [2, 2])
|
2379
|
+
|
2380
|
+
def test_mip4(self):
|
2381
|
+
# solve MIP with inequality constraints and only one integer constraint
|
2382
|
+
# source: https://www.mathworks.com/help/optim/ug/intlinprog.html
|
2383
|
+
A_ub = np.array([[-1, -2], [-4, -1], [2, 1]])
|
2384
|
+
b_ub = np.array([14, -33, 20])
|
2385
|
+
c = np.array([8, 1])
|
2386
|
+
|
2387
|
+
bounds = [(0, np.inf)] * len(c)
|
2388
|
+
integrality = [0, 1]
|
2389
|
+
|
2390
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, bounds=bounds,
|
2391
|
+
method=self.method, integrality=integrality)
|
2392
|
+
|
2393
|
+
np.testing.assert_allclose(res.x, [6.5, 7])
|
2394
|
+
np.testing.assert_allclose(res.fun, 59)
|
2395
|
+
|
2396
|
+
def test_mip5(self):
|
2397
|
+
# solve MIP with inequality and inequality constraints
|
2398
|
+
# source: https://www.mathworks.com/help/optim/ug/intlinprog.html
|
2399
|
+
A_ub = np.array([[1, 1, 1]])
|
2400
|
+
b_ub = np.array([7])
|
2401
|
+
A_eq = np.array([[4, 2, 1]])
|
2402
|
+
b_eq = np.array([12])
|
2403
|
+
c = np.array([-3, -2, -1])
|
2404
|
+
|
2405
|
+
bounds = [(0, np.inf), (0, np.inf), (0, 1)]
|
2406
|
+
integrality = [0, 1, 0]
|
2407
|
+
|
2408
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
2409
|
+
bounds=bounds, method=self.method,
|
2410
|
+
integrality=integrality)
|
2411
|
+
|
2412
|
+
np.testing.assert_allclose(res.x, [0, 6, 0])
|
2413
|
+
np.testing.assert_allclose(res.fun, -12)
|
2414
|
+
|
2415
|
+
# gh-16897: these fields were not present, ensure that they are now
|
2416
|
+
assert res.get("mip_node_count", None) is not None
|
2417
|
+
assert res.get("mip_dual_bound", None) is not None
|
2418
|
+
assert res.get("mip_gap", None) is not None
|
2419
|
+
|
2420
|
+
@pytest.mark.xslow
|
2421
|
+
def test_mip6(self):
|
2422
|
+
# solve a larger MIP with only equality constraints
|
2423
|
+
# source: https://www.mathworks.com/help/optim/ug/intlinprog.html
|
2424
|
+
A_eq = np.array([[22, 13, 26, 33, 21, 3, 14, 26],
|
2425
|
+
[39, 16, 22, 28, 26, 30, 23, 24],
|
2426
|
+
[18, 14, 29, 27, 30, 38, 26, 26],
|
2427
|
+
[41, 26, 28, 36, 18, 38, 16, 26]])
|
2428
|
+
b_eq = np.array([7872, 10466, 11322, 12058])
|
2429
|
+
c = np.array([2, 10, 13, 17, 7, 5, 7, 3])
|
2430
|
+
|
2431
|
+
bounds = [(0, np.inf)]*8
|
2432
|
+
integrality = [1]*8
|
2433
|
+
|
2434
|
+
res = linprog(c=c, A_eq=A_eq, b_eq=b_eq, bounds=bounds,
|
2435
|
+
method=self.method, integrality=integrality)
|
2436
|
+
|
2437
|
+
np.testing.assert_allclose(res.fun, 1854)
|
2438
|
+
|
2439
|
+
@pytest.mark.xslow
|
2440
|
+
def test_mip_rel_gap_passdown(self):
|
2441
|
+
# MIP taken from test_mip6, solved with different values of mip_rel_gap
|
2442
|
+
# solve a larger MIP with only equality constraints
|
2443
|
+
# source: https://www.mathworks.com/help/optim/ug/intlinprog.html
|
2444
|
+
A_eq = np.array([[22, 13, 26, 33, 21, 3, 14, 26],
|
2445
|
+
[39, 16, 22, 28, 26, 30, 23, 24],
|
2446
|
+
[18, 14, 29, 27, 30, 38, 26, 26],
|
2447
|
+
[41, 26, 28, 36, 18, 38, 16, 26]])
|
2448
|
+
b_eq = np.array([7872, 10466, 11322, 12058])
|
2449
|
+
c = np.array([2, 10, 13, 17, 7, 5, 7, 3])
|
2450
|
+
|
2451
|
+
bounds = [(0, np.inf)]*8
|
2452
|
+
integrality = [1]*8
|
2453
|
+
|
2454
|
+
mip_rel_gaps = [0.5, 0.25, 0.01, 0.001]
|
2455
|
+
sol_mip_gaps = []
|
2456
|
+
for mip_rel_gap in mip_rel_gaps:
|
2457
|
+
res = linprog(c=c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq,
|
2458
|
+
bounds=bounds, method=self.method,
|
2459
|
+
integrality=integrality,
|
2460
|
+
options={"mip_rel_gap": mip_rel_gap})
|
2461
|
+
final_mip_gap = res["mip_gap"]
|
2462
|
+
# assert that the solution actually has mip_gap lower than the
|
2463
|
+
# required mip_rel_gap supplied
|
2464
|
+
assert final_mip_gap <= mip_rel_gap
|
2465
|
+
sol_mip_gaps.append(final_mip_gap)
|
2466
|
+
|
2467
|
+
# make sure that the mip_rel_gap parameter is actually doing something
|
2468
|
+
# check that differences between solution gaps are declining
|
2469
|
+
# monotonically with the mip_rel_gap parameter. np.diff does
|
2470
|
+
# x[i+1] - x[i], so flip the array before differencing to get
|
2471
|
+
# what should be a positive, monotone decreasing series of solution
|
2472
|
+
# gaps
|
2473
|
+
gap_diffs = np.diff(np.flip(sol_mip_gaps))
|
2474
|
+
assert np.all(gap_diffs >= 0)
|
2475
|
+
assert not np.all(gap_diffs == 0)
|
2476
|
+
|
2477
|
+
def test_semi_continuous(self):
|
2478
|
+
# See issue #18106. This tests whether the solution is being
|
2479
|
+
# checked correctly (status is 0) when integrality > 1:
|
2480
|
+
# values are allowed to be 0 even if 0 is out of bounds.
|
2481
|
+
|
2482
|
+
c = np.array([1., 1., -1, -1])
|
2483
|
+
bounds = np.array([[0.5, 1.5], [0.5, 1.5], [0.5, 1.5], [0.5, 1.5]])
|
2484
|
+
integrality = np.array([2, 3, 2, 3])
|
2485
|
+
|
2486
|
+
res = linprog(c, bounds=bounds,
|
2487
|
+
integrality=integrality, method='highs')
|
2488
|
+
|
2489
|
+
np.testing.assert_allclose(res.x, [0, 0, 1.5, 1])
|
2490
|
+
assert res.status == 0
|
2491
|
+
|
2492
|
+
def test_bug_20584(self):
|
2493
|
+
"""
|
2494
|
+
Test that when integrality is a list of all zeros, linprog gives the
|
2495
|
+
same result as when it is an array of all zeros / integrality=None
|
2496
|
+
"""
|
2497
|
+
c = [1, 1]
|
2498
|
+
A_ub = [[-1, 0]]
|
2499
|
+
b_ub = [-2.5]
|
2500
|
+
res1 = linprog(c, A_ub=A_ub, b_ub=b_ub, integrality=[0, 0])
|
2501
|
+
res2 = linprog(c, A_ub=A_ub, b_ub=b_ub, integrality=np.asarray([0, 0]))
|
2502
|
+
res3 = linprog(c, A_ub=A_ub, b_ub=b_ub, integrality=None)
|
2503
|
+
assert_equal(res1.x, res2.x)
|
2504
|
+
assert_equal(res1.x, res3.x)
|
2505
|
+
|
2506
|
+
|
2507
|
+
###########################
|
2508
|
+
# Autoscale-Specific Tests#
|
2509
|
+
###########################
|
2510
|
+
|
2511
|
+
|
2512
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
2513
|
+
class AutoscaleTests:
|
2514
|
+
options = {"autoscale": True}
|
2515
|
+
|
2516
|
+
test_bug_6139 = LinprogCommonTests.test_bug_6139
|
2517
|
+
test_bug_6690 = LinprogCommonTests.test_bug_6690
|
2518
|
+
test_bug_7237 = LinprogCommonTests.test_bug_7237
|
2519
|
+
|
2520
|
+
|
2521
|
+
class TestAutoscaleIP(AutoscaleTests):
|
2522
|
+
method = "interior-point"
|
2523
|
+
|
2524
|
+
def test_bug_6139(self):
|
2525
|
+
self.options['tol'] = 1e-10
|
2526
|
+
return AutoscaleTests.test_bug_6139(self)
|
2527
|
+
|
2528
|
+
|
2529
|
+
class TestAutoscaleSimplex(AutoscaleTests):
|
2530
|
+
method = "simplex"
|
2531
|
+
|
2532
|
+
|
2533
|
+
class TestAutoscaleRS(AutoscaleTests):
|
2534
|
+
method = "revised simplex"
|
2535
|
+
|
2536
|
+
def test_nontrivial_problem_with_guess(self):
|
2537
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2538
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2539
|
+
method=self.method, options=self.options, x0=x_star)
|
2540
|
+
_assert_success(res, desired_fun=f_star, desired_x=x_star)
|
2541
|
+
assert_equal(res.nit, 0)
|
2542
|
+
|
2543
|
+
def test_nontrivial_problem_with_bad_guess(self):
|
2544
|
+
c, A_ub, b_ub, A_eq, b_eq, x_star, f_star = nontrivial_problem()
|
2545
|
+
bad_guess = [1, 2, 3, .5]
|
2546
|
+
res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds,
|
2547
|
+
method=self.method, options=self.options, x0=bad_guess)
|
2548
|
+
assert_equal(res.status, 6)
|
2549
|
+
|
2550
|
+
|
2551
|
+
###########################
|
2552
|
+
# Redundancy Removal Tests#
|
2553
|
+
###########################
|
2554
|
+
|
2555
|
+
|
2556
|
+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
2557
|
+
class RRTests:
|
2558
|
+
method = "interior-point"
|
2559
|
+
LCT = LinprogCommonTests
|
2560
|
+
# these are a few of the existing tests that have redundancy
|
2561
|
+
test_RR_infeasibility = LCT.test_remove_redundancy_infeasibility
|
2562
|
+
test_bug_10349 = LCT.test_bug_10349
|
2563
|
+
test_bug_7044 = LCT.test_bug_7044
|
2564
|
+
test_NFLC = LCT.test_network_flow_limited_capacity
|
2565
|
+
test_enzo_example_b = LCT.test_enzo_example_b
|
2566
|
+
|
2567
|
+
|
2568
|
+
class TestRRSVD(RRTests):
|
2569
|
+
options = {"rr_method": "SVD"}
|
2570
|
+
|
2571
|
+
|
2572
|
+
class TestRRPivot(RRTests):
|
2573
|
+
options = {"rr_method": "pivot"}
|
2574
|
+
|
2575
|
+
|
2576
|
+
class TestRRID(RRTests):
|
2577
|
+
options = {"rr_method": "ID"}
|