Exemple #1
0
    def _update(self):
        with self.device:
            if self.accelerate or self.proxg is not None:
                backend.copyto(self.x_old, self.x)

            if self.accelerate:
                backend.copyto(self.x, self.z)

            gradf_x = self.gradf(self.x)

            util.axpy(self.x, -self.alpha, gradf_x)

            if self.proxg is not None:
                backend.copyto(self.x, self.proxg(self.alpha, self.x))

            if self.accelerate:
                t_old = self.t
                self.t = (1 + (1 + 4 * t_old**2)**0.5) / 2
                backend.copyto(
                    self.z,
                    self.x + (t_old - 1) / self.t * (self.x - self.x_old))

            xp = self.device.xp
            if self.accelerate or self.proxg is not None:
                self.resid = util.asscalar(
                    xp.linalg.norm((self.x - self.x_old) / self.alpha**0.5))
            else:
                self.resid = util.asscalar(xp.linalg.norm(gradf_x))
Exemple #2
0
 def _update(self):
     y = self.A(self.x)
     device = backend.get_device(y)
     xp = device.xp
     with device:
         self.max_eig = util.asscalar(xp.linalg.norm(y))
         backend.copyto(self.x, y / self.max_eig)
Exemple #3
0
    def __init__(self, A, b, x, P=None, max_iter=100, tol=0):
        self.A = A
        self.P = P
        self.x = x
        self.tol = tol
        self.device = backend.get_device(x)
        with self.device:
            xp = self.device.xp
            self.r = b - self.A(self.x)

            if self.P is None:
                z = self.r
            else:
                z = self.P(self.r)

            if max_iter > 1:
                self.p = z.copy()
            else:
                self.p = z

            self.not_positive_definite = False
            self.rzold = xp.real(xp.vdot(self.r, z))
            self.resid = util.asscalar(self.rzold)**0.5

        super().__init__(max_iter)
Exemple #4
0
    def objective(self):
        with self.y_device:
            r = self.A(self.x) - self.y

            obj = 1 / 2 * util.norm2(r)
            if self.lamda > 0:
                if self.R is None:
                    obj += self.lamda / 2 * util.norm2(self.x)
                else:
                    obj += self.lamda / 2 * util.norm2(self.R(self.x))

            if self.mu != 0:
                obj += self.mu / 2 * util.norm2(self.x - self.z)

            if self.proxg is not None:
                if self.g is None:
                    raise ValueError(
                        'Cannot compute objective when proxg is specified,'
                        'but g is not.')

                if self.G is None:
                    obj += self.g(self.x)
                else:
                    obj += self.g(self.G(self.x))

            obj = util.asscalar(obj)
            return obj
Exemple #5
0
    def _update(self):
        backend.copyto(self.u_old, self.u)
        backend.copyto(self.x_old, self.x)

        # Update dual.
        delta_u = self.A(self.x_ext)
        util.axpy(self.u, self.sigma, delta_u)
        backend.copyto(self.u, self.proxfc(self.sigma, self.u))

        # Update primal.
        with self.x_device:
            delta_x = self.AH(self.u)
            if self.gradh is not None:
                delta_x += self.gradh(self.x)

            util.axpy(self.x, -self.tau, delta_x)
            backend.copyto(self.x, self.proxg(self.tau, self.x))

        # Update step-size if neccessary.
        if self.gamma_primal > 0 and self.gamma_dual == 0:
            with self.x_device:
                xp = self.x_device.xp
                theta = 1 / (
                    1 + 2 * self.gamma_primal * xp.amin(xp.abs(self.tau)))**0.5
                self.tau *= theta

            with self.u_device:
                self.sigma /= theta
        elif self.gamma_primal == 0 and self.gamma_dual > 0:
            with self.u_device:
                xp = self.u_device.xp
                theta = 1 / (
                    1 + 2 * self.gamma_dual * xp.amin(xp.abs(self.sigma)))**0.5
                self.sigma *= theta

            with self.x_device:
                self.tau /= theta
        else:
            theta = self.theta

        # Extrapolate primal.
        with self.x_device:
            xp = self.x_device.xp
            x_diff = self.x - self.x_old
            backend.copyto(self.x_ext, self.x + theta * x_diff)
            x_diff_norm = xp.linalg.norm(x_diff / self.tau**0.5)

        with self.u_device:
            xp = self.u_device.xp
            u_diff = self.u - self.u_old
            u_diff_norm = xp.linalg.norm(u_diff / self.sigma**0.5)

        self.resid = util.asscalar(x_diff_norm**2 + u_diff_norm**2)
Exemple #6
0
    def _update(self):
        xp = self.device.xp
        with self.device:
            if self.accelerate:
                backend.copyto(self.x, self.z)

            # Perform update
            gradf_x = self.gradf(self.x)
            alpha = self.alpha
            x_new = self.x - alpha * gradf_x
            if self.proxg is not None:
                x_new = self.proxg(alpha, x_new)

            delta_x = x_new - self.x
            # Backtracking line search
            if self.beta < 1:
                fx = self.f(self.x)
                while self.f(x_new) > fx + util.asscalar(
                        xp.real(xp.vdot(delta_x, gradf_x))) + \
                        1 / (2 * alpha) * util.asscalar(
                            xp.linalg.norm(delta_x))**2:
                    alpha *= self.beta

                    x_new = self.x - alpha * gradf_x
                    if self.proxg is not None:
                        x_new = self.proxg(alpha, x_new)

                    delta_x = x_new - self.x

            backend.copyto(self.x, x_new)
            if self.accelerate:
                t_old = self.t
                self.t = (1 + (1 + 4 * t_old**2)**0.5) / 2
                backend.copyto(self.z,
                               x_new + ((t_old - 1) / self.t) * delta_x)

            self.resid = util.asscalar(xp.linalg.norm(delta_x / alpha))
Exemple #7
0
    def _update(self):
        with self.device:
            xp = self.device.xp
            Ap = self.A(self.p)
            pAp = util.asscalar(xp.real(xp.vdot(self.p, Ap)))
            if pAp <= 0:
                self.not_positive_definite = True
                return

            self.alpha = self.rzold / pAp
            util.axpy(self.x, self.alpha, self.p)
            if self.iter < self.max_iter - 1:
                util.axpy(self.r, -self.alpha, Ap)
                if self.P is not None:
                    z = self.P(self.r)
                else:
                    z = self.r

                rznew = xp.real(xp.vdot(self.r, z))
                beta = rznew / self.rzold
                util.xpay(self.p, beta, z)
                self.rzold = rznew

            self.resid = util.asscalar(self.rzold)**0.5
Exemple #8
0
    def _update(self):
        device = backend.get_device(self.x)
        xp = device.xp
        with device:
            gradf_x = self.gradf(self.x)
            p = -self.inv_hessf(self.x)(gradf_x)
            self.lamda2 = util.asscalar(-xp.real(xp.vdot(p, gradf_x)))

            if self.lamda2 < 0:
                raise ValueError('Hessian is not positive semi-definite. '
                                 'inv_hessf might not be defined correctly.')

            x_new = self.x + p
            if self.beta < 1:
                fx = self.f(self.x)
                alpha = 1
                while self.f(x_new) > fx - alpha / 2 * self.lamda2:
                    alpha *= self.beta
                    x_new = self.x + alpha * p

            backend.copyto(self.x, x_new)
            self.residual = self.lamda2**0.5