class TestAtan(UnaryFunctionTest): @given(child=expressions()) def test_is_concave(self, visitor, child): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, I(0, None), pe.atan) assert cvx == C.Concave @pytest.mark.parametrize('bounds', [I(None, 0), I(None, None)]) @given(child=expressions()) def test_is_not_concave(self, visitor, child, bounds): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, bounds, pe.atan) assert cvx == C.Unknown @given(child=expressions()) def test_is_convex(self, visitor, child): cvx = self._rule_result(visitor, child, C.Convex, M.Unknown, I(None, 0), pe.atan) assert cvx == C.Convex @pytest.mark.parametrize('bounds', [I(0, None), I(None, None)]) @given(child=expressions()) def test_is_not_convex(self, visitor, child, bounds): cvx = self._rule_result(visitor, child, C.Convex, C.Unknown, bounds, pe.atan) assert cvx == C.Unknown
def test_problem(self): problem = self.get_problem( lambda m: aml.cos(m.x) * aml.sin(m.y) - m.x / (m.y * m.y + 1)) h = IntervalHessianEvaluator(problem) h.eval_at_x(np.array([I(-1, 2), I(-1, 1)])) print(h.jacobian[0]) print(h.hessian[0]) assert False
def test_positive_lt_0_non_integer(self, visitor, base, expo, cvx, expected): expo = expo - 1e-5 # make it negative assume(not almosteq(expo, int(expo))) cvx = self._rule_result(visitor, base, cvx, M.Unknown, I(0, None), expo) assert cvx == expected
def test_noninteger_negative_base(self, visitor, base, expo, mono_base): assume(not almosteq(expo, 0)) assume(not almosteq(expo, int(expo))) mono = self._result_with_base_expo( visitor, base, mono_base, I(None, 0), expo ) assert mono == M.Unknown
def test_positive_gt_1_non_integer_negative_base(self, visitor, base, expo): expo = expo + 1e-6 assume(expo != int(expo)) cvx = self._rule_result(visitor, base, C.Convex, M.Unknown, I(None, -1), expo) assert cvx == C.Unknown
def test_product_with_constant(self, visitor, f, g, cvx_f, bounds_g, expected): assume(f.is_expression_type() and not isinstance(f, MonomialTermExpression)) cvx_g = C.Linear # g is constant mono_f = M.Unknown mono_g = M.Constant bounds_f = I(None, None) assert self._rule_result(visitor, f, g, cvx_f, cvx_g, mono_f, mono_g, bounds_f, bounds_g) == expected assert self._rule_result(visitor, g, f, cvx_g, cvx_f, mono_g, mono_f, bounds_g, bounds_f) == expected
def test_Pow(self): problem = self.get_problem(lambda m: m.x**2) h = IntervalHessianEvaluator(problem) h.eval_at_x(np.array([I(-1, 1), I(2, 3)])) print(h.jacobian[0]) print(h.hessian[0]) assert np.all(h.jacobian[0] == np.array([I(-2, 2), I(0, 0)])) assert np.all(h.hessian[0] == np.array([[I(2, 2), I(0, 0)], [I(0, 0), I(0, 0)]]))
def test_abs_nonnegative(self): problem = self.get_problem(lambda m: abs(m.x)) h = IntervalHessianEvaluator(problem) h.eval_at_x(np.array([I(0, 1), I(2, 3)])) print(h.jacobian[0]) print(h.hessian[0]) assert np.all(h.jacobian[0] == np.array([I(0, 1), I(0, 0)])) assert np.all(h.hessian[0] == np.array([[I(0, 0), I(0, 0)], [I(0, 0), I(0, 0)]]))
class TestAbs(UnaryFunctionTest): @pytest.mark.parametrize( 'mono,bounds', itertools.product( [M.Nondecreasing, M.Nonincreasing, M.Constant], [I(None, 0), I(0, None), I(None, None)])) @given(child=expressions()) def test_linear_child(self, visitor, child, mono, bounds): cvx = self._rule_result(visitor, child, C.Linear, mono, bounds, abs) assert cvx == C.Convex @pytest.mark.parametrize('mono,bounds,expected', [ (M.Unknown, I(0, None), C.Convex), (M.Unknown, I(None, 0), C.Concave), ]) @given(child=expressions()) def test_convex_child(self, visitor, child, mono, bounds, expected): cvx = self._rule_result(visitor, child, C.Convex, mono, bounds, abs) assert cvx == expected @pytest.mark.parametrize('mono,bounds,expected', [ (M.Unknown, I(0, None), C.Concave), (M.Unknown, I(None, 0), C.Convex), ]) @given(child=expressions()) def test_concave_child(self, visitor, child, mono, bounds, expected): cvx = self._rule_result(visitor, child, C.Concave, mono, bounds, abs) assert cvx == expected
def test_linear_over_variable(coef): rule = FractionalRule() x = PE(ET.Variable) num = PE(ET.Linear, [x], coefficients=[coef], constant_term=0.0) ctx = FractionalContext({ x: I(0, None), }) result = rule.apply(PE(ET.Division, [num, x]), ctx) assert result == Convexity.Linear
def test_product(self): problem = self.get_problem(lambda m: m.x * m.y) h = IntervalHessianEvaluator(problem) h.eval_at_x(np.array([I(-1, 1), I(2, 3)])) assert np.all(h.jacobian[0] == np.array([I(2, 3), I(-1, 1)])) expected_hess = np.array([ [I(0, 0), I(1, 1)], [I(1, 1), I(0, 0)], ]) assert np.all(h.hessian[0] == expected_hess)
def _result_with_base_expo(self, visitor, base, mono_base, bounds_base, expo): mono = ComponentMap() mono[base] = mono_base mono[expo] = M.Constant bounds = ComponentMap() bounds[base] = bounds_base bounds[expo] = I(expo, expo) expr = PowExpression([base, expo]) matched, result = visitor.visit_expression(expr, mono, bounds) assert matched return result
class TestExp(UnaryFunctionTest): @pytest.mark.parametrize( 'cvx,mono,bounds', itertools.product( [C.Convex, C.Linear], [M.Nondecreasing, M.Nonincreasing, M.Constant, M.Unknown], [I(0, None), I(None, 0), I(None, None)], ) ) @given(child=expressions()) def test_convex_child(self, visitor, child, cvx, mono, bounds): cvx = self._rule_result(visitor, child, cvx, mono, bounds, pe.exp) assert cvx == C.Convex @pytest.mark.parametrize( 'cvx,mono,bounds', itertools.product( [C.Concave, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Constant, M.Unknown], [I(0, None), I(None, 0), I(None, None)], ) ) @given(child=expressions()) def test_convex_child(self, visitor, child, cvx, mono, bounds): cvx = self._rule_result(visitor, child, cvx, mono, bounds, pe.exp) assert cvx == C.Unknown
def _result_with_base_expo(self, visitor, base, expo, mono_expo, bounds_expo): rule = PowerRule() mono = ComponentMap() mono[base] = M.Constant mono[expo] = mono_expo bounds = ComponentMap() bounds[base] = I(base, base) bounds[expo] = bounds_expo expr = base ** expo assume(isinstance(expr, PowExpression)) matched, result = visitor.visit_expression(expr, mono, bounds) assert matched return result
def _rule_result(self, visitor, base, cvx_base, mono_base, bounds_base, expo): convexity = ComponentMap() convexity[base] = cvx_base convexity[expo] = C.Linear mono = ComponentMap() mono[base] = mono_base mono[expo] = M.Constant bounds = ComponentMap() bounds[base] = bounds_base bounds[expo] = I(expo, expo) expr = PowExpression([base, expo]) matched, result = visitor.visit_expression(expr, convexity, mono, bounds) assert matched return result
def test_division(visitor, g, mono_g, bound_g, expected): num = NumericConstant(1.0) bounds = ComponentMap() bounds[num] = I(1.0, 1.0) bounds[g] = bound_g mono = ComponentMap() mono[num] = M.Constant mono[g] = mono_g print(mono) print(mono[num]) expr = DivisionExpression([num, g]) matched, result = visitor.visit_expression(expr, mono, bounds) assert matched assert result == expected
def nonnegative_sin_bounds(draw): start = draw(st.floats( min_value=0.1*pi, max_value=0.9*pi, allow_nan=False, allow_infinity=False, )) end = draw(st.floats( min_value=0, max_value=0.9*pi-start, allow_nan=False, allow_infinity=False, )) mul = draw(st.integers(min_value=-100, max_value=100)) * 2 * pi b = I(start + mul, start + end + mul) assume(b.size() > 0) return b
def test_linear_with_constant_over_variable(coef, const): assume(coef != 0.0) assume(coef < MAX_NUM and const < MAX_NUM) rule = FractionalRule() x = PE(ET.Variable) num = PE(ET.Linear, [x], coefficients=[coef], constant_term=const) ctx = FractionalContext({ x: I(0, None), }) result = rule.apply(PE(ET.Division, [num, x]), ctx) if almosteq(const, 0): expected = Convexity.Linear elif const > 0: expected = Convexity.Convex elif const < 0: expected = Convexity.Concave
def test_bound_opposite_sign(self, visitor, child): cvx = self._rule_result(visitor, child, C.Linear, M.Constant, I(-0.1, 0.1), pe.tan) assert cvx == C.Unknown
def test_bound_size_too_big(self, visitor, child): cvx = self._rule_result(visitor, child, C.Linear, M.Constant, I(-2, 2), pe.tan) assert cvx == C.Unknown
def test_negative_cos_convex_child(self, visitor, child): cvx = self._rule_result(visitor, child, C.Convex, M.Unknown, I(0.6 * pi, 0.9 * pi), pe.cos) assert cvx == C.Convex
def test_positive_tan_concave_child(self, visitor, child): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, I(pi, 1.5 * pi), pe.tan) assert cvx == C.Unknown
def test_positive_gt_1_non_integer(self, visitor, base, expo): expo = expo + 1e-5 # make it positive assume(expo != int(expo)) cvx = self._rule_result(visitor, base, C.Convex, M.Unknown, I(0, None), expo) assert cvx == C.Convex
class TestPowConstantBase: def _rule_result(self, visitor, base, expo, cvx_expo, mono_expo, bounds_expo): convexity = ComponentMap() convexity[expo] = cvx_expo convexity[base] = C.Linear mono = ComponentMap() mono[expo] = mono_expo mono[base] = M.Constant bounds = ComponentMap() bounds[base] = I(base, base) bounds[expo] = bounds_expo expr = PowExpression([base, expo]) matched, result = visitor.visit_expression(expr, convexity, mono, bounds) assert matched return result @pytest.mark.parametrize( 'cvx_expo,mono_expo,bounds_expo', itertools.product( [C.Convex, C.Concave, C.Linear, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Unknown], [I(None, 0), I(0, None), I(None, None)], )) @given( base=reals(max_value=-0.01, allow_infinity=False), expo=expressions(), ) def test_negative_base(self, visitor, base, expo, cvx_expo, mono_expo, bounds_expo): cvx = self._rule_result(visitor, base, expo, cvx_expo, mono_expo, bounds_expo) assert cvx == C.Unknown @pytest.mark.parametrize( 'cvx_expo,mono_expo,bounds_expo', itertools.product( [C.Convex, C.Concave, C.Linear, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Unknown], [I(None, 0), I(0, None), I(None, None)], )) @given( base=reals(min_value=0.001, max_value=0.999), expo=expressions(), ) def test_base_between_0_and_1(self, visitor, base, expo, cvx_expo, mono_expo, bounds_expo): if cvx_expo == C.Concave or cvx_expo == C.Linear: expected = C.Convex else: expected = C.Unknown cvx = self._rule_result(visitor, base, expo, cvx_expo, mono_expo, bounds_expo) assert cvx == expected @pytest.mark.parametrize( 'cvx_expo,mono_expo,bounds_expo', itertools.product( [C.Convex, C.Concave, C.Linear, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Unknown], [I(None, 0), I(0, None), I(None, None)], )) @given( base=reals(min_value=1, allow_infinity=False), expo=expressions(), ) def test_base_gt_1(self, visitor, base, expo, cvx_expo, mono_expo, bounds_expo): if cvx_expo == C.Convex or cvx_expo == C.Linear: expected = C.Convex else: expected = C.Unknown cvx = self._rule_result(visitor, base, expo, cvx_expo, mono_expo, bounds_expo) assert cvx == expected
class TestPowConstantExponent(object): def _rule_result(self, visitor, base, cvx_base, mono_base, bounds_base, expo): convexity = ComponentMap() convexity[base] = cvx_base convexity[expo] = C.Linear mono = ComponentMap() mono[base] = mono_base mono[expo] = M.Constant bounds = ComponentMap() bounds[base] = bounds_base bounds[expo] = I(expo, expo) expr = PowExpression([base, expo]) matched, result = visitor.visit_expression(expr, convexity, mono, bounds) assert matched return result @pytest.mark.parametrize( 'cvx_base,mono_base,bounds_base', itertools.product( [C.Convex, C.Concave, C.Linear, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Unknown], [I(None, 0), I(0, None), I(None, None)], )) @given(base=expressions()) def test_exponent_equals_0(self, visitor, base, cvx_base, mono_base, bounds_base): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, 0.0) assert cvx == C.Linear @pytest.mark.parametrize( 'cvx_base,mono_base,bounds_base', itertools.product( [C.Convex, C.Concave, C.Linear, C.Unknown], [M.Nondecreasing, M.Nonincreasing, M.Unknown], [I(None, 0), I(0, None), I(None, None)], )) @given(base=expressions()) def test_exponent_equals_1(self, visitor, base, cvx_base, mono_base, bounds_base): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, 1.0) assert cvx == cvx_base @pytest.mark.parametrize('cvx_base,mono_base,bounds_base,expected', [ (C.Linear, M.Nondecreasing, I(None, None), C.Convex), (C.Convex, M.Unknown, I(0, None), C.Convex), (C.Convex, M.Unknown, I(None, 0), C.Unknown), (C.Concave, M.Unknown, I(0, None), C.Unknown), (C.Concave, M.Unknown, I(None, 0), C.Convex), ]) @given( base=expressions(), expo=st.integers(min_value=1), ) def test_positive_even_integer(self, visitor, base, expo, cvx_base, mono_base, bounds_base, expected): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, 2 * expo) assert cvx == expected @pytest.mark.parametrize('cvx_base,mono_base,bounds_base,expected', [ (C.Convex, M.Unknown, I(None, 0), C.Convex), (C.Convex, M.Unknown, I(0, None), C.Concave), (C.Concave, M.Unknown, I(0, None), C.Convex), (C.Concave, M.Unknown, I(None, 0), C.Concave), ]) @given( base=expressions(), expo=st.integers(min_value=1), ) def test_negative_even_integer(self, visitor, base, expo, cvx_base, mono_base, bounds_base, expected): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, -2 * expo) assert cvx == expected @pytest.mark.parametrize('cvx_base,mono_base,bounds_base,expected', [ (C.Convex, M.Unknown, I(0, None), C.Convex), (C.Convex, M.Unknown, I(None, 0), C.Unknown), (C.Concave, M.Unknown, I(None, 0), C.Concave), (C.Concave, M.Unknown, I(0, None), C.Unknown), ]) @given( base=expressions(), expo=st.integers(min_value=1), ) def test_positive_odd_integer(self, visitor, base, expo, cvx_base, mono_base, bounds_base, expected): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, 2 * expo + 1) assert cvx == expected @pytest.mark.parametrize('cvx_base,mono_base,bounds_base,expected', [ (C.Concave, M.Unknown, I(0, None), C.Convex), (C.Concave, M.Unknown, I(None, 0), C.Unknown), (C.Convex, M.Unknown, I(None, 0), C.Concave), (C.Convex, M.Unknown, I(0, None), C.Unknown), ]) @given( base=expressions(), expo=st.integers(min_value=1), ) def test_negative_odd_integer(self, visitor, base, expo, cvx_base, mono_base, bounds_base, expected): cvx = self._rule_result(visitor, base, cvx_base, mono_base, bounds_base, -2 * expo + 1) assert cvx == expected @given( base=expressions(), expo=reals(min_value=1, allow_infinity=False), ) def test_positive_gt_1_non_integer_negative_base(self, visitor, base, expo): expo = expo + 1e-6 assume(expo != int(expo)) cvx = self._rule_result(visitor, base, C.Convex, M.Unknown, I(None, -1), expo) assert cvx == C.Unknown @given( base=expressions(), expo=reals(min_value=1, allow_infinity=False), ) def test_positive_gt_1_non_integer(self, visitor, base, expo): expo = expo + 1e-5 # make it positive assume(expo != int(expo)) cvx = self._rule_result(visitor, base, C.Convex, M.Unknown, I(0, None), expo) assert cvx == C.Convex @pytest.mark.parametrize('cvx,expected', [(C.Convex, C.Concave), (C.Concave, C.Convex)]) @given( base=expressions(), expo=reals(max_value=0, allow_infinity=False), ) def test_positive_lt_0_non_integer(self, visitor, base, expo, cvx, expected): expo = expo - 1e-5 # make it negative assume(not almosteq(expo, int(expo))) cvx = self._rule_result(visitor, base, cvx, M.Unknown, I(0, None), expo) assert cvx == expected @given( base=expressions(), expo=reals(min_value=0, max_value=1, allow_infinity=False), ) def test_positive_0_1_non_integer(self, visitor, base, expo): assume(not almosteq(expo, int(expo))) cvx = self._rule_result(visitor, base, C.Concave, M.Unknown, I(0, None), expo) assert cvx == C.Concave
def test_is_convex(self, visitor, child): cvx = self._rule_result(visitor, child, C.Convex, M.Unknown, I(None, 0), pe.atan) assert cvx == C.Convex
def test_is_concave(self, visitor, child): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, I(0, None), pe.atan) assert cvx == C.Concave
def test_negative_tan_convex_child(self, visitor, child): cvx = self._rule_result(visitor, child, C.Convex, M.Unknown, I(-1.5 * pi, -pi), pe.tan) assert cvx == C.Unknown
def test_is_convex(self, visitor, child): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, I(-1, 0), pe.acos) assert cvx == C.Convex
def test_negative_tan_concave_child(self, visitor, child): cvx = self._rule_result(visitor, child, C.Concave, M.Unknown, I(-0.49 * pi, -0.1), pe.tan) assert cvx == C.Concave