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))
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)
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)
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
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)
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))
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
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