Skip to content

Commit

Permalink
Merge pull request #13908 from tylerjereddy/treddy_backport_issue_13890
Browse files Browse the repository at this point in the history
MAINT: additional 1.6.3 backport
  • Loading branch information
tylerjereddy committed Apr 25, 2021
2 parents e633da1 + 6eab5bb commit 4ec4ab8
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 155 deletions.
155 changes: 14 additions & 141 deletions benchmarks/benchmarks/optimize_linprog.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,29 @@
with safe_import():
from scipy.optimize import linprog, OptimizeWarning

with safe_import() as exc:
with safe_import():
from scipy.optimize.tests.test_linprog import lpgen_2d, magic_square
from scipy.optimize._remove_redundancy import (
_remove_redundancy_svd,
_remove_redundancy_pivot_sparse,
_remove_redundancy_pivot_dense,
_remove_redundancy_id
)
from scipy.optimize._linprog_util import (
_presolve,
_clean_inputs,
_LPProblem
)
if exc.error:
_remove_redundancy_svd = None
_remove_redundancy_pivot_sparse = None
_remove_redundancy_pivot_dense = None
_remove_redundancy_id = None

with safe_import():
from scipy.linalg import toeplitz

with safe_import():
from scipy.sparse import csc_matrix, csr_matrix, issparse

methods = [("interior-point", {"sparse": True}),
("interior-point", {"sparse": False}),
("revised simplex", {}),
("highs-ipm", {}),
("highs-simplex", {})]
rr_methods = [_remove_redundancy_svd, _remove_redundancy_pivot_sparse,
_remove_redundancy_pivot_dense, _remove_redundancy_id]
presolve_methods = ['sparse', 'dense']
methods = [("highs-ipm", {})]

problems = ['25FV47', '80BAU3B', 'ADLITTLE', 'AFIRO', 'AGG', 'AGG2', 'AGG3',
'BANDM', 'BEACONFD', 'BLEND', 'BNL1', 'BNL2', 'BORE3D', 'BRANDY',
'CAPRI', 'CYCLE', 'CZPROB', 'D6CUBE', 'DEGEN2', 'DEGEN3', 'E226',
'ETAMACRO', 'FFFFF800', 'FINNIS', 'FIT1D', 'FIT1P', 'GANGES',
'GFRD-PNC', 'GROW15', 'GROW22', 'GROW7', 'ISRAEL', 'KB2', 'LOTFI',
'MAROS', 'MODSZK1', 'PEROLD', 'PILOT', 'PILOT-WE', 'PILOT4',
'PILOTNOV', 'QAP8', 'RECIPE', 'SC105', 'SC205', 'SC50A', 'SC50B',
'SCAGR25', 'SCAGR7', 'SCFXM1', 'SCFXM2', 'SCFXM3', 'SCORPION',
'SCRS8', 'SCSD1', 'SCSD6', 'SCSD8', 'SCTAP1', 'SCTAP2', 'SCTAP3',
'SHARE1B', 'SHARE2B', 'SHELL', 'SHIP04L', 'SHIP04S', 'SHIP08L',
'SHIP08S', 'SHIP12L', 'SHIP12S', 'SIERRA', 'STAIR', 'STANDATA',
'STANDMPS', 'STOCFOR1', 'STOCFOR2', 'TRUSS', 'TUFF', 'VTP-BASE',
'CAPRI', 'CYCLE', 'CZPROB', 'D2Q06C', 'D6CUBE', 'DEGEN2', 'DEGEN3',
'DFL001', 'E226', 'ETAMACRO', 'FFFFF800', 'FINNIS', 'FIT1D',
'FIT1P', 'FIT2D', 'FIT2P', 'GANGES', 'GFRD-PNC', 'GREENBEA',
'GREENBEB', 'GROW15', 'GROW22', 'GROW7', 'ISRAEL', 'KB2', 'LOTFI',
'MAROS', 'MAROS-R7', 'MODSZK1', 'PEROLD', 'PILOT', 'PILOT4',
'PILOT87', 'PILOT-JA', 'PILOTNOV', 'PILOT-WE', 'QAP8', 'QAP12',
'QAP15', 'RECIPE', 'SC105', 'SC205', 'SC50A', 'SC50B', 'SCAGR25',
'SCAGR7', 'SCFXM1', 'SCFXM2', 'SCFXM3', 'SCORPION', 'SCRS8',
'SCSD1', 'SCSD6', 'SCSD8', 'SCTAP1', 'SCTAP2', 'SCTAP3', 'SHARE1B',
'SHARE2B', 'SHELL', 'SHIP04L', 'SHIP04S', 'SHIP08L', 'SHIP08S',
'SHIP12L', 'SHIP12S', 'SIERRA', 'STAIR', 'STANDATA', 'STANDMPS',
'STOCFOR1', 'STOCFOR2', 'STOCFOR3', 'TRUSS', 'TUFF', 'VTP-BASE',
'WOOD1P', 'WOODW']
presolve_problems = problems
rr_problems = ['AFIRO', 'BLEND', 'FINNIS', 'RECIPE', 'SCSD6', 'VTP-BASE',
'BORE3D', 'CYCLE', 'DEGEN2', 'DEGEN3', 'ETAMACRO', 'PILOTNOV',
'QAP8', 'RECIPE', 'SCORPION', 'SHELL', 'SIERRA', 'WOOD1P']
infeasible_problems = ['bgdbg1', 'bgetam', 'bgindy', 'bgprtr', 'box1',
'ceria3d', 'chemcom', 'cplex1', 'cplex2', 'ex72a',
'ex73a', 'forest6', 'galenet', 'gosh', 'gran',
Expand All @@ -69,17 +41,12 @@
if not is_xslow():
enabled_problems = ['ADLITTLE', 'AFIRO', 'BLEND', 'BEACONFD', 'GROW7',
'LOTFI', 'SC105', 'SCTAP1', 'SHARE2B', 'STOCFOR1']
enabled_presolve_problems = enabled_problems
enabled_rr_problems = ['AFIRO', 'BLEND', 'FINNIS', 'RECIPE', 'SCSD6',
'VTP-BASE', 'DEGEN2', 'ETAMACRO', 'RECIPE']
enabled_infeasible_problems = ['bgdbg1', 'bgprtr', 'box1', 'chemcom',
'cplex2', 'ex72a', 'ex73a', 'forest6',
'galenet', 'itest2', 'itest6', 'klein1',
'refinery', 'woodinfe']
else:
enabled_problems = problems
enabled_presolve_problems = enabled_problems
enabled_rr_problems = rr_problems
enabled_infeasible_problems = infeasible_problems


Expand Down Expand Up @@ -220,100 +187,6 @@ def track_netlib(self, meth, prob):
return min(self.abs_error, self.rel_error)


class Netlib_RR(Benchmark):
params = [
rr_methods,
rr_problems
]
param_names = ['method', 'problems']
# sparse routine returns incorrect matrix on BORE3D and PILOTNOV
# SVD fails (doesn't converge) on QAP8
known_fails = {('_remove_redundancy_svd', 'QAP8'),
('_remove_redundancy_pivot_sparse', 'BORE3D'),
('_remove_redundancy_pivot_sparse', 'PILOTNOV')}

def setup(self, meth, prob):
if prob not in enabled_rr_problems:
raise NotImplementedError("skipped")

if (meth.__name__, prob) in self.known_fails:
raise NotImplementedError("Known issues with these benchmarks.")

dir_path = os.path.dirname(os.path.realpath(__file__))
datafile = os.path.join(dir_path, "linprog_benchmark_files",
prob + ".npz")
data = np.load(datafile, allow_pickle=True)

c, A_eq, A_ub, b_ub, b_eq = (data["c"], data["A_eq"], data["A_ub"],
data["b_ub"], data["b_eq"])
bounds = np.squeeze(data["bounds"])
x0 = np.zeros(c.shape)

lp = _LPProblem(c, A_ub, b_ub, A_eq, b_eq, bounds, x0)
lp_cleaned = _clean_inputs(lp)
# rr_method is None here because we're not using RR
res = _presolve(lp_cleaned, rr=False, rr_method=None, tol=1e-9)[0]

self.A_eq, self.b_eq = res.A_eq, res.b_eq
self.true_rank = np.linalg.matrix_rank(self.A_eq)
if meth == _remove_redundancy_pivot_sparse:
self.A_eq = csc_matrix(self.A_eq)
self.rr_A = None

def time_netlib_rr(self, meth, prob):
self.rr_A, b, status, message = meth(self.A_eq, self.b_eq)

def track_netlib_rr(self, meth, prob):
if self.rr_A is None:
self.time_netlib_rr(meth, prob)

if meth == _remove_redundancy_pivot_sparse:
self.rr_A = self.rr_A.todense()

rr_rank = np.linalg.matrix_rank(self.rr_A)
rr_rows = self.rr_A.shape[0]

self.error1 = rr_rank - self.true_rank
self.error2 = rr_rows - self.true_rank

if abs(self.error1) > abs(self.error2):
return float(self.error1)
else:
return float(self.error2)


class Netlib_presolve(Benchmark):
params = [
presolve_methods,
presolve_problems
]
param_names = ['method', 'problems']

def setup(self, meth, prob):
if prob not in enabled_presolve_problems:
raise NotImplementedError("skipped")

dir_path = os.path.dirname(os.path.realpath(__file__))
datafile = os.path.join(dir_path, "linprog_benchmark_files",
prob + ".npz")
data = np.load(datafile, allow_pickle=True)

c, A_eq, A_ub, b_ub, b_eq = (data["c"], data["A_eq"], data["A_ub"],
data["b_ub"], data["b_eq"])
bounds = np.squeeze(data["bounds"])
x0 = np.zeros(c.shape)

if meth == "sparse":
A_eq = csr_matrix(A_eq)
A_ub = csr_matrix(A_ub)

lp = _LPProblem(c, A_ub, b_ub, A_eq, b_eq, bounds, x0)
self.lp_cleaned = _clean_inputs(lp)

def time_netlib_presolve(self, meth, prob):
_presolve(self.lp_cleaned, rr=False, rr_method=None, tol=1e-9)


class Netlib_infeasible(Benchmark):
params = [
methods,
Expand Down
8 changes: 7 additions & 1 deletion doc/release/1.6.3-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ Authors
=======

* Peter Bell
* Ralf Gommers
* Matt Haberland
* Peter Mahler Larsen
* Tirth Patel
* Tyler Reddy
* Pamphile ROY +
* Xingyu Liu +

A total of 5 people contributed to this release.
A total of 8 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.

Expand All @@ -25,6 +28,8 @@ Issues closed for 1.6.3

* `#13772 <https://github.com/scipy/scipy/issues/13772>`__: Divide by zero in distance.yule
* `#13796 <https://github.com/scipy/scipy/issues/13796>`__: CI: prerelease_deps failures
* `#13890 <https://github.com/scipy/scipy/issues/13890>`__: TST: spatial rotation failure in (1.6.3) wheels repo (ARM64)


Pull requests for 1.6.3
-----------------------
Expand All @@ -33,3 +38,4 @@ Pull requests for 1.6.3
* `#13773 <https://github.com/scipy/scipy/pull/13773>`__: BUG: Divide by zero in yule dissimilarity of constant vectors
* `#13799 <https://github.com/scipy/scipy/pull/13799>`__: CI/MAINT: deprecated np.typeDict
* `#13819 <https://github.com/scipy/scipy/pull/13819>`__: substitute np.math.factorial with math.factorial
* `#13895 <https://github.com/scipy/scipy/pull/13895>`__: TST: add random seeds in Rotation module
27 changes: 14 additions & 13 deletions scipy/spatial/transform/tests/test_rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import numpy as np
from numpy.testing import assert_equal, assert_array_almost_equal
from numpy.testing import assert_allclose, assert_array_less
from numpy.testing import assert_allclose
from scipy.spatial.transform import Rotation, Slerp
from scipy.stats import special_ortho_group
from itertools import permutations
Expand Down Expand Up @@ -701,7 +701,7 @@ def test_inv_single_rotation():
assert_array_almost_equal(res1, eye)
assert_array_almost_equal(res2, eye)

x = Rotation.from_quat(np.random.normal(size=(1, 4)))
x = Rotation.from_quat(rnd.normal(size=(1, 4)))
y = x.inv()

x_matrix = x.as_matrix()
Expand Down Expand Up @@ -729,7 +729,7 @@ def test_single_identity_magnitude():

def test_identity_invariance():
n = 10
p = Rotation.random(n)
p = Rotation.random(n, random_state=0)

result = p * Rotation.identity(n)
assert_array_almost_equal(p.as_quat(), result.as_quat())
Expand All @@ -740,7 +740,7 @@ def test_identity_invariance():

def test_single_identity_invariance():
n = 10
p = Rotation.random(n)
p = Rotation.random(n, random_state=0)

result = p * Rotation.identity()
assert_array_almost_equal(p.as_quat(), result.as_quat())
Expand Down Expand Up @@ -984,7 +984,7 @@ def test_align_vectors_no_rotation():
def test_align_vectors_no_noise():
rnd = np.random.RandomState(0)
c = Rotation.from_quat(rnd.normal(size=4))
b = np.random.normal(size=(5, 3))
b = rnd.normal(size=(5, 3))
a = c.apply(b)

est, rmsd = Rotation.align_vectors(a, b)
Expand Down Expand Up @@ -1022,14 +1022,14 @@ def test_align_vectors_noise():
rnd = np.random.RandomState(0)
n_vectors = 100
rot = Rotation.from_euler('xyz', rnd.normal(size=3))
vectors = np.random.normal(size=(n_vectors, 3))
vectors = rnd.normal(size=(n_vectors, 3))
result = rot.apply(vectors)

# The paper adds noise as independently distributed angular errors
sigma = np.deg2rad(1)
tolerance = 1.5 * sigma
noise = Rotation.from_rotvec(
np.random.normal(
rnd.normal(
size=(n_vectors, 3),
scale=sigma
)
Expand Down Expand Up @@ -1084,11 +1084,12 @@ def test_align_vectors_invalid_input():


def test_random_rotation_shape():
assert_equal(Rotation.random().as_quat().shape, (4,))
assert_equal(Rotation.random(None).as_quat().shape, (4,))
rnd = np.random.RandomState(0)
assert_equal(Rotation.random(random_state=rnd).as_quat().shape, (4,))
assert_equal(Rotation.random(None, random_state=rnd).as_quat().shape, (4,))

assert_equal(Rotation.random(1).as_quat().shape, (1, 4))
assert_equal(Rotation.random(5).as_quat().shape, (5, 4))
assert_equal(Rotation.random(1, random_state=rnd).as_quat().shape, (1, 4))
assert_equal(Rotation.random(5, random_state=rnd).as_quat().shape, (5, 4))


def test_slerp():
Expand Down Expand Up @@ -1222,8 +1223,8 @@ def test_multiplication_stability():


def test_rotation_within_numpy_array():
single = Rotation.random()
multiple = Rotation.random(2)
single = Rotation.random(random_state=0)
multiple = Rotation.random(2, random_state=1)

array = np.array(single)
assert_equal(array.shape, ())
Expand Down

0 comments on commit 4ec4ab8

Please sign in to comment.