Source code for PEPit.functions.convex_indicator

import numpy as np

from PEPit.point import Point
from PEPit.function import Function


[docs] class ConvexIndicatorFunction(Function): """ The :class:`ConvexIndicatorFunction` class overwrites the `add_class_constraints` method of :class:`Function`, implementing interpolation constraints for the class of closed convex indicator functions. Attributes: D (float): upper bound on the diameter of the feasible set, possibly set to np.inf R (float): upper bound on the radius of the feasible set, possibly set to np.inf center (Point): Center of the feasible set spanned by the radius constraint. If set to None, there exists such a point but it remains undefined. Convex indicator functions are characterized by a parameter `D` and/or `R`, hence can be instantiated as Example: >>> from PEPit import PEP >>> from PEPit import Point >>> from PEPit.functions import ConvexIndicatorFunction >>> problem = PEP() >>> func1 = problem.declare_function(function_class=ConvexIndicatorFunction, D=1) >>> func2 = problem.declare_function(function_class=ConvexIndicatorFunction, R=1) >>> omega = Point() >>> func3 = problem.declare_function(function_class=ConvexIndicatorFunction, R=1, center=omega) References: `[1] A. Taylor, J. Hendrickx, F. Glineur (2017). Exact worst-case performance of first-order methods for composite convex optimization. SIAM Journal on Optimization, 27(3):1283–1313. <https://arxiv.org/pdf/1512.07516.pdf>`_ """ def __init__(self, D=np.inf, R=np.inf, center=None, is_leaf=True, decomposition_dict=None, reuse_gradient=False, name=None): """ Args: D (float): Diameter of the support of self. Default value set to infinity. R (float): Radius of the support of self. Default value set to infinity. center: Center of the feasible set spanned by the radius constraint of self. Default value set to None. If the value is None, the feasible set is centered on the origin. is_leaf (bool): True if self is defined from scratch. False if self is defined as linear combination of leaf. decomposition_dict (dict): Decomposition of self as linear combination of leaf :class:`Function` objects. Keys are :class:`Function` objects and values are their associated coefficients. reuse_gradient (bool): If True, the same subgradient is returned when one requires it several times on the same :class:`Point`. If False, a new subgradient is computed each time one is required. name (str): name of the object. None by default. Can be updated later through the method `set_name`. """ super().__init__(is_leaf=is_leaf, decomposition_dict=decomposition_dict, reuse_gradient=reuse_gradient, name=name, ) # Store the diameter D in an attribute self.D = D # Store the radius R in an attribute self.R = R # Store the center in an attribute if center is None and self.R != np.inf: self.center = Point() else: self.center = center
[docs] @staticmethod def set_value_constraint_i(xi, gi, fi): """ Set the value of the function to 0 everywhere on the support. """ # Value constraint constraint = (fi == 0) return constraint
[docs] @staticmethod def set_convexity_constraint_i_j(xi, gi, fi, xj, gj, fj, ): """ Formulates the list of interpolation constraints for self (CCP function). """ # Interpolation conditions of convex functions class constraint = (0 >= gj * (xi - xj)) return constraint
[docs] def set_diameter_constraint_i_j(self, xi, gi, fi, xj, gj, fj, ): """ Formulate the constraints bounding the diameter of the support of self. """ # Diameter constraint constraint = ((xi - xj) ** 2 <= self.D ** 2) return constraint
[docs] def set_radius_constraint_i(self, xi, gi, fi, ): """ Formulate the constraints bounding the radius of the support of self around self.center. """ # Radius constraint constraint = ((xi - self.center)**2 <= self.R ** 2) return constraint
[docs] def add_class_constraints(self): """ Formulates the list of interpolation constraints for self (closed convex indicator function), see [1, Theorem 3.6]. """ self.add_constraints_from_one_list_of_points(list_of_points=self.list_of_points, constraint_name="value", set_class_constraint_i=self.set_value_constraint_i, ) self.add_constraints_from_two_lists_of_points(list_of_points_1=self.list_of_points, list_of_points_2=self.list_of_points, constraint_name="convexity", set_class_constraint_i_j=self.set_convexity_constraint_i_j, ) if self.D != np.inf: self.add_constraints_from_two_lists_of_points(list_of_points_1=self.list_of_points, list_of_points_2=self.list_of_points, constraint_name="diameter", set_class_constraint_i_j=self.set_diameter_constraint_i_j, ) if self.R != np.inf: self.add_constraints_from_one_list_of_points(list_of_points=self.list_of_points, constraint_name="radius", set_class_constraint_i=self.set_radius_constraint_i, )