Skip to content

Commit 1e90ab6

Browse files
BUG: numpy 1.16 doesn't support @np.vectorize decorator syntax (#1164)
* Revert "Increase minimum numpy version to 1.19.0 (#1162)" This reverts commit 149b057. * Refactor matrix multiplication to use vectorized core_dot_2d Replaces usage of _core_dot_2d with a new vectorized _core_dot_nd for mixed-type matrix multiplication in _core_dot. Defines _core_dot_nd as a vectorized wrapper around _core_dot_2d, improving code clarity and consistency. * Change _core_dot_2d from cdef to def and add return type Refactored _core_dot_2d to be a Python-accessible function with an explicit return type annotation. This improves clarity and allows the function to be used from Python code. * Remove unused NDArray import and update type hints NumPy 1.x doesn't support this * Move _vec_evaluate definition above _ensure_array Relocated the _vec_evaluate assignment to precede the _ensure_array function for improved code organization and clarity. * Use bint for boolean variables in matrix.pxi NumPy 1.x doesn't support bool --------- Co-authored-by: João Dionísio <57299939+Joao-Dionisio@users.noreply.github.com>
1 parent a82bf15 commit 1e90ab6

File tree

4 files changed

+14
-12
lines changed

4 files changed

+14
-12
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
- changed default value of enablepricing flag to True
2020
- Speed up MatrixExpr.add.reduce via quicksum
2121
- Speed up np.ndarray(..., dtype=np.float64) @ MatrixExpr
22-
- Minimum numpy version increased from 1.16.0 to 1.19.0
2322
- MatrixExpr and MatrixExprCons use `__array_ufunc__` protocol to control all numpy.ufunc inputs and outputs
2423
### Removed
2524

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description = "Python interface and modeling environment for SCIP"
88
authors = [
99
{name = "Zuse Institute Berlin", email = "scip@zib.de"},
1010
]
11-
dependencies = ['numpy >=1.19.0']
11+
dependencies = ['numpy >=1.16.0']
1212
requires-python = ">=3.8"
1313
readme = "README.md"
1414
license = {text = "MIT License"}

src/pyscipopt/matrix.pxi

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import operator
22
from typing import Literal, Optional, Tuple, Union
33
import numpy as np
4-
from numpy.typing import NDArray
54
try:
65
# NumPy 2.x location
76
from numpy.lib.array_utils import normalize_axis_tuple
@@ -73,7 +72,6 @@ class MatrixExpr(np.ndarray):
7372
res = super().__array_ufunc__(ufunc, method, *args, **kwargs)
7473
return res.view(MatrixExpr) if isinstance(res, np.ndarray) else res
7574

76-
7775
def _evaluate(self, Solution sol) -> NDArray[np.float64]:
7876
return _vec_evaluate(self, sol).view(np.ndarray)
7977

@@ -100,7 +98,7 @@ _vec_eq = np.frompyfunc(operator.eq, 2, 1)
10098
_vec_evaluate = np.frompyfunc(lambda expr, sol: expr._evaluate(sol), 2, 1)
10199

102100

103-
cdef inline _ensure_array(arg, bool convert_scalar = True):
101+
cdef inline _ensure_array(arg, bint convert_scalar = True):
104102
if isinstance(arg, np.ndarray):
105103
return arg.view(np.ndarray)
106104
elif isinstance(arg, (list, tuple)):
@@ -127,14 +125,14 @@ def _core_dot(cnp.ndarray a, cnp.ndarray b) -> Union[Expr, np.ndarray]:
127125
If both `a` and `b` are 1-D arrays, return an `Expr`, otherwise return a
128126
`np.ndarray` of type `object` and containing `Expr` objects.
129127
"""
130-
cdef bool a_is_1d = a.ndim == 1
131-
cdef bool b_is_1d = b.ndim == 1
128+
cdef bint a_is_1d = a.ndim == 1
129+
cdef bint b_is_1d = b.ndim == 1
132130
cdef cnp.ndarray a_nd = a[..., np.newaxis, :] if a_is_1d else a
133131
cdef cnp.ndarray b_nd = b[..., :, np.newaxis] if b_is_1d else b
134-
cdef bool a_is_num = a_nd.dtype.kind in "fiub"
132+
cdef bint a_is_num = a_nd.dtype.kind in "fiub"
135133

136134
if a_is_num ^ (b_nd.dtype.kind in "fiub"):
137-
res = _core_dot_2d(a_nd, b_nd) if a_is_num else _core_dot_2d(b_nd.T, a_nd.T).T
135+
res = _core_dot_nd(a_nd, b_nd) if a_is_num else _core_dot_nd(b_nd.T, a_nd.T).T
138136
if a_is_1d and b_is_1d:
139137
return res.item()
140138
if a_is_1d:
@@ -145,7 +143,6 @@ def _core_dot(cnp.ndarray a, cnp.ndarray b) -> Union[Expr, np.ndarray]:
145143
return NotImplemented
146144

147145

148-
@np.vectorize(otypes=[object], signature="(m,n),(n,p)->(m,p)")
149146
def _core_dot_2d(cnp.ndarray a, cnp.ndarray x) -> np.ndarray:
150147
"""
151148
Perform matrix multiplication between a 2-Demension constant array and a 2-Demension
@@ -183,6 +180,13 @@ def _core_dot_2d(cnp.ndarray a, cnp.ndarray x) -> np.ndarray:
183180
return res
184181

185182

183+
_core_dot_nd = np.vectorize(
184+
_core_dot_2d,
185+
otypes=[object],
186+
signature="(m,n),(n,p)->(m,p)",
187+
)
188+
189+
186190
def _core_sum(
187191
cnp.ndarray a,
188192
axis: Optional[Union[int, Tuple[int, ...]]] = None,

src/pyscipopt/scip.pxi

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ from dataclasses import dataclass
2121
from typing import Union
2222

2323
import numpy as np
24-
from numpy.typing import NDArray
2524

2625
include "expr.pxi"
2726
include "lp.pxi"
@@ -10735,7 +10734,7 @@ cdef class Model:
1073510734
self,
1073610735
Solution sol,
1073710736
expr: Union[Expr, GenExpr],
10738-
) -> Union[float, NDArray[np.float64]]:
10737+
) -> Union[float, np.ndarray]:
1073910738
"""
1074010739
Retrieve value of given variable or expression in the given solution or in
1074110740
the LP/pseudo solution if sol == None

0 commit comments

Comments
 (0)