# 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

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`

.