Пример #1
0
def par_xstep(i):
    r"""Minimise Augmented Lagrangian with respect to
    :math:`\mathbf{x}_{G_i}`, one of the disjoint problems of optimizing
    :math:`\mathbf{x}`.

    Parameters
    ----------
    i : int
      Index of grouping to update

    """
    global mp_X
    global mp_DX
    YU0f = rfftn(mp_Y0[[i]] - mp_U0[[i]], mp_Nv, mp_axisN)
    YU1f = rfftn(mp_Y1[mp_grp[i]:mp_grp[i+1]] -
                    1/mp_alpha*mp_U1[mp_grp[i]:mp_grp[i+1]], mp_Nv, mp_axisN)
    if mp_Cd == 1:
        b = np.conj(mp_Df[mp_grp[i]:mp_grp[i+1]]) * YU0f + mp_alpha**2*YU1f
        Xf = sl.solvedbi_sm(mp_Df[mp_grp[i]:mp_grp[i+1]], mp_alpha**2, b,
                            mp_cache[i], axis=mp_axisM)
    else:
        b = sl.inner(np.conj(mp_Df[mp_grp[i]:mp_grp[i+1]]), YU0f,
                     axis=mp_C) + mp_alpha**2*YU1f
        Xf = sl.solvemdbi_ism(mp_Df[mp_grp[i]:mp_grp[i+1]], mp_alpha**2, b,
                              mp_axisM, mp_axisC)
    mp_X[mp_grp[i]:mp_grp[i+1]] = irfftn(Xf, mp_Nv,
                                            mp_axisN)
    mp_DX[i] = irfftn(sl.inner(mp_Df[mp_grp[i]:mp_grp[i+1]], Xf,
                                  mp_axisM), mp_Nv, mp_axisN)
Пример #2
0
def ccmodmd_xstep(k):
    """Do the X step of the ccmod stage. The only parameter is the slice
    index `k` and there are no return values; all inputs and outputs are
    from and to global variables.
    """

    YU0 = mp_D_Y0 - mp_D_U0[k]
    YU1 = mp_D_Y1[k] + mp_S[k] - mp_D_U1[k]
    b = rfftn(YU0, None, mp_cri.axisN) + \
      np.conj(mp_Zf[k]) * rfftn(YU1, None, mp_cri.axisN)
    Xf = sl.solvedbi_sm(mp_Zf[k], 1.0, b, axis=mp_cri.axisM)
    mp_D_X[k] = irfftn(Xf, mp_cri.Nv, mp_cri.axisN)
    mp_DX[k] = irfftn(sl.inner(Xf, mp_Zf[k]), mp_cri.Nv, mp_cri.axisN)
Пример #3
0
    def eval_objfn(self):
        """Compute components of objective function as well as total
        contribution to objective function.
        """

        Xf = self.Xf
        Ef = self.Gf * Xf - self.Sf
        dfd = np.sum((irfftn(Ef, self.S.shape, axes=self.axes))**2) / 2.0
        reg = np.sum(
            irfftn(self.Df * Xf[..., np.newaxis], self.S.shape,
                   axes=self.axes)**2)
        obj = dfd + self.lmbda * reg
        cns = np.linalg.norm(self.X - self.cnstr_proj(self.X))
        return (obj, dfd, reg, cns)
Пример #4
0
    def xstep(self, gradf=None):
        """Compute proximal update (gradient descent + constraint).
        Variables are mapped back and forth between input and
        frequency domains. Optionally, a monotone PGM version from
        :cite:`beck-2009-tv` is available.
        """

        if gradf is None:
            gradf = self.grad_f()

        if self.stepsizepolicy is not None:
            if self.k > 1:
                self.L = self.stepsizepolicy.update(self, gradf)
            if isinstance(self.stepsizepolicy, StepSizePolicyBB):
                # BB variants are two-point methods
                self.stepsizepolicy.store_prev_state(self.Xf, gradf)

        self.Vf[:] = self.Yf - (1. / self.L) * gradf
        V = irfftn(self.Vf, self.Nv, self.axisN)

        self.X[:] = self.prox_g(V)
        self.Xf = rfftn(self.X, None, self.axisN)

        if self.opt['Monotone'] and self.k > 0:
            self.ZZf = self.Xf.copy()
            self.objfn = self.eval_objfn()
            if self.objfn_prev[0] < self.objfn[0]:
                # If increment on objective function
                # revert to previous iterate
                self.Xf = self.Xfprv.copy()
                self.objfn = self.objfn_prev

        return gradf
Пример #5
0
    def xstep(self):
        r"""Minimise Augmented Lagrangian with respect to
        :math:`\mathbf{x}`.
        """

        self.YU[:] = self.Y - self.U
        self.block_sep0(self.YU)[:] += self.S
        Zf = rfftn(self.YU, None, self.cri.axisN)
        Z0f = self.block_sep0(Zf)
        Z1f = self.block_sep1(Zf)

        DZ0f = np.conj(self.Df) * Z0f
        DZ0fBQ = dot(self.B.dot(self.Q).T, DZ0f, axis=self.cri.axisC)
        Z1fQ = dot(self.Q.T, Z1f, axis=self.cri.axisC)
        b = DZ0fBQ + Z1fQ

        Xh = solvedbd_sm(self.gDf, (self.mu / self.rho) * self.GHGf + 1.0,
                         b,
                         self.c,
                         axis=self.cri.axisM)
        self.Xf[:] = dot(self.Q, Xh, axis=self.cri.axisC)
        self.X = irfftn(self.Xf, self.cri.Nv, self.cri.axisN)

        if self.opt['LinSolveCheck']:
            DDXf = np.conj(self.Df) * inner(
                self.Df, self.Xf, axis=self.cri.axisM)
            DDXfBB = dot(self.B.T.dot(self.B), DDXf, axis=self.cri.axisC)
            ax = self.rho * (DDXfBB + self.Xf) + \
                 self.mu * self.GHGf * self.Xf
            b = self.rho * (dot(self.B.T, DZ0f, axis=self.cri.axisC) + Z1f)
            self.xrrs = rrs(ax, b)
        else:
            self.xrrs = None
Пример #6
0
    def xstep(self):
        r"""Minimise Augmented Lagrangian with respect to
        :math:`\mathbf{x}`."""

        self.YU[:] = self.Y - self.U
        YUf = rfftn(self.YU, None, self.cri.axisN)

        # The sum is over the extra axis indexing spatial gradient
        # operators G_i, *not* over axisM
        b = self.DSf + self.rho * (YUf[..., -1] + self.Wtv * np.sum(
            np.conj(self.Gf) * YUf[..., 0:-1], axis=-1))

        if self.cri.Cd == 1:
            self.Xf[:] = sl.solvedbi_sm(self.Df,
                                        self.rho * self.GHGf + self.rho, b,
                                        self.c, self.cri.axisM)
        else:
            self.Xf[:] = sl.solvemdbi_ism(self.Df,
                                          self.rho * self.GHGf + self.rho, b,
                                          self.cri.axisM, self.cri.axisC)

        self.X = irfftn(self.Xf, self.cri.Nv, self.cri.axisN)

        if self.opt['LinSolveCheck']:
            Dop = lambda x: sl.inner(self.Df, x, axis=self.cri.axisM)
            if self.cri.Cd == 1:
                DHop = lambda x: np.conj(self.Df) * x
            else:
                DHop = lambda x: sl.inner(
                    np.conj(self.Df), x, axis=self.cri.axisC)
            ax = DHop(Dop(
                self.Xf)) + (self.rho * self.GHGf + self.rho) * self.Xf
            self.xrrs = sl.rrs(ax, b)
        else:
            self.xrrs = None
Пример #7
0
    def cnst_A1T(self, Y1):
        r"""Compute :math:`A_1^T \mathbf{y}_1` component of
        :math:`A^T \mathbf{y}`. In this case :math:`A_1^T \mathbf{y}_1 =
        (\Gamma_0^T \;\; \Gamma_1^T \;\; \ldots) \mathbf{y}_1`.
        """

        Y1f = rfftn(Y1, None, axes=self.cri.axisN)
        return irfftn(np.conj(self.GDf) * Y1f, self.cri.Nv, self.cri.axisN)
Пример #8
0
    def reconstruct(self, X=None):
        """Reconstruct representation."""

        if X is None:
            X = self.X
        Xf = rfftn(X, None, self.cri.axisN)
        Sf = np.sum(self.Df * Xf, axis=self.cri.axisM)
        return irfftn(Sf, self.cri.Nv, self.cri.axisN)
Пример #9
0
    def cnst_A(self, X, Xf=None):
        r"""Compute :math:`A \mathbf{x}` component of ADMM problem
        constraint.  In this case :math:`A \mathbf{x} = (G_r^T \;\;
        G_c^T)^T \mathbf{x}`.
        """

        if Xf is None:
            Xf = rfftn(X, axes=self.axes)
        return irfftn(self.Gf * Xf[..., np.newaxis], self.axsz, axes=self.axes)
Пример #10
0
    def cnst_AT(self, X):
        r"""Compute :math:`A^T \mathbf{x}` where :math:`A \mathbf{x}` is
        a component of ADMM problem constraint. In this case
        :math:`A^T \mathbf{x} = (G_r^T \;\; G_c^T) \mathbf{x}`.
        """

        Xf = rfftn(X, axes=self.axes)
        return np.sum(irfftn(np.conj(self.Gf) * Xf, self.axsz, axes=self.axes),
                      axis=self.Y.ndim - 1)
Пример #11
0
 def obfn_dfd(self):
     r"""Compute data fidelity term :math:`(1/2) \| W \left( \sum_m
     \mathbf{d}_m * \mathbf{x}_m - \mathbf{s} \right) \|_2^2`.
     """
     XF = rfftn(self.obfn_fvar(), mp_Nv, mp_axisN)
     DX = np.moveaxis(irfftn(sl.inner(mp_Df, XF, mp_axisM),
                                mp_Nv, mp_axisN), mp_axisM,
                      self.cri.axisM)
     return np.sum((self.W*(DX-self.S))**2)/2.0
Пример #12
0
    def obfn_dfd(self):
        r"""Compute data fidelity term :math:`(1/2) \| W \left( \sum_m
        \mathbf{d}_m * \mathbf{x}_m - \mathbf{s} \right) \|_2^2`.
        """

        Ef = sl.inner(self.Zf, self.obfn_fvarf(), axis=self.cri.axisM) \
          - self.Sf
        return (np.linalg.norm(
            self.W * irfftn(Ef, self.cri.Nv, self.cri.axisN))**2) / 2.0
Пример #13
0
    def obfn_dfd(self):
        r"""Compute data fidelity term :math:`(1/2) \| W (\sum_m
        \mathbf{d}_m * \mathbf{x}_{m} - \mathbf{s}) \|_2^2`
        """

        Ef = self.eval_Rf(self.Xf)
        E = irfftn(Ef, self.cri.Nv, self.cri.axisN)

        return (np.linalg.norm(self.W * E)**2) / 2.0
Пример #14
0
    def ystep(self):
        r"""Minimise Augmented Lagrangian with respect to
        :math:`\mathbf{y}`."""

        if (self.Wg is None or self.mu == 0) and self.gamma == 0:
            # Skip unnecessary inhibition steps and run standard CBPDN
            super(ConvBPDNInhib, self).ystep()

        else:
            # Perform soft-thresholding step of Y subproblem using l1 weights
            self.Y = sp.prox_l1(self.AX + self.U,
                                (self.lmbda * self.wl1 + self.mu * self.wml +
                                 self.gamma * self.wms) / self.rho)

            # Compute the frequency domain representation of the
            # magnitude of X
            Xaf = rfftn(np.abs(self.X), self.cri.Nv, self.cri.axisN)

            if self.mu > 0 and self.Wg is not None:
                # Update previous lateral inhibition term
                self.wml_prev = self.wml
                # Convolve the lateral spatial weighting matrix with the
                # magnitude of X
                WhXal = irfftn(self.Whfl * Xaf, self.cri.Nv, self.cri.axisN)
                # Sum the weights across in-group members for each element
                self.wml = np.dot(np.dot(WhXal, self.Wg.T),
                                  self.Wg) - np.sum(self.Wg, axis=0) * WhXal
                # Smooth lateral inhibition term
                self.wml = self.smooth * self.wml_prev + \
                    (1 - self.smooth) * self.wml

            if self.gamma > 0:
                # Update previous self inhibition term
                self.wms_prev = self.wms
                # Convolve the self spatial weighting matrix with the
                # magnitude of X
                self.wms = irfftn(
                    self.Whfs * Xaf, self.cri.Nv, self.cri.axisN)
                # Smooth self inhibition term
                self.wms = self.smooth * self.wms_prev + \
                    (1 - self.smooth) * self.wms

            # Handle negative coefficients and boundary crossings
            super(cbpdn.ConvBPDN, self).ystep()
Пример #15
0
    def reconstruct(self, D=None):
        """Reconstruct representation."""

        if D is None:
            Df = self.Xf
        else:
            Df = rfftn(D, None, self.cri.axisN)

        Sf = np.sum(self.Zf * Df, axis=self.cri.axisM)
        return irfftn(Sf, self.cri.Nv, self.cri.axisN)
Пример #16
0
    def xstep(self):
        r"""Minimise Augmented Lagrangian with respect to :math:`\mathbf{x}`.
        """

        self.YU[:] = self.Y - self.U
        b = self.ZSf + self.rho * rfftn(self.YU, None, self.cri.axisN)
        self.Xf[:] = sl.solvemdbi_ism(self.Zf, self.rho, b, self.cri.axisM,
                                      self.cri.axisK)
        self.X = irfftn(self.Xf, self.cri.Nv, self.cri.axisN)
        self.xstep_check(b)
Пример #17
0
    def cnst_A0T(self, X):
        r"""Compute :math:`A_0^T \mathbf{x}` where :math:`A_0 \mathbf{x}`
        is a component of the ADMM problem constraint. In this case
        :math:`A_0^T \mathbf{x} = (\Gamma_0^T \;\; \Gamma_1^T \;\; \ldots )
        \mathbf{x}`.
        """

        Xf = rfftn(X, axes=self.cri.axisN)
        return self.Wtv[..., np.newaxis] * irfftn(
            np.conj(self.Gf) * Xf[..., 0:-1], self.cri.Nv, axes=self.cri.axisN)
Пример #18
0
    def cnst_A0(self, X, Xf=None):
        r"""Compute :math:`A_0 \mathbf{x}` component of ADMM problem
        constraint. In this case :math:`A_0 \mathbf{x} = (\Gamma_0^T \;\;
        \Gamma_1^T \;\; \ldots )^T \mathbf{x}`.
        """

        if Xf is None:
            Xf = rfftn(X, axes=self.cri.axisN)
        return self.Wtv[..., np.newaxis] * irfftn(
            self.Gf * Xf[..., np.newaxis], self.cri.Nv, axes=self.cri.axisN)
Пример #19
0
def ccmod_xstep(k):
    """Do the X step of the ccmod stage. The only parameter is the slice
    index `k` and there are no return values; all inputs and outputs are
    from and to global variables.
    """

    YU = mp_D_Y - mp_D_U[k]
    b = mp_ZSf[k] + mp_drho * rfftn(YU, None, mp_cri.axisN)
    Xf = sl.solvedbi_sm(mp_Zf[k], mp_drho, b, axis=mp_cri.axisM)
    mp_D_X[k] = irfftn(Xf, mp_cri.Nv, mp_cri.axisN)
Пример #20
0
def cbpdnmd_xstep(k):
    """Do the X step of the cbpdn stage. The only parameter is the slice
    index `k` and there are no return values; all inputs and outputs are
    from and to global variables.
    """

    YU0 = mp_Z_Y0[k] + mp_S[k] - mp_Z_U0[k]
    YU1 = mp_Z_Y1[k] - mp_Z_U1[k]
    if mp_cri.Cd == 1:
        b = np.conj(mp_Df) * rfftn(YU0, None, mp_cri.axisN) + \
            rfftn(YU1, None, mp_cri.axisN)
        Xf = sl.solvedbi_sm(mp_Df, 1.0, b, axis=mp_cri.axisM)
    else:
        b = sl.inner(np.conj(mp_Df), rfftn(YU0, None, mp_cri.axisN),
                      axis=mp_cri.axisC) + \
            rfftn(YU1, None, mp_cri.axisN)
        Xf = sl.solvemdbi_ism(mp_Df, 1.0, b, mp_cri.axisM, mp_cri.axisC)
    mp_Z_X[k] = irfftn(Xf, mp_cri.Nv, mp_cri.axisN)
    mp_DX[k] = irfftn(sl.inner(mp_Df, Xf), mp_cri.Nv, mp_cri.axisN)
Пример #21
0
    def cnst_A0T(self, Y0):
        r"""Compute :math:`A_0^T \mathbf{y}_0` component of
        :math:`A^T \mathbf{y}` (see :meth:`.ADMMTwoBlockCnstrnt.cnst_AT`).
        """

        # This calculation involves non-negligible computational cost. It
        # should be possible to disable relevant diagnostic information
        # (dual residual) to avoid this cost.
        Y0f = rfftn(Y0, None, self.cri.axisN)
        return irfftn(sl.inner(np.conj(self.Zf), Y0f, axis=self.cri.axisK),
                      self.cri.Nv, self.cri.axisN)
Пример #22
0
    def compute_residuals(self):
        """Compute residuals and stopping thresholds. The parent class
        method is overridden to ensure that the residual calculations
        include the additional variables introduced in the modification
        to the baseline algorithm.
        """

        # The full primary residual is straightforward to compute from
        # the primary residuals for the baseline algorithm and for the
        # additional variables
        r0 = self.rsdl_r(self.AXnr, self.Y)
        r1 = self.AX1nr - self.Y1 - self.S
        r = np.sqrt(np.sum(r0**2) + np.sum(r1**2))

        # The full dual residual is more complicated to compute than the
        # full primary residual
        ATU = self.swapaxes(self.U) + irfftn(
            np.conj(self.Zf) * rfftn(self.U1, self.cri.Nv, self.cri.axisN),
            self.cri.Nv, self.cri.axisN)
        s = self.rho * np.linalg.norm(ATU)

        # The normalisation factor for the full primal residual is also not
        # straightforward
        nAX = np.sqrt(
            np.linalg.norm(self.AXnr)**2 + np.linalg.norm(self.AX1nr)**2)
        nY = np.sqrt(np.linalg.norm(self.Y)**2 + np.linalg.norm(self.Y1)**2)
        rn = max(nAX, nY, np.linalg.norm(self.S))

        # The normalisation factor for the full dual residual is
        # straightforward to compute
        sn = self.rho * np.sqrt(
            np.linalg.norm(self.U)**2 + np.linalg.norm(self.U1)**2)

        # Final residual values and stopping tolerances depend on
        # whether standard or normalised residuals are specified via the
        # options object
        if self.opt['AutoRho', 'StdResiduals']:
            epri = np.sqrt(self.Nc)*self.opt['AbsStopTol'] + \
                rn*self.opt['RelStopTol']
            edua = np.sqrt(self.Nx)*self.opt['AbsStopTol'] + \
                sn*self.opt['RelStopTol']
        else:
            if rn == 0.0:
                rn = 1.0
            if sn == 0.0:
                sn = 1.0
            r /= rn
            s /= sn
            epri = np.sqrt(self.Nc)*self.opt['AbsStopTol']/rn + \
                self.opt['RelStopTol']
            edua = np.sqrt(self.Nx)*self.opt['AbsStopTol']/sn + \
                self.opt['RelStopTol']

        return r, s, epri, edua
Пример #23
0
    def cnst_A1(self, X, Xf=None):
        r"""Compute :math:`A_1 \mathbf{x}` component of ADMM problem
        constraint. In this case :math:`A_1 \mathbf{x} = (\Gamma_0^T \;\;
        \Gamma_1^T \;\; \ldots )^T \mathbf{x}`.
        """

        if Xf is None:
            Xf = rfftn(X, axes=self.cri.axisN)
        return irfftn(
            sl.inner(self.GDf, Xf[..., np.newaxis], axis=self.cri.axisM),
            self.cri.Nv, self.cri.axisN)
Пример #24
0
    def reconstruct(self, D=None, X=None):
        """Reconstruct representation."""

        if D is None:
            D = self.getdict(crop=False)
        if X is None:
            X = self.getcoef()
        Df = rfftn(D, self.xstep.cri.Nv, self.xstep.cri.axisN)
        Xf = rfftn(X, self.xstep.cri.Nv, self.xstep.cri.axisN)
        DXf = inner(Df, Xf, axis=self.xstep.cri.axisM)
        return irfftn(DXf, self.xstep.cri.Nv, self.xstep.cri.axisN)
Пример #25
0
    def cnst_A0(self, X, Xf=None):
        r"""Compute :math:`A_0 \mathbf{x}` component of ADMM problem
        constraint.
        """

        if Xf is None:
            Xf = rfftn(X, None, self.cri.axisN)
        return irfftn(
            dot(self.B,
                inner(self.Df, Xf, axis=self.cri.axisM),
                axis=self.cri.axisC), self.cri.Nv, self.cri.axisN)
Пример #26
0
    def cnst_A0(self, X, Xf=None):
        r"""Compute :math:`A_0 \mathbf{x}` component of ADMM problem
        constraint.
        """

        # This calculation involves non-negligible computational cost
        # when Xf is None (i.e. the function is not being applied to
        # self.X).
        if Xf is None:
            Xf = rfftn(X, None, self.cri.axisN)
        return irfftn(sl.inner(self.Zf, Xf, axis=self.cri.axisM), self.cri.Nv,
                      self.cri.axisN)
Пример #27
0
def tikhonov_filter(s, lmbda, npd=16):
    r"""Lowpass filter based on Tikhonov regularization.

    Lowpass filter image(s) and return low and high frequency
    components, consisting of the lowpass filtered image and its
    difference with the input image. The lowpass filter is equivalent to
    Tikhonov regularization with `lmbda` as the regularization parameter
    and a discrete gradient as the operator in the regularization term,
    i.e. the lowpass component is the solution to

    .. math::
      \mathrm{argmin}_\mathbf{x} \; (1/2) \left\|\mathbf{x} - \mathbf{s}
      \right\|_2^2 + (\lambda / 2) \sum_i \| G_i \mathbf{x} \|_2^2 \;\;,

    where :math:`\mathbf{s}` is the input image, :math:`\lambda` is the
    regularization parameter, and :math:`G_i` is an operator that
    computes the discrete gradient along image axis :math:`i`. Once the
    lowpass component :math:`\mathbf{x}` has been computed, the highpass
    component is just :math:`\mathbf{s} - \mathbf{x}`.

    Parameters
    ----------
    s : array_like
      Input image or array of images.
    lmbda : float
      Regularization parameter controlling lowpass filtering.
    npd : int, optional (default=16)
      Number of samples to pad at image boundaries.

    Returns
    -------
    slp : array_like
      Lowpass image or array of images.
    shp : array_like
      Highpass image or array of images.
    """

    grv = np.array([-1.0, 1.0]).reshape([2, 1])
    gcv = np.array([-1.0, 1.0]).reshape([1, 2])
    Gr = rfftn(grv, (s.shape[0] + 2 * npd, s.shape[1] + 2 * npd), (0, 1))
    Gc = rfftn(gcv, (s.shape[0] + 2 * npd, s.shape[1] + 2 * npd), (0, 1))
    A = 1.0 + lmbda * (np.conj(Gr) * Gr + np.conj(Gc) * Gc).real
    if s.ndim > 2:
        A = A[(slice(None), ) * 2 + (np.newaxis, ) * (s.ndim - 2)]
    sp = np.pad(s, ((npd, npd), ) * 2 + ((0, 0), ) * (s.ndim - 2), 'symmetric')
    spshp = sp.shape
    sp = rfftn(sp, axes=(0, 1))
    sp /= A
    sp = irfftn(sp, s=spshp[0:2], axes=(0, 1))
    slp = sp[npd:(sp.shape[0] - npd), npd:(sp.shape[1] - npd)]
    shp = s - slp
    return slp.astype(s.dtype), shp.astype(s.dtype)
Пример #28
0
def cbpdn_xstep(k):
    """Do the X step of the cbpdn stage. The only parameter is the slice
    index `k` and there are no return values; all inputs and outputs are
    from and to global variables.
    """

    YU = mp_Z_Y[k] - mp_Z_U[k]
    b = mp_DSf[k] + mp_xrho * rfftn(YU, None, mp_cri.axisN)
    if mp_cri.Cd == 1:
        Xf = sl.solvedbi_sm(mp_Df, mp_xrho, b, axis=mp_cri.axisM)
    else:
        Xf = sl.solvemdbi_ism(mp_Df, mp_xrho, b, mp_cri.axisM, mp_cri.axisC)
    mp_Z_X[k] = irfftn(Xf, mp_cri.Nv, mp_cri.axisN)
Пример #29
0
    def xstep(self):
        r"""Minimise Augmented Lagrangian with respect to :math:`\mathbf{x}`.
        """

        self.cgit = None
        self.YU[:] = self.Y - self.U
        b = self.ZSf + self.rho * rfftn(self.YU, None, self.cri.axisN)
        self.Xf[:], cgit = sl.solvemdbi_cg(self.Zf, self.rho, b,
                                           self.cri.axisM, self.cri.axisK,
                                           self.opt['CG', 'StopTol'],
                                           self.opt['CG', 'MaxIter'], self.Xf)
        self.cgit = cgit
        self.X = irfftn(self.Xf, self.cri.Nv, self.cri.axisN)
        self.xstep_check(b)
Пример #30
0
    def xistep(self, i):
        r"""Minimise Augmented Lagrangian with respect to :math:`\mathbf{x}`
        component :math:`\mathbf{x}_i`.
        """

        self.YU[:] = self.Y - self.U[..., i]
        b = np.take(self.ZSf, [i], axis=self.cri.axisK) + \
            self.rho*rfftn(self.YU, None, self.cri.axisN)

        self.Xf[..., i] = sl.solvedbi_sm(np.take(self.Zf, [i],
                                                 axis=self.cri.axisK),
                                         self.rho,
                                         b,
                                         axis=self.cri.axisM)
        self.X[..., i] = irfftn(self.Xf[..., i], self.cri.Nv, self.cri.axisN)