def armijo_backtracking(self, func, alpha, maxiter=20): """ Returns step and next point, minimizing given functional Parameters ---------- func : function function to minimize x : ManifoldElement initial point alpha : float estimated line search parameter direction : TangentVector direction to move from initial point conj_direction : TangentVector conjugated direction Returns ------- x_new : next point (x + step * direction) step : float optimal step """ scale = -0.0001 * alpha for i in range(maxiter): x_new = svd_retraction(self.x + (0.5 ** i * alpha) * self.conj.release(), self.x.r) bound = (0.5 ** i * scale) * self.grad.release().scalar_product(self.conj.release()) if self.cost_raw(self.x) - self.cost_raw(x_new) >= bound: return x_new, 0.5 ** i * scale return x_new, 0.5 ** maxiter * scale
def gd_step(self): alpha = minimize_scalar(lambda x: self.cost_func(x), bounds=(0.0, 10.0), method="bounded")["x"] if alpha is None: alpha = 1.0 print(alpha) self.x = svd_retraction(self.x + alpha * self.grad.release(), self.x.r) # self.armijo_backtracking(lambda x: self.cost_raw(x), alpha)[0] return None
def cost_func(self, param): retracted = svd_retraction(self.x + param * self.grad.release(), self.x.r) return self.cost_raw(retracted)