Contributing

PEPit is designed for allowing users to easily contribute to add new features to the package. Classes of functions (or operators) as well as black-box oracles can be implemented by following the canvas from respectively PEPit/functions/ (or PEPit/operators/ and PEPit/primitive_steps/).

We encourage authors of research papers presenting novel optimization methods and/or a novel convergence results to submit the corresponding PEPit files in the directory PEPit/examples/.

General guidelines

We kindly ask you follow common guidelines, namely that the provided code:

  • sticks as much as possible to the PEP8 convention.

  • is commented with Google style docstring.

  • is well covered by tests.

  • is aligned with the documentation.

  • is also mentioned in the whatsnew section of the documentation.

Adding a new function or operator class

To add a new function / operator class, please follow the format used for the other function / operator classes.

In particular:

  • your class must inherit from the class Function and overwrite its add_class_constraints method.

  • the docstring must be complete. In particular, it must contains the list of attributes and arguments as well as an example of usage via the declare_function method of the class PEP. It must also contain a clickable reference to the paper introducing it.

Adding a step / an oracle

To add a new oracle / step, please add a new file containing the oracle function in PEPit/primitive_steps.

Remark that transforming the mathematical formulation of an oracle into its PEP equivalent may require additional tricks, see e.g. PEPit/primitive_steps/proximal_step.py, or PEPit/primitive_steps/linear_optimization_step.py.

Please make sure that your docstring contains the mathematical derivation of the latest from the previous.

Adding a new method as an example

We don’t require a specific code format for a new example. However, we ask the associated docstring to be precisely organized as follow:

  • Define Problem solved (introducing function notations and assumptions).

  • Name method in boldface formatting.

  • Introduce performance metric, initial condition and parameters (performance_metric < tau(parameters) initialization).

  • Describe method main step and cite reference with specified algorithm.

  • Provide theoretical result (Upper/Lower/Tight in boldface formatting + performance_metric < theoretical_bound initialization).

  • Reference block containing relevant clickable references (preferably to arxiv with specified version of the paper) in the format: (First name initial letter, last name (YEAR). Title. Journal or conference (Acronym of journal or conference).

  • Args block containing parameters with their type and short description.

  • Returns block containing pepit_tau and theoretical_tau.

  • Example block containing a minimal work example of the coded function.

We provide, in PEPit/examples/example_template.py, a template that can be filled very quickly to help the contributor to share their method easily.

New example template

PEPit.examples.example_template.wc_example_template(arg1, arg2, arg3, wrapper='cvxpy', solver=None, verbose=1)[source]

Consider the CHARACTERISTIC (eg., convex) minimization problem

\[f_\star \triangleq \min_x f(x),\]

where \(f\) is CLASS (eg., smooth convex).

This code computes a worst-case guarantee for the ** NAME OF THE METHOD **. That is, it computes the smallest possible \(\tau(arg_1, arg_2, arg_3)\) such that the guarantee

\[\text{PERFORMANCE METRIC} \leqslant \tau(arg_1, arg_2, arg_3) \text{ INITIALIZATION}\]

is valid, where NOTATION OF THE OUTPUT is the output of the ** NAME OF THE METHOD **, and where \(x_\star\) is the minimizer of \(f\). In short, for given values of ARGUMENTS, \(\tau(arg_1, arg_2, arg_3)\) is computed as the worst-case value of \(\text{PERFORMANCE METRIC}\) when \(\text{INITIALIZATION} \leqslant 1\).

Algorithm: The NAME OF THE METHOD of this example is provided in REFERENCE WITH SPECIFIED ALGORITHM by

\begin{eqnarray} \text{MAIN STEP} \end{eqnarray}

Theoretical guarantee: A TIGHT, UPPER OR LOWER guarantee can be found in REFERENCE WITH SPECIFIED THEOREM:

\[\text{PERFORMANCE METRIC} \leqslant \text{THEORETICAL BOUND} \text{ INITIALIZATION}\]

References:

[1] F. Name, F. Name, F. Name (YEAR). Title. Conference or journal (Acronym of conference or journal).

[2] F. Name, F. Name, F. Name (YEAR). Title. Conference or journal (Acronym of journal or conference).

[3] F. Name, F. Name, F. Name (YEAR). Title. Conference or journal (Acronym of journal or conference).

Parameters:
  • arg1 (type1) – description of arg1.

  • arg2 (type2) – description of arg2.

  • arg3 (type3) – description of arg3.

  • wrapper (str) – the name of the wrapper to be used.

  • solver (str) – the name of the solver the wrapper should use.

  • verbose (int) –

    level of information details to print.

    • -1: No verbose at all.

    • 0: This example’s output.

    • 1: This example’s output + PEPit information.

    • 2: This example’s output + PEPit information + solver details.

Returns:
  • pepit_tau (float) – worst-case value

  • theoretical_tau (float) – theoretical value

Example

>>> pepit_tau, theoretical_tau = wc_example_template(arg1=value1, arg2=value2, arg3=value3, wrapper="cvxpy", solver=None, verbose=1)
``OUTPUT MESSAGE``

New example test template

def test_[NAME_METHOD](self):
    PARAMS = PARAMS

    wc, theory = wc_[NAME_METHOD](PARAMS=PARAMS, verbose=self.verbose)

    # If theoretical upper bound is tight
    self.assertAlmostEqual(theory, wc, delta=self.relative_precision * theory)

    # If theoretical upper bound is not tight
    self.assertLessEqual(wc, theory * (1 + self.relative_precision))

    # If theoretical lower bound is not tight
    self.assertLessEqual(theory, wc * (1 + self.relative_precision))