Skip to content

Commit

Permalink
Merge pull request #19279 from tylerjereddy/treddy_1_11_3_prep
Browse files Browse the repository at this point in the history
MAINT: SciPy 1.11.3 backports/prep
  • Loading branch information
tylerjereddy committed Sep 27, 2023
2 parents b56f4c9 + 8208cf6 commit 329b980
Show file tree
Hide file tree
Showing 38 changed files with 686 additions and 135 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/linux_meson.yml
Expand Up @@ -230,9 +230,9 @@ jobs:
run: |
pip install "numpy==1.21.6" &&
# build deps
pip install build meson-python ninja pythran "pybind11<2.11.0" "cython<3.0.0" "wheel<0.41.0"
pip install build "meson-python<0.14.0" ninja "pythran<0.14.0" "pybind11<2.11.0" "cython<3.0.0" "wheel<0.41.0"
# test deps
pip install gmpy2 threadpoolctl mpmath pooch pythran "pybind11<2.11.0" pytest pytest-xdist==2.5.0 pytest-timeout
pip install gmpy2 threadpoolctl mpmath pooch "pythran<0.14.0" "pybind11<2.11.0" pytest pytest-xdist==2.5.0 pytest-timeout
- name: Build wheel and install
run: |
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/wheels.yml
Expand Up @@ -131,14 +131,15 @@ jobs:
CIBW_PRERELEASE_PYTHONS: True

# required so that cp312 can grab a nightly wheel
# can remove when cp312 is release and we don't need to search
# can remove when cp312 is released and we don't need to search
# other wheel locations.
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple PIP_PRE=1
# PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
CIBW_ENVIRONMENT: PIP_PRE=1

CIBW_ENVIRONMENT_WINDOWS: >
PKG_CONFIG_PATH=c:/opt/64/lib/pkgconfig
PIP_PRE=1
PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
# PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
# setting SDKROOT necessary when using the gfortran compiler
# installed in cibw_before_build_macos.sh
Expand All @@ -153,7 +154,7 @@ jobs:
MACOS_DEPLOYMENT_TARGET=10.9
_PYTHON_HOST_PLATFORM=macosx-10.9-x86_64
PIP_PRE=1
PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
# PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
CIBW_REPAIR_WHEEL_COMMAND_MACOS: >
DYLD_LIBRARY_PATH=/usr/local/lib delocate-listdeps {wheel} &&
Expand Down
1 change: 1 addition & 0 deletions .mailmap
Expand Up @@ -167,6 +167,7 @@ Ed Schofield <edschofield@localhost> edschofield <edschofield@localhost>
Egor Zemlyanoy <egorz734@mail.ru> egorz734 <egorz734@mail.ru>
Egor Zemlyanoy <egorz734@mail.ru> Egorz734 <egorz734@mail.ru>
Egor Zemlyanoy <egorz734@mail.ru> Egor <egorz734@mail.ru>
Ellie Litwack <ellie@PF2WXP6T.ad.bac.work> ellieLitwack <ellie@PF2WXP6T.ad.bac.work>
Eric Larson <larson.eric.d@gmail.com> Eric89GXL <larson.eric.d@gmail.com>
Eric Quintero <eric.antonio.quintero@gmail.com> e-q <eric.antonio.quintero@gmail.com>
Eric Quintero <eric.antonio.quintero@gmail.com> Eric Quintero <e-q@users.noreply.github.com>
Expand Down
18 changes: 17 additions & 1 deletion benchmarks/benchmarks/signal_filtering.py
Expand Up @@ -6,7 +6,7 @@

with safe_import():
from scipy.signal import (lfilter, firwin, decimate, butter, sosfilt,
medfilt2d)
medfilt2d, freqz)


class Decimate(Benchmark):
Expand Down Expand Up @@ -102,3 +102,19 @@ def time_medfilt2d(self, threads):

def peakmem_medfilt2d(self, threads):
self._medfilt2d(threads)


class FreqzRfft(Benchmark):
param_names = ['whole', 'nyquist', 'worN']
params = [
[False, True],
[False, True],
[64, 65, 128, 129, 256, 257, 258, 512, 513, 65536, 65537, 65538],
]

def setup(self, whole, nyquist, worN):
self.y = np.zeros(worN)
self.y[worN//2] = 1.0

def time_freqz(self, whole, nyquist, worN):
freqz(self.y, whole=whole, include_nyquist=nyquist, worN=worN)
4 changes: 2 additions & 2 deletions ci/cirrus_wheels.yml
Expand Up @@ -30,8 +30,8 @@ cirrus_wheels_linux_aarch64_task:
env:
CIBW_PRERELEASE_PYTHONS: True
CIBW_ENVIRONMENT: >
PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
PIP_PRE=1
# PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple

build_script: |
apt install -y python3-venv python-is-python3
Expand Down Expand Up @@ -59,8 +59,8 @@ cirrus_wheels_macos_arm64_task:
CIBW_ENVIRONMENT: >
MACOSX_DEPLOYMENT_TARGET=12.0
_PYTHON_HOST_PLATFORM="macosx-12.0-arm64"
PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
PIP_PRE=1
# PIP_EXTRA_INDEX_URL=https://pypi.anaconda.org/scientific-python-nightly-wheels/simple
PKG_CONFIG_PATH: /opt/arm64-builds/lib/pkgconfig
# assumes that the cmake config is in /usr/local/lib/cmake
CMAKE_PREFIX_PATH: /opt/arm64-builds/
Expand Down
31 changes: 16 additions & 15 deletions dev.py
Expand Up @@ -111,14 +111,6 @@ def task_meta(cls, **kwargs):
import traceback
from concurrent.futures.process import _MAX_WINDOWS_WORKERS

# distutils is required to infer meson install path
# if this needs to be replaced for Python 3.12 support and there's no
# stdlib alternative, use CmdAction and the hack discussed in gh-16058
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
from distutils import dist
from distutils.command.install import INSTALL_SCHEMES

from pathlib import Path
from collections import namedtuple
from types import ModuleType as new_module
Expand Down Expand Up @@ -337,14 +329,23 @@ def get_site_packages(self):
Depending on whether we have debian python or not,
return dist_packages path or site_packages path.
"""
if 'deb_system' in INSTALL_SCHEMES:
# debian patched python in use
install_cmd = dist.Distribution().get_command_obj('install')
install_cmd.select_scheme('deb_system')
install_cmd.finalize_options()
plat_path = Path(install_cmd.install_platlib)
else:
if sys.version_info >= (3, 12):
plat_path = Path(get_path('platlib'))
else:
# distutils is required to infer meson install path
# for python < 3.12 in debian patched python
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
from distutils import dist
from distutils.command.install import INSTALL_SCHEMES
if 'deb_system' in INSTALL_SCHEMES:
# debian patched python in use
install_cmd = dist.Distribution().get_command_obj('install')
install_cmd.select_scheme('deb_system')
install_cmd.finalize_options()
plat_path = Path(install_cmd.install_platlib)
else:
plat_path = Path(get_path('platlib'))
return self.installed / plat_path.relative_to(sys.exec_prefix)


Expand Down
52 changes: 52 additions & 0 deletions doc/source/release/1.11.3-notes.rst
Expand Up @@ -12,13 +12,65 @@ compared to 1.11.2.
Authors
=======
* Name (commits)
* Jake Bowhay (2)
* CJ Carey (1)
* Colin Carroll (1) +
* Anirudh Dagar (2)
* drestebon (1) +
* Ralf Gommers (5)
* Matt Haberland (2)
* Julien Jerphanion (1)
* Uwe L. Korn (1) +
* Ellie Litwack (2)
* Andrew Nelson (5)
* Bharat Raghunathan (1)
* Tyler Reddy (37)
* Søren Fuglede Jørgensen (2)
* Hielke Walinga (1) +
* Warren Weckesser (1)
* Bernhard M. Wiedemann (1)

A total of 17 people contributed to this release.
People with a "+" by their names contributed a patch for the first time.
This list of names is automatically generated, and may not be fully complete.


Issues closed for 1.11.3
------------------------

* `#15093 <https://github.com/scipy/scipy/issues/15093>`__: BUG: scipy.optimize's trust-constr algorithm hangs when keep-feasible...
* `#15273 <https://github.com/scipy/scipy/issues/15273>`__: freqz: suboptimal performance for worN=2\*\*n+1, include_nyquist=True...
* `#17269 <https://github.com/scipy/scipy/issues/17269>`__: Bug in scipy.sparse.csgraph.min_weight_full_bipartite_matching
* `#17289 <https://github.com/scipy/scipy/issues/17289>`__: BUG: Different results between numpy.fft.rfft and scipy.signal.freqz
* `#18716 <https://github.com/scipy/scipy/issues/18716>`__: Buffer dtype mismatch, expected 'ITYPE_t' but got 'long'
* `#18782 <https://github.com/scipy/scipy/issues/18782>`__: BUG: johnsonsu distribution no longer accepts integer \`b\` parameter
* `#18922 <https://github.com/scipy/scipy/issues/18922>`__: BUG: dev.py has \`distutils\` usage
* `#19101 <https://github.com/scipy/scipy/issues/19101>`__: BUG: mesonpy embeds random path in .pyx files
* `#19103 <https://github.com/scipy/scipy/issues/19103>`__: BUG: Regression in 1.11.2: optimize.least_squares with method='trf'...
* `#19132 <https://github.com/scipy/scipy/issues/19132>`__: BUG: Build fails on latest commit
* `#19149 <https://github.com/scipy/scipy/issues/19149>`__: BUG: scipy.sparse.csgraph.laplacian raises AttributeError on...
* `#19197 <https://github.com/scipy/scipy/issues/19197>`__: BUG: Incorrect sampling from zero rank covariance


Pull requests for 1.11.3
------------------------

* `#17633 <https://github.com/scipy/scipy/pull/17633>`__: BUG: add infeasibility checks to min_weight_full_bipartite_matching
* `#18784 <https://github.com/scipy/scipy/pull/18784>`__: BUG: Allow johnsonsu parameters to be floats
* `#18913 <https://github.com/scipy/scipy/pull/18913>`__: BUG: sparse.csgraph: Support int64 indices in traversal.pyx
* `#18924 <https://github.com/scipy/scipy/pull/18924>`__: BUG: Fix python3.12 distutils dev.py build
* `#18956 <https://github.com/scipy/scipy/pull/18956>`__: BUG: trust-constr Bounds exclusive
* `#19076 <https://github.com/scipy/scipy/pull/19076>`__: MAINT: should not be using np.float64() on arrays
* `#19084 <https://github.com/scipy/scipy/pull/19084>`__: REL, MAINT: prep for 1.11.3
* `#19111 <https://github.com/scipy/scipy/pull/19111>`__: BUG: Fixes #19103 by adding back make_strictly_feasible to lsq...
* `#19123 <https://github.com/scipy/scipy/pull/19123>`__: BLD: Avoid absolute pathnames in .pyx files
* `#19135 <https://github.com/scipy/scipy/pull/19135>`__: MAINT: signal: Remove the cval parameter from the private function...
* `#19139 <https://github.com/scipy/scipy/pull/19139>`__: BLD: revert to using published wheels [wheel build]
* `#19156 <https://github.com/scipy/scipy/pull/19156>`__: BUG: Support sparse arrays in scipy.sparse.csgraph.laplacian
* `#19199 <https://github.com/scipy/scipy/pull/19199>`__: MAINT: stats.CovViaEigendecomposition: fix \`_LA\` attribute...
* `#19200 <https://github.com/scipy/scipy/pull/19200>`__: TST: fix \`TestODR.test_implicit\` test failure with tolerance...
* `#19208 <https://github.com/scipy/scipy/pull/19208>`__: BUG: freqz rfft grid fix
* `#19280 <https://github.com/scipy/scipy/pull/19280>`__: MAINT: newton, make sure x0 is an inexact type
* `#19286 <https://github.com/scipy/scipy/pull/19286>`__: BUG: stats: fix build failure due to incorrect Boost policies...
* `#19290 <https://github.com/scipy/scipy/pull/19290>`__: BLD: add float.h include to \`_fpumode.c\`, fixes Clang on Windows...
* `#19299 <https://github.com/scipy/scipy/pull/19299>`__: MAINT: fix libquadmath licence
22 changes: 12 additions & 10 deletions pyproject.toml
Expand Up @@ -10,13 +10,15 @@
[build-system]
build-backend = 'mesonpy'
requires = [
"meson-python>=0.12.1,<0.14.0", # already working with 0.13.x series at branch time
"Cython>=0.29.35,<3.0", # when updating version, also update check in meson.build
"pybind11>=2.10.4,<2.11.0",
"pythran>=0.12.0,<0.14.0", # already working with 0.13.x series at branch time
# `wheel` is needed for non-isolated builds, given that `meson-python`
# doesn't list it as a runtime requirement (at least in 0.5.0)
"wheel<0.41.0",
# Reason for `<`: future-proofing (0.14.0 released and known to work)
"meson-python>=0.12.1,<0.15.0",
# Reason for `<`: we want to build the 1.11.x releases with Cython 0.29.x
# (too many changes in 3.0)
"Cython>=0.29.35,<3.0", # when updating version, also update check in meson.build
# Reason for `<`: future-proofing (2.11.1 is the most recent version)
"pybind11>=2.10.4,<2.11.1",
# Reason for `<`: future-proofing (0.14.0 released and known to work)
"pythran>=0.12.0,<0.15.0",

# NumPy dependencies - to update these, sync from
# https://github.com/scipy/oldest-supported-numpy/, and then
Expand All @@ -41,13 +43,14 @@ requires = [
# (see oldest-supported-numpy issues gh-28 and gh-45)
"numpy==1.21.6; python_version=='3.10' and (platform_system!='Windows' and platform_machine!='loongarch64') and platform_python_implementation != 'PyPy'",
"numpy==1.23.2; python_version=='3.11' and platform_python_implementation != 'PyPy'",
"numpy>=1.26.0,<1.27.0; python_version=='3.12'", # no `==` because we expect relevant bug fixes in 1.26.1/2

# For Python versions which aren't yet officially supported,
# we specify an unpinned NumPy which allows source distributions
# to be used and allows wheels to be used as soon as they
# become available.
"numpy; python_version>='3.9' and platform_python_implementation=='PyPy'",
"numpy==1.26.0b1; python_version>='3.12.0.rc1'",
"numpy>=1.26.0; python_version>='3.13'",
]

[project]
Expand All @@ -64,8 +67,6 @@ maintainers = [
# https://scipy.github.io/devdocs/dev/core-dev/index.html#version-ranges-for-numpy-and-other-dependencies
requires-python = ">=3.9,<3.13"
dependencies = [
# TODO: update to "pin-compatible" once possible, see
# https://github.com/FFY00/meson-python/issues/29
"numpy>=1.21.6,<1.28.0",
]
readme = "README.rst"
Expand All @@ -80,6 +81,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Libraries",
"Topic :: Scientific/Engineering",
"Operating System :: Microsoft :: Windows",
Expand Down
1 change: 1 addition & 0 deletions scipy/_lib/_fpumode.c
Expand Up @@ -4,6 +4,7 @@


#ifdef _MSC_VER
#include <float.h>
#pragma float_control(precise, on)
#pragma fenv_access (on)
#endif
Expand Down
4 changes: 2 additions & 2 deletions scipy/integrate/_quadrature.py
Expand Up @@ -502,8 +502,8 @@ def _basic_simpson(y, start, stop, x, dx, axis):
h = np.diff(x, axis=axis)
sl0 = tupleset(slice_all, axis, slice(start, stop, step))
sl1 = tupleset(slice_all, axis, slice(start+1, stop+1, step))
h0 = np.float64(h[sl0])
h1 = np.float64(h[sl1])
h0 = h[sl0].astype(float, copy=False)
h1 = h[sl1].astype(float, copy=False)
hsum = h0 + h1
hprod = h0 * h1
h0divh1 = np.true_divide(h0, h1, out=np.zeros_like(h0), where=h1 != 0)
Expand Down
6 changes: 4 additions & 2 deletions scipy/odr/tests/test_odr.py
Expand Up @@ -5,7 +5,8 @@
import numpy as np
from numpy import pi
from numpy.testing import (assert_array_almost_equal,
assert_equal, assert_warns)
assert_equal, assert_warns,
assert_allclose)
import pytest
from pytest import raises as assert_raises

Expand Down Expand Up @@ -127,7 +128,7 @@ def test_implicit(self):
np.array([0.1113840353364371, 0.1097673310686467, 0.0041060738314314,
0.0027500347539902, 0.0034962501532468]),
)
assert_array_almost_equal(
assert_allclose(
out.cov_beta,
np.array([[2.1089274602333052e+00, -1.9437686411979040e+00,
7.0263550868344446e-02, -4.7175267373474862e-02,
Expand All @@ -144,6 +145,7 @@ def test_implicit(self):
[5.2515575927380355e-02, -5.8822307501391467e-02,
1.4528860663055824e-03, -1.2692942951415293e-03,
2.0778813389755596e-03]]),
rtol=1e-6, atol=2e-6,
)

# Multi-variable Example
Expand Down
5 changes: 4 additions & 1 deletion scipy/optimize/_lsq/least_squares.py
Expand Up @@ -12,7 +12,7 @@

from .trf import trf
from .dogbox import dogbox
from .common import EPS, in_bounds
from .common import EPS, in_bounds, make_strictly_feasible


TERMINATION_MESSAGES = {
Expand Down Expand Up @@ -821,6 +821,9 @@ def least_squares(

ftol, xtol, gtol = check_tolerance(ftol, xtol, gtol, method)

if method == 'trf':
x0 = make_strictly_feasible(x0, lb, ub, rstep=0)

def fun_wrapped(x):
return np.atleast_1d(fun(x, *args, **kwargs))

Expand Down
Expand Up @@ -3,7 +3,7 @@
from scipy.sparse.linalg import LinearOperator
from .._differentiable_functions import VectorFunction
from .._constraints import (
NonlinearConstraint, LinearConstraint, PreparedConstraint, strict_bounds)
NonlinearConstraint, LinearConstraint, PreparedConstraint, Bounds, strict_bounds)
from .._hessian_update_strategy import BFGS
from .._optimize import OptimizeResult
from .._differentiable_functions import ScalarFunction
Expand Down Expand Up @@ -323,6 +323,11 @@ def _minimize_trustregion_constr(fun, x0, args, grad,
verbose = 1

if bounds is not None:
modified_lb = np.nextafter(bounds.lb, -np.inf, where=bounds.lb > -np.inf)
modified_ub = np.nextafter(bounds.ub, np.inf, where=bounds.ub < np.inf)
modified_lb = np.where(np.isfinite(bounds.lb), modified_lb, bounds.lb)
modified_ub = np.where(np.isfinite(bounds.ub), modified_ub, bounds.ub)
bounds = Bounds(modified_lb, modified_ub, keep_feasible=bounds.keep_feasible)
finite_diff_bounds = strict_bounds(bounds.lb, bounds.ub,
bounds.keep_feasible, n_vars)
else:
Expand Down
5 changes: 4 additions & 1 deletion scipy/optimize/_zeros_py.py
Expand Up @@ -290,7 +290,10 @@ class of similar problems can be solved together.
full_output)

# Convert to float (don't use float(x0); this works also for complex x0)
x0 = np.asarray(x0)[()]
# Use np.asarray because we want x0 to be a numpy object, not a Python
# object. e.g. np.complex(1+1j) > 0 is possible, but (1 + 1j) > 0 raises
# a TypeError
x0 = np.asarray(x0)[()] * 1.0
p0 = x0
funcalls = 0
if fprime is not None:
Expand Down
28 changes: 28 additions & 0 deletions scipy/optimize/tests/test_least_squares.py
Expand Up @@ -822,3 +822,31 @@ def chi2(x):
# if we choose an initial condition that is close to the solution
# we shouldn't return an answer that is further away from the solution
assert_allclose(res.x, answer, atol=initial_guess-answer)


def test_gh_19103():
# Checks that least_squares trf method selects a strictly feasible point,
# and thus succeeds instead of failing,
# when the initial guess is reported exactly at a boundary point.
# This is a reduced example from gh191303

ydata = np.array([0.] * 66 + [
1., 0., 0., 0., 0., 0., 1., 1., 0., 0., 1.,
1., 1., 1., 0., 0., 0., 1., 0., 0., 2., 1.,
0., 3., 1., 6., 5., 0., 0., 2., 8., 4., 4.,
6., 9., 7., 2., 7., 8., 2., 13., 9., 8., 11.,
10., 13., 14., 19., 11., 15., 18., 26., 19., 32., 29.,
28., 36., 32., 35., 36., 43., 52., 32., 58., 56., 52.,
67., 53., 72., 88., 77., 95., 94., 84., 86., 101., 107.,
108., 118., 96., 115., 138., 137.,
])
xdata = np.arange(0, ydata.size) * 0.1

def exponential_wrapped(params):
A, B, x0 = params
return A * np.exp(B * (xdata - x0)) - ydata

x0 = [0.01, 1., 5.]
bounds = ((0.01, 0, 0), (np.inf, 10, 20.9))
res = least_squares(exponential_wrapped, x0, method='trf', bounds=bounds)
assert res.success

0 comments on commit 329b980

Please sign in to comment.