Functions#

Function Base Class#

class pepflow.Function(*, is_basis: bool, composition: AddedFunc | ScaledFunc | None = None, tags: list[str] = NOTHING, math_expr: MathExpr = NOTHING)#

A Function object represents a function.

Function objects can be constructed as linear combinations of other Function objects. Let a and b be some numeric data type. Let f and g be Function objects. Then, we can form a new Function object: a*f+b*g.

A Function object should never be explicitly constructed. Only children of Function such as ConvexFunction or SmoothConvexFunction should be constructed. See their respective documentation to see how.

Every child class needs to implement the get_interpolation_constraints_by_group() method. This returns a ConstraintData object which will store the Function’s interpolation conditions. See the ConstraintData documentation for details and the ConvexFunction or SmoothConvexFunction for examples.

Let f be a Function object. The naming convention for a ScalarConstraint object representing an interpolation condition of f between two Vector objects x_0 and x_1 is {f.tag}:{x_0.tag},{x_1.tag}. The naming convention for a ScalarConstraint object representing an interpolation condition of f using only one Vector object x_0 is {f.tag}:{x_0.tag},{x_0.tag}.

If a Function has multiple ScalarConstraint groups, then the naming convention of the individual ScalarConstraint objects must differ. For example, Convex Lipschitz functions has a group of ScalarConstraint objects representing the interpolation conditions related to convexity and a group of ScalarConstraint objects representing the interpolation conditions related to Lipschitz Continuity. Let f be a Function object. A possible naming convention for a ScalarConstraint object representing an interpolation condition related to the convexity of f between two Vector objects x_0 and x_1 is {f.tag}_convex:{x_0.tag},{x_1.tag}. A possible naming convention for a ScalarConstraint object representing an interpolation condition related to the Lipschitz Continuity of f between two Vector objects x_0 and x_1 is {f.tag}_LC:{x_0.tag},{x_1.tag}.

Variables:
  • is_basis (bool) – True if this function is not formed through a linear combination of other functions. False otherwise.

  • tags (list[str]) – A list that contains tags that can be used to identify the Function object. Tags should be unique.

  • math_expr (MathExpr) – A MathExpr object with a member variable that contains a mathematical expression represented as a string.

add_tag(tag: str) Function#

Add a new tag for this Function object.

Parameters:

tag (str) – The new tag to be added to the tags list.

Returns:

The instance itself.

func_val(point: Vector) Scalar#

Returns a Scalar object that is the function value of the Function at the given Vector.

Parameters:

point (Vector) – Any Vector.

Returns:

Vector – The function value of the Function at the given Vector.

get_interpolation_constraints_by_group(pep_context: PEPContext | None = None) ConstraintData#

When implemented, structure the types of constraints as a list of related ScalarConstraint or individual PSDConstraint objects.

grad(point: Vector) Vector#

Returns a Vector object that is the gradient of the Function at the given Vector.

This function should be used to return subgradients as well as gradients and subgradients are effectively treated the same in the context of PEP.

Parameters:

point (Vector) – Any Vector.

Returns:

Vector – The gradient of the Function at the given Vector.

Example

>>> import pepflow as pf
>>> ctx = pf.PEPContext("ctx").set_as_current()
>>> x_0 = pf.Vector(is_basis=True, tags=["x_0"])
>>> f = pf.SmoothConvexFunction(is_basis=True, L=1, tags=["f"])
>>> f.grad(x_0)
prox(x: Vector, stepsize: numbers.Number | Parameter, tag: str | None = None) Vector#

Apply the proximal operator on the input \(x\).

Define the proximal operator as

\[\text{prox}_{\gamma f}(x) := \arg\min_u \left\{ \gamma f(u) + \frac{1}{2} \|u - x\|^2 \right\}.\]

This function returns the output Vector \(u\) found from applying the proximal operator with respect to some Function \(f\) on the input Vector \(x\) with stepsize \(\gamma\). Consider the following equivalence relationship:

\[\arg\min_u \left\{ \gamma f(u) + \frac{1}{2} \|u - x\|^2 \right\} \Longleftrightarrow x - u \in \gamma \partial f(u) \Longleftrightarrow u = x - \gamma \widetilde{\nabla} f(u) \text{ where } \widetilde{\nabla} f(u)\in\partial f(u).\]
Parameters:
  • x (Vector) – The input point.

  • stepsize (numbers.Number | Parameter) – The stepsize.

  • tag (str | None) – By default set to None. Pass a tag to add to the output of the proximal operator applied the input point.

Returns:

Vector – The output of the proximal operator applied on x.

Note

For children of Function for which the proximal operator is not defined, overwrite the function to raise NotImplemented.

set_stationary_point(name: str) Vector#

Return a stationary point for this Function object.

A Function object can only have one stationary point.

Parameters:

name (str) – The tag for the Vector object which will serve as the stationary point.

Returns:

Vector – The stationary point for this Function object.

Example

>>> import pepflow as pf
>>> f = pf.SmoothConvexFunction(is_basis=True, tags=["f"], L=1)
>>> ctx = pf.PEPContext("ctx").set_as_current()
>>> f.set_stationary_point("x_star")
property tag#

Returns the most recently added tag.

Returns:

str – The most recently added tag of this Function object.

Triplet#

class pepflow.Triplet(point: Vector, func_val: Scalar, grad: Vector, func: Function, name: str | None)#

A data class that represents, for some given function \(f\), the tuple \(\{x, f(x), \nabla f(x)\}\).

Subgradients \(\widetilde{\nabla} f(x)\) are represented by gradients as they are effectively treated the same in the context of PEP.

Variables:
  • point (Vector) – A vector \(x\).

  • func_val (Scalar) – The function value \(f(x)\).

  • grad (Vector) – The gradient \(\nabla f(x)\) or a subgradient \(\widetilde{\nabla} f(x)\).

  • name (str) – The unique name of the Triplet object.

expand() tuple[Vector, Scalar, Vector]#

Return the point, func_value, and grad member variables of a Triplet as a tuple.

Convex#

class pepflow.ConvexFunction(*, is_basis: bool, composition: AddedFunc | ScaledFunc | None = None, tags: list[str] = NOTHING, math_expr: MathExpr = NOTHING)#

Bases: Function

The ConvexFunction class represents a closed, convex, and proper (CCP) function, i.e., a convex function whose epigraph is a non-empty closed set.

The ConvexFunction class is a child of Function.

A CCP function typically has no parameters. We can instantiate a ConvexFunction object as follows:

Example

>>> import pepflow as pf
>>> f = pf.ConvexFunction(is_basis=True, tags=["f"])
get_interpolation_constraints_by_group(pep_context: PEPContext | None = None) ConstraintData#

Return a ConstraintData object that manages the function’s groups of interpolation conditions.

interp_ineq(p1: Vector | str, p2: Vector | str, pep_context: PEPContext | None = None, sympy_mode: bool = False) Scalar#

Generate the interpolation inequality Scalar object between two Vector objects through the objects themselves or their tags.

The interpolation inequality between two points \(p_1, p_2\) for a CCP function \(f\) is

\[f(p_2) - f(p_1) + \langle \widetilde{\nabla} f(p_2), p_1 - p_2 \rangle,\]

where \(\widetilde{\nabla} f(p_2) \in\partial f(p_2)\).

References

A. B. Taylor, J. M. Hendrickx, and F. Glineur. Smooth strongly convex interpolation and exact worst-case performance of first-order methods. Mathematical Programming, 161(1-2):307–345, 2017.

Parameters:

Example

>>> import pepflow as pf
>>> ctx = pf.PEPContext("ctx").set_as_current()
>>> xi = pf.Vector(is_basis=True, tags=["x_i"])
>>> xj = pf.Vector(is_basis=True, tags=["x_j"])
>>> f = pf.ConvexFunction(is_basis=True, L=1, tags=["f"])
>>> fi, fj = f(xi), f(xj)
>>> f.interp_ineq("x_i", "x_j")

Smooth and Convex#

class pepflow.SmoothConvexFunction(*, is_basis: bool, composition: AddedFunc | ScaledFunc | None = None, tags: list[str] = NOTHING, math_expr: MathExpr = NOTHING, L: NUMERICAL_TYPE | Parameter)#

Bases: Function

The SmoothConvexFunction class represents a smooth, convex function.

The SmoothConvexFunction class is a child of Function.

A smooth, convex function has a smoothness parameter \(L\). We can instantiate a SmoothConvexFunction object as follows:

Example

>>> import pepflow as pf
>>> f = pf.SmoothConvexFunction(is_basis=True, tags=["f"], L=1)
get_interpolation_constraints_by_group(pep_context: PEPContext | None = None) ConstraintData#

Return a ConstraintData object that manages the function’s groups of interpolation conditions.

interp_ineq(p1: Vector | str, p2: Vector | str, pep_context: PEPContext | None = None, sympy_mode: bool = False) Scalar#

Generate the interpolation inequality Scalar object between two Vector objects through the objects themselves or their tags.

The interpolation inequality between two points \(p_1, p_2\) for a smooth, convex function \(f\) is

\[f(p_2) - f(p_1) + \langle \nabla f(p_2), p_1 - p_2 \rangle + \tfrac{1}{2} \lVert \nabla f(p_1) - \nabla f(p_2) \rVert^2.\]

References

A. B. Taylor, J. M. Hendrickx, and F. Glineur. Smooth strongly convex interpolation and exact worst-case performance of first-order methods. Mathematical Programming, 161(1-2):307–345, 2017.

Parameters:

Example

>>> import pepflow as pf
>>> ctx = pf.PEPContext("ctx").set_as_current()
>>> xi = pf.Vector(is_basis=True, tags=["x_i"])
>>> xj = pf.Vector(is_basis=True, tags=["x_j"])
>>> f = pf.SmoothConvexFunction(is_basis=True, L=1, tags=["f"])
>>> fi, fj = f(xi), f(xj)
>>> f.interp_ineq("x_i", "x_j")