# ADMMConsensus¶

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.