ADMMConsensus specialises ADMM for solving optimisation problems of the form

$\mathrm{argmin}_{\mathbf{x}} \; \sum_{i = 0}^{N_b - 1} f_i(\mathbf{x}) + g(\mathbf{x})$

via an ADMM problem of the form

$\begin{split}\mathrm{argmin}_{\mathbf{x}_i,\mathbf{y}} \; \sum_{i = 0}^{N_b - 1} f(\mathbf{x}_i) + g(\mathbf{y}) \;\mathrm{such\;that}\; \left( \begin{array}{c} \mathbf{x}_0 \\ \mathbf{x}_1 \\ \vdots \end{array} \right) = \left( \begin{array}{c} I \\ I \\ \vdots \end{array} \right) \mathbf{y} \;\;.\end{split}$

See ConvCnstrMOD_Consensus as an example of a class derived from ADMMConsensus, or see the simple usage example.

Classes derived from ADMMConsensus should override/define the methods and attributes in the following sections.

Initialisation¶

The __init__ method of the derived class should call the ADMMConsensus __init__ method to ensure proper initialisation. Note that this method assumes that the ADMM consensus component blocks in working variable $$\mathbf{x}$$ will be stacked on the final array index, and defines attribute self.xshape accordingly.

State variables $$\mathbf{y}$$ and $$\mathbf{u}$$ are initialised to zero by inherited methods ADMM.yinit and ADMM.uinit respectively (this behaviour is inherited from ADMM). These methods should be overridden if a different initialization is desired.

Update Steps¶

The $$\mathbf{x}$$ update method ADMMConsensus.xstep calls ADMMConsensus.xistep for each ADMM consensus component block. In most cases a derived class will define ADMMConsensus.xistep rather than override ADMMConsensus.xstep. Method ADMMConsensus.xistep should solve

$\mathbf{x}_i^{(j+1)} = \mathrm{argmin}_{\mathbf{x}_i} \;\; f_i(\mathbf{x}_i) + \frac{\rho}{2} \left\| \mathbf{x}_i - \left( \mathbf{y}^{(j)} - \mathbf{u}_i^{(j)} \right) \right\|_2^2$

setting a slice of self.X on the final index from the result.

The $$\mathbf{y}$$ update method ADMMConsensus.ystep solves

$\mathbf{y}^{(j+1)} = \mathrm{argmin}_{\mathbf{y}} \;\; g(\mathbf{y}) + \frac{N_b \rho}{2} \left\| \mathbf{y} - \mathbf{z}^{(j)} \right\|_2^2$

where

$\mathbf{z}^{(j)} = \sum_{i = 0}^{N_b - 1} \left( \mathbf{x}_i^{(j+1)} + \mathbf{u}_i^{(j)} \right) \;.$

A class derived from ADMMConsensus should override ADMMConsensus.prox_g to implement the proximal operator of $$g(\cdot)$$. Note that $$N_b \rho$$ is passed as a parameter to ADMMConsensus.prox_g; it is the responsibility of the implementer of this method to understand that it implements what is in mathematical terms the proximal operator of $$g(\cdot)$$ with parameter $$(N_b \rho)^{-1}$$.

The dual variable update is

$\mathbf{u}_i^{(j+1)} = \mathbf{u}_i^{(j)} + \mathbf{x}_i^{(j+1)} - \mathbf{y}^{(j+1)} \;.$

This update is implemented in ADMM.ustep, which will usually not need to be overridden.

As in ADMM, if one of the update steps makes use of pre-computed values that depend on the penalty parameter self.rho, ADMM.rhochange should be with a method that updates these pre-computed values.

Constraint Definition¶

Class ADMMConsensus overrides all of the methods in Residual Evaluation and does not define any of the ADMM constraint definition methods discussed in Constraint Definition.

Residual Evaluation¶

The residual evaluation methods ADMMConsensus.rsdl_r, ADMMConsensus.rsdl_s, ADMMConsensus.rsdl_rn, ADMMConsensus.rsdl_sn are all appropriately defined for a general ADMM consensus problem, and will typically not need to be overridden.

Iteration Statistics¶

The iteration statistics mechanism, as described in Iteration Statistics, is inherited largely unchanged from ADMM. The only exception is that ADMMConsensus.obfn_f is defined to evaluate the sum over class for each ADMM consensus block to ADMMConsensus.obfn_fi, which should be overridden in a derived class if it is desired to use this simple iteration statistics mechanism rather than override ADMM.eval_objfn.