def test_bounds_repr(): from numpy import array, inf # so that eval works for args in ( (-1.0, 5.0), (-1.0, np.inf, True), (np.array([1.0, -np.inf]), np.array([2.0, np.inf])), (np.array([1.0, -np.inf]), np.array([2.0, np.inf]), np.array([True, False])), ): bounds = Bounds(*args) bounds2 = eval(repr(Bounds(*args))) assert_array_equal(bounds.lb, bounds2.lb) assert_array_equal(bounds.ub, bounds2.ub) assert_array_equal(bounds.keep_feasible, bounds2.keep_feasible)
def test_constraint_wrapper(self): lb = np.array([0, 20, 30]) ub = np.array([0.5, np.inf, 70]) x0 = np.array([1, 2, 3]) pc = _ConstraintWrapper(Bounds(lb, ub), x0) assert (pc.violation(x0) > 0).any() assert (pc.violation([0.25, 21, 31]) == 0).all() x0 = np.array([1, 2, 3, 4]) A = np.array([[1, 2, 3, 4], [5, 0, 0, 6], [7, 0, 8, 0]]) pc = _ConstraintWrapper(LinearConstraint(A, -np.inf, 0), x0) assert (pc.violation(x0) > 0).any() assert (pc.violation([-10, 2, -10, 4]) == 0).all() pc = _ConstraintWrapper(LinearConstraint(csr_matrix(A), -np.inf, 0), x0) assert (pc.violation(x0) > 0).any() assert (pc.violation([-10, 2, -10, 4]) == 0).all() def fun(x): return A.dot(x) nonlinear = NonlinearConstraint(fun, -np.inf, 0) pc = _ConstraintWrapper(nonlinear, [-10, 2, -10, 4]) assert (pc.violation(x0) > 0).any() assert (pc.violation([-10, 2, -10, 4]) == 0).all()
def test_prepare_constraint_infeasible_x0(): lb = np.array([0, 20, 30]) ub = np.array([0.5, np.inf, 70]) x0 = np.array([1, 2, 3]) enforce_feasibility = np.array([False, True, True], dtype=bool) bounds = Bounds(lb, ub, enforce_feasibility) pytest.raises(ValueError, PreparedConstraint, bounds, x0) x0 = np.array([1, 2, 3, 4]) A = np.array([[1, 2, 3, 4], [5, 0, 0, 6], [7, 0, 8, 0]]) enforce_feasibility = np.array([True, True, True], dtype=bool) linear = LinearConstraint(A, -np.inf, 0, enforce_feasibility) pytest.raises(ValueError, PreparedConstraint, linear, x0) def fun(x): return A.dot(x) def jac(x): return A def hess(x, v): return sps.csr_matrix((4, 4)) nonlinear = NonlinearConstraint(fun, -np.inf, 0, jac, hess, enforce_feasibility) pytest.raises(ValueError, PreparedConstraint, nonlinear, x0)
def test_concatenation(): rng = np.random.RandomState(0) n = 4 x0 = np.random.rand(n) f1 = x0 J1 = np.eye(n) lb1 = [-1, -np.inf, -2, 3] ub1 = [1, np.inf, np.inf, 3] bounds = Bounds(lb1, ub1, [False, False, True, False]) fun, jac, hess = create_quadratic_function(n, 5, rng) f2 = fun(x0) J2 = jac(x0) lb2 = [-10, 3, -np.inf, -np.inf, -5] ub2 = [10, 3, np.inf, 5, np.inf] nonlinear = NonlinearConstraint(fun, lb2, ub2, jac, hess, [True, False, False, True, False]) for sparse_jacobian in [False, True]: bounds_prepared = PreparedConstraint(bounds, x0, sparse_jacobian) nonlinear_prepared = PreparedConstraint(nonlinear, x0, sparse_jacobian) c1 = CanonicalConstraint.from_PreparedConstraint(bounds_prepared) c2 = CanonicalConstraint.from_PreparedConstraint(nonlinear_prepared) c = CanonicalConstraint.concatenate([c1, c2], sparse_jacobian) assert_equal(c.n_eq, 2) assert_equal(c.n_ineq, 7) c_eq, c_ineq = c.fun(x0) assert_array_equal(c_eq, [f1[3] - lb1[3], f2[1] - lb2[1]]) assert_array_equal(c_ineq, [ lb1[2] - f1[2], f1[0] - ub1[0], lb1[0] - f1[0], f2[3] - ub2[3], lb2[4] - f2[4], f2[0] - ub2[0], lb2[0] - f2[0] ]) J_eq, J_ineq = c.jac(x0) if sparse_jacobian: J_eq = J_eq.toarray() J_ineq = J_ineq.toarray() assert_array_equal(J_eq, np.vstack((J1[3], J2[1]))) assert_array_equal( J_ineq, np.vstack((-J1[2], J1[0], -J1[0], J2[3], -J2[4], J2[0], -J2[0]))) v_eq = rng.rand(c.n_eq) v_ineq = rng.rand(c.n_ineq) v = np.zeros(5) v[1] = v_eq[1] v[3] = v_ineq[3] v[4] = -v_ineq[4] v[0] = v_ineq[5] - v_ineq[6] H = c.hess(x0, v_eq, v_ineq).dot(np.eye(n)) assert_array_equal(H, hess(x0, v)) assert_array_equal(c.keep_feasible, [True, False, False, True, False, True, True])
def test_bounds_checking(self): # test that the bounds checking works func = rosen bounds = [(-3)] assert_raises(ValueError, differential_evolution, func, bounds) bounds = [(-3, 3), (3, 4, 5)] assert_raises(ValueError, differential_evolution, func, bounds) # test that we can use a new-type Bounds object result = differential_evolution(rosen, Bounds([0, 0], [2, 2])) assert_almost_equal(result.x, (1., 1.))
def test_initial_constraints_as_canonical(): # rng is only used to generate the coefficients of the quadratic # function that is used by the nonlinear constraint. rng = np.random.RandomState(0) x0 = np.array([0.5, 0.4, 0.3, 0.2]) n = len(x0) lb1 = [-1, -np.inf, -2, 3] ub1 = [1, np.inf, np.inf, 3] bounds = Bounds(lb1, ub1, [False, False, True, False]) fun, jac, hess = create_quadratic_function(n, 5, rng) lb2 = [-10, 3, -np.inf, -np.inf, -5] ub2 = [10, 3, np.inf, 5, np.inf] nonlinear = NonlinearConstraint(fun, lb2, ub2, jac, hess, [True, False, False, True, False]) for sparse_jacobian in [False, True]: bounds_prepared = PreparedConstraint(bounds, x0, sparse_jacobian) nonlinear_prepared = PreparedConstraint(nonlinear, x0, sparse_jacobian) f1 = bounds_prepared.fun.f J1 = bounds_prepared.fun.J f2 = nonlinear_prepared.fun.f J2 = nonlinear_prepared.fun.J c_eq, c_ineq, J_eq, J_ineq = initial_constraints_as_canonical( n, [bounds_prepared, nonlinear_prepared], sparse_jacobian) assert_array_equal(c_eq, [f1[3] - lb1[3], f2[1] - lb2[1]]) assert_array_equal(c_ineq, [ lb1[2] - f1[2], f1[0] - ub1[0], lb1[0] - f1[0], f2[3] - ub2[3], lb2[4] - f2[4], f2[0] - ub2[0], lb2[0] - f2[0] ]) if sparse_jacobian: J1 = J1.toarray() J2 = J2.toarray() J_eq = J_eq.toarray() J_ineq = J_ineq.toarray() assert_array_equal(J_eq, np.vstack((J1[3], J2[1]))) assert_array_equal( J_ineq, np.vstack((-J1[2], J1[0], -J1[0], J2[3], -J2[4], J2[0], -J2[0])))
def test_bounds_cases(): # Test 1: no constraints. user_constraint = Bounds(-np.inf, np.inf) x0 = np.array([-1, 2]) prepared_constraint = PreparedConstraint(user_constraint, x0, False) c = CanonicalConstraint.from_PreparedConstraint(prepared_constraint) assert_equal(c.n_eq, 0) assert_equal(c.n_ineq, 0) c_eq, c_ineq = c.fun(x0) assert_array_equal(c_eq, []) assert_array_equal(c_ineq, []) J_eq, J_ineq = c.jac(x0) assert_array_equal(J_eq, np.empty((0, 2))) assert_array_equal(J_ineq, np.empty((0, 2))) assert_array_equal(c.keep_feasible, []) # Test 2: infinite lower bound. user_constraint = Bounds(-np.inf, [0, np.inf, 1], [False, True, True]) x0 = np.array([-1, -2, -3], dtype=float) prepared_constraint = PreparedConstraint(user_constraint, x0, False) c = CanonicalConstraint.from_PreparedConstraint(prepared_constraint) assert_equal(c.n_eq, 0) assert_equal(c.n_ineq, 2) c_eq, c_ineq = c.fun(x0) assert_array_equal(c_eq, []) assert_array_equal(c_ineq, [-1, -4]) J_eq, J_ineq = c.jac(x0) assert_array_equal(J_eq, np.empty((0, 3))) assert_array_equal(J_ineq, np.array([[1, 0, 0], [0, 0, 1]])) assert_array_equal(c.keep_feasible, [False, True]) # Test 3: infinite upper bound. user_constraint = Bounds([0, 1, -np.inf], np.inf, [True, False, True]) x0 = np.array([1, 2, 3], dtype=float) prepared_constraint = PreparedConstraint(user_constraint, x0, False) c = CanonicalConstraint.from_PreparedConstraint(prepared_constraint) assert_equal(c.n_eq, 0) assert_equal(c.n_ineq, 2) c_eq, c_ineq = c.fun(x0) assert_array_equal(c_eq, []) assert_array_equal(c_ineq, [-1, -1]) J_eq, J_ineq = c.jac(x0) assert_array_equal(J_eq, np.empty((0, 3))) assert_array_equal(J_ineq, np.array([[-1, 0, 0], [0, -1, 0]])) assert_array_equal(c.keep_feasible, [True, False]) # Test 4: interval constraint. user_constraint = Bounds([-1, -np.inf, 2, 3], [1, np.inf, 10, 3], [False, True, True, True]) x0 = np.array([0, 10, 8, 5]) prepared_constraint = PreparedConstraint(user_constraint, x0, False) c = CanonicalConstraint.from_PreparedConstraint(prepared_constraint) assert_equal(c.n_eq, 1) assert_equal(c.n_ineq, 4) c_eq, c_ineq = c.fun(x0) assert_array_equal(c_eq, [2]) assert_array_equal(c_ineq, [-1, -2, -1, -6]) J_eq, J_ineq = c.jac(x0) assert_array_equal(J_eq, [[0, 0, 0, 1]]) assert_array_equal( J_ineq, [[1, 0, 0, 0], [0, 0, 1, 0], [-1, 0, 0, 0], [0, 0, -1, 0]]) assert_array_equal(c.keep_feasible, [False, True, False, True])
def test_Bounds_array(): # gh13501 b = Bounds(lb=[0.0, 0.0], ub=[1.0, 1.0]) assert isinstance(b.lb, np.ndarray) assert isinstance(b.ub, np.ndarray)
def test_residual(self): bounds = Bounds(-2, 4) x0 = [-1, 2] np.testing.assert_allclose(bounds.residual(x0), ([1, 4], [5, 2]))
def test_input_validation(self): message = "`lb`, `ub`, and `keep_feasible` must be broadcastable." with pytest.raises(ValueError, match=message): Bounds([1, 2], [1, 2, 3])
def test_defaults(self): b1 = Bounds() b2 = Bounds(np.asarray(-np.inf), np.asarray(np.inf)) assert b1.lb == b2.lb assert b1.ub == b2.ub
def _do_optimisation(q, args, s, opt): """Run optimisation routine to fit q. Parameters ---------- q : (N, Nq) tensor_like Lie algebra of affine registration fit. args : tuple All arguments for optimiser (except the parameters to be fitted) opt : dict See run_affine_reg. s : float Current sub-sampling level. Returns ---------- q : (N, Nq) tensor_like Optimised Lie algebra of affine registration fit. """ if len(q.shape) == 1: # Pairwise registration N = 1 Nq = q.shape[0] else: # Groupwise registration N = q.shape[0] Nq = q.shape[1] # Optimisers require CPU Numpy arrays device = q.device q = q.cpu().numpy() q_shape = q.shape q = q.flatten() if opt['optimiser'] == 'powell': # Powell optimisation # ---------- # Feasible initial search directions # [translation, rotation, scaling, skew] direc = np.concatenate([ 0.5 * np.ones(3), 0.025 * np.ones(3), 0.005 * np.ones(3), 0.005 * np.ones(3) ]) direc = direc[:Nq] direc = np.tile(direc, N) direc = np.diag(direc) # Feasible upper and lower bounds # [translation, rotation, scaling, skew] ub = np.concatenate([ 100 * np.ones(3), 0.5 * np.ones(3), 0.15 * np.ones(3), 0.15 * np.ones(3) ]) ub = ub[:Nq] ub = np.tile(ub, N) lb = -ub bounds = Bounds(lb=lb, ub=ub) # Callback callback = None if opt['mean_space']: # Ensure that the parameters have zero mean, across images. callback = lambda x: _zero_mean(x, q_shape) # Do optimisation res = _minimize_powell(_compute_cost, q, args, disp=False, callback=callback, direc=direc, bounds=bounds) q = res['x'] # Cast back to tensor q = q.reshape(q_shape) q = torch.from_numpy(q).to(device) from scipy.optimize._minimize import standardize_bounds return q