def test_projection(self): """Test for CConstraint.projection().""" self._test_projection(self.c, self.p1_inside, self.p2_outside, self.p3_on, CArray([1.5, 1.5])) # Test for sparse arrays self._test_projection(self.c, self.p1_inside.tosparse(), self.p2_outside.tosparse(), self.p3_on.tosparse(), CArray([1.5, 1.5], tosparse=True)) # Check sparse arrays and scalar ub/lb # (corner case of sparse arrays as we cannot sub/add scalara) c = CConstraintBox(lb=0, ub=1.5) self._test_projection(c, CArray([1., 1., 0.], tosparse=True), CArray([2., 2., 0.], tosparse=True), CArray([0., 1., 0.]).tosparse(), CArray([1.5, 1.5, 0], tosparse=True)) # Constraint with one or more inf c = CConstraintBox(lb=CArray([0, -inf]), ub=1.5) self._test_projection(c, self.p1_inside, self.p2_outside, p_out_expected=CArray([1.5, 1.5])) c = CConstraintBox(lb=CArray([-inf, -0.5]), ub=inf) self._test_projection( # Using [-2, -2] as outside, expect [-2, -0.5] c, self.p1_inside, -self.p2_outside, p_out_expected=CArray([-2, -0.5]))
def test_constraint(self): """Test for CConstraint.constraint().""" self._test_constraint(self.c, self.p1_inside, self.p2_outside, self.p3_on) # Test for sparse arrays self._test_constraint(self.c, self.p1_inside.tosparse(), self.p2_outside.tosparse(), self.p3_on.tosparse()) # Constraint with one or more inf, error should be raised c = CConstraintBox(lb=CArray([0, -inf]), ub=1.5) with self.assertRaises(ValueError): c.constraint(self.p1_inside)
def test_is_violated(self): """Test for CConstraint.is_violated().""" self._test_is_violated(self.c, self.p1_inside, self.p2_outside, self.p3_on) # Test for sparse arrays self._test_is_violated(self.c, self.p1_inside.tosparse(), self.p2_outside.tosparse(), self.p3_on.tosparse()) # Constraint with one or more inf c = CConstraintBox(lb=CArray([0, -inf]), ub=1.5) self._test_is_violated(c, self.p1_inside, self.p2_outside, self.p3_on) c = CConstraintBox(lb=CArray([0, -0.5]), ub=inf) self._test_is_violated( # Using [-2, -2] as outside c, self.p1_inside, -self.p2_outside, self.p3_on)
def _create_box(self): """Create a box constraint""" if self.lb == "x0": self.lb = self.x0 if self.ub == "x0": self.ub = self.x0 box = CConstraintBox(lb=self.lb, ub=self.ub) return box
def setUp(self): self.c = CConstraintBox(lb=CArray([0, -0.5]), ub=1.5) # create a point that lies inside the constraint self.p1_inside = CArray([1., 1.]) # create a point that lies outside the constraint self.p2_outside = CArray([2., 2.]) # create a point that lies on the constraint self.p3_on = CArray([0., 1.])
def test_is_active(self): """Test for CConstraint.is_active().""" self._test_is_active(self.c, self.p1_inside, self.p2_outside, self.p3_on) # Test for sparse arrays self._test_is_active(self.c, self.p1_inside.tosparse(), self.p2_outside.tosparse(), self.p3_on.tosparse()) # Constraint with one or more inf, should be never active c = CConstraintBox(lb=CArray([0, -0.5]), ub=inf) self.assertEqual(c.is_active(self.p1_inside), False) self.assertEqual(c.is_active(self.p2_outside), False) self.assertEqual(c.is_active(self.p3_on), False) c = CConstraintBox(lb=CArray([0, -inf]), ub=2) self.assertEqual(c.is_active(self.p1_inside), False) self.assertEqual(c.is_active(self.p2_outside), False) self.assertEqual(c.is_active(self.p3_on), False)
def test_minimize_mc_cormick(self): """Test for COptimizer.minimize() method on mc-cormick fun.""" from secml.optim.function import CFunctionMcCormick from secml.optim.constraints import CConstraintBox opt_params = { 'eta': 1e-1, 'eps': 1e-12, 'bounds': CConstraintBox(*CFunctionMcCormick.bounds()) } self._test_minimize(COptimizerPGD, 'mc-cormick', opt_params=opt_params)
def test_minimize_mc_cormick(self): """Test for COptimizer.minimize() method on mc-cormick fun.""" # mc-cormick always needs the bounds # test using L-BFGS-B scipy solver (supports bounds) bounds = CConstraintBox(lb=-2, ub=3) # fake box self._test_minimize(COptimizerScipy, 'mc-cormick', opt_params={'bounds': bounds}, minimize_params={ 'method': 'L-BFGS-B', 'options': { 'gtol': 1e-6 } })
def _box(evas): """Return the bounding box constraint. Parameters ---------- evas : CAttackEvasion Returns ------- CConstraintBox """ # TODO: there is no way to cleanly extract it from evasion object return CConstraintBox(lb=evas.lb, ub=evas.ub)
def test_check_bounds(self): """Check validation of lb/ub""" CConstraintBox(lb=0.5, ub=1.5) # Fine CConstraintBox(lb=CArray([0, -0.5]), ub=1.5) # Fine CConstraintBox(lb=-1.5, ub=CArray([inf, -0.5])) # Fine CConstraintBox(lb=CArray([-inf, 0]), ub=CArray([0, 0.5])) # Fine # LB > UB with self.assertRaises(ValueError): CConstraintBox(lb=2, ub=1.5) with self.assertRaises(ValueError): CConstraintBox(lb=1.5, ub=CArray([2, -0.5])) with self.assertRaises(ValueError): CConstraintBox(lb=CArray([2, 0]), ub=CArray([-1.5, 1.5])) # LB, UB both CArray but with different dimensions with self.assertRaises(ValueError): CConstraintBox(lb=CArray([0]), ub=CArray([-1.5, 1.5]))
def test_minimize_beale(self): """Test for COptimizer.minimize() method on 3h-camel fun. This function tests the optimization in discrete space, with a floating eta and an integer starting point. The solution expected by this test is a float vector.""" opt_params = { 'eta': 1e-6, 'eta_min': 1e-4, 'eps': 1e-12, 'discrete': True, 'bounds': CConstraintBox(lb=0, ub=4) } self._test_minimize(COptimizerPGDLS, 'beale', opt_params=opt_params, label='discrete')
def test_minimize_3h_camel(self): """Test for COptimizer.minimize() method on 3h-camel fun. This function tests the optimization in discrete space, with an integer eta and an integer starting point. The solution expected by this test is a integer vector. """ opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'bounds': CConstraintBox(lb=-1, ub=1) } self._test_minimize(COptimizerPGDLS, '3h-camel', opt_params=opt_params, label='discrete', out_int=True)
def test_minimize_3h_camel_l1(self): """Test for COptimizer.minimize() method on 3h-camel fun. This function tests the optimization in discrete space, with a floating eta (l1 constraint) and an integer starting point. The solution expected by this test is a float vector. """ opt_params = { 'eta': 0.5, 'eta_min': 0.5, 'eps': 1e-12, 'constr': CConstraintL1(radius=2), 'bounds': CConstraintBox(lb=-1, ub=1) } self._test_minimize(COptimizerPGDLS, '3h-camel', opt_params=opt_params, label='discrete-l1')
def test_minimize_poly_100d_bounded_sparse(self): """Test for COptimizer.minimize() method on a polynomial function in a 100-dimensional space. This function tests the optimization in discrete space, with an integer eta, an integer and sparse starting point (it is a zero vector) with a box constraint. The solution expected by this test is an integer and sparse vector.""" opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'discrete': True, 'bounds': CConstraintBox(lb=-1, ub=1) } self._test_minimize(COptimizerPGDLS, 'poly-100-int-sparse', opt_params=opt_params, label='poly-int-sparse-discrete-bounded', out_int=True)
def test_minimize_quad2d_bound(self): """Test for COptimizer.minimize() method on a quadratic function in a 2-dimensional space. This function tests the optimization in discrete space, with an integer eta, an integer starting point and with a box constraint. The solution expected by this test is an integer vector. """ opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'bounds': CConstraintBox(lb=-2, ub=3) } self._test_minimize(COptimizerPGDLS, 'quad-2', opt_params=opt_params, label='quad-2-discrete-bounded', out_int=True)
def test_minimize_poly_100d_bounded(self): """Test for COptimizer.minimize() method on a polynomial function in a 2-dimensional space. This function tests the optimization in discrete space, with an integer eta, an integer starting point with a box constraint. The solution of this problem is an integer vector (of zeros). """ opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'bounds': CConstraintBox(lb=-1, ub=1) } self._test_minimize(COptimizerPGDLS, 'poly-100-int', opt_params=opt_params, label='poly-int-discrete-bounded', out_int=True)
def test_minimize_quad100d_l1_sparse(self): """Test for COptimizer.minimize() method on a quadratic function in a 100-dimensional space. This function tests the optimization in discrete space, with an integer eta (l1 constraint), an integer sparse starting point with box constraint. The solution expected by this test is an integer sparse vector. """ opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'constr': CConstraintL1(radius=100), 'bounds': CConstraintBox(lb=-2, ub=3) } self._test_minimize(COptimizerPGDLS, 'quad-100-sparse', opt_params=opt_params, label='quad-100-sparse-discrete-bounded-l1', out_int=True)
def test_minimize_expsum2d_bounded(self): """Test for COptimizer.minimize() method on a polynomial function in a 2-dimensional space. This function tests the optimization in discrete space, with an integer eta, an floating starting point with a box constraint. The solution expected by this test is an integer vector.""" opt_params = { 'eta': 1, 'eta_min': 1, 'eps': 1e-12, 'discrete': True, 'bounds': CConstraintBox(lb=-1, ub=1) } self._test_minimize( COptimizerPGDLS, 'poly-2', opt_params=opt_params, label='poly-discrete-bounded', )
def test_minimize_3h_camel(self): """Test for COptimizer.minimize() method on 3h-camel fun.""" self._test_minimize(COptimizerScipy, '3h-camel', opt_params={}, minimize_params={ 'method': 'BFGS', 'options': { 'gtol': 1e-6 } }) # test using L-BFGS-B scipy solver (supports bounds) bounds = CConstraintBox(lb=-2, ub=3) # fake box self._test_minimize(COptimizerScipy, '3h-camel', opt_params={'bounds': bounds}, minimize_params={ 'method': 'L-BFGS-B', 'options': { 'gtol': 1e-6 } })
def _test_constr_bounds(self, opt_class): """Test for COptimizer.minimize() method behaviour depending on constraint and bounds. 3 cases will be tested against 'rosenbrock' function - constraint radius 0 (no bounds) - constraint radius 0 inside bounds - constraint radius 0 outside bounds (should raise warning) Parameters ---------- opt_class : class COptimizer. """ fun_dict = self.test_funcs['rosenbrock'] fun = fun_dict['fun'] # Constraint radius 0 (no bounds) opt_params = {'constr': CConstraintL2(center=CArray([0, 0]), radius=0)} opt = opt_class(fun, **opt_params) opt.verbose = 1 self.logger.info("Testing minimization of {:} using {:} " "and constr {:}".format(fun.__class__.__name__, opt.__class__.__name__, opt_params['constr'])) min_x = opt.minimize(fun_dict['x0']) self.assertAlmostEqual(opt.f_opt, 1.0) self.assert_array_almost_equal(min_x.todense().ravel(), CArray([0, 0])) # Constraint radius 0 inside bounds opt_params = { 'constr': CConstraintL2(center=CArray([0, 0]), radius=0), 'bounds': CConstraintBox(lb=-1, ub=1) } opt = opt_class(fun, **opt_params) opt.verbose = 1 self.logger.info("Testing minimization of {:} using {:}, constr {:} " "and bounds {:}".format(fun.__class__.__name__, opt.__class__.__name__, opt_params['constr'], opt_params['bounds'])) min_x = opt.minimize(fun_dict['x0']) self.assertAlmostEqual(opt.f_opt, 1.0) self.assert_array_almost_equal(min_x.todense().ravel(), CArray([0, 0])) # Constraint radius 0 outside bounds (should raise warning) opt_params = { 'constr': CConstraintL2(center=CArray([0, 0]), radius=0), 'bounds': CConstraintBox(lb=1, ub=2) } opt = opt_class(fun, **opt_params) opt.verbose = 1 self.logger.info("Testing minimization of {:} using {:}, constr {:} " "and bounds {:}".format(fun.__class__.__name__, opt.__class__.__name__, opt_params['constr'], opt_params['bounds'])) with self.logger.catch_warnings(record=True) as w: min_x = opt.minimize(fun_dict['x0']) self.assertIn('is outside of the given bounds', w[0].message.args[0]) self.assertAlmostEqual(opt.f_opt, 1.0) self.assert_array_almost_equal(min_x.todense().ravel(), CArray([0, 0]))