MCPcopy Create free account
hub / github.com/cvxpy/cvxpy / grad

Method grad

cvxpy/transforms/partial_optimize.py:226–277  ·  view source on GitHub ↗

Gives the (sub/super)gradient of the expression w.r.t. each variable. Matrix expressions are vectorized, so the gradient is a matrix. None indicates variable values unknown or outside domain. Returns: A map of variable to SciPy CSC sparse matrix or None.

(self)

Source from the content-addressed store, hash-verified

224
225 @property
226 def grad(self):
227 """Gives the (sub/super)gradient of the expression w.r.t. each variable.
228
229 Matrix expressions are vectorized, so the gradient is a matrix.
230 None indicates variable values unknown or outside domain.
231
232 Returns:
233 A map of variable to SciPy CSC sparse matrix or None.
234 """
235 # Subgrad of g(y) = min f_0(x,y)
236 # s.t. f_i(x,y) <= 0, i = 1,..,p
237 # h_i(x,y) == 0, i = 1,...,q
238 # Given by Df_0(x^*,y) + \sum_i Df_i(x^*,y) \lambda^*_i
239 # + \sum_i Dh_i(x^*,y) \nu^*_i
240 # where x^*, \lambda^*_i, \nu^*_i are optimal primal/dual variables.
241 # Add PSD constraints in same way.
242
243 # Short circuit for constant.
244 if self.is_constant():
245 return u.grad.constant_grad(self)
246
247 old_vals = {var.id: var.value for var in self.variables()}
248 fix_vars = []
249 for var in self.dont_opt_vars:
250 if var.value is None:
251 return u.grad.error_grad(self)
252 else:
253 fix_vars += [var == var.value]
254 prob = Problem(self.args[0].objective,
255 fix_vars + self.args[0].constraints)
256 prob.solve(solver=self.solver, **self._solve_kwargs)
257 # Compute gradient.
258 if prob.status in s.SOLUTION_PRESENT:
259 sign = self.is_convex() - self.is_concave()
260 # Form Lagrangian.
261 lagr = self.args[0].objective.args[0]
262 for constr in self.args[0].constraints:
263 # TODO: better way to get constraint expressions.
264 lagr_multiplier = self.cast_to_const(sign * constr.dual_value)
265 prod = lagr_multiplier.T @ constr.expr
266 if prod.is_scalar():
267 lagr += sum(prod)
268 else:
269 lagr += trace(prod)
270 grad_map = lagr.grad
271 result = {var: grad_map[var] for var in self.dont_opt_vars}
272 else: # Unbounded, infeasible, or solver error.
273 result = u.grad.error_grad(self)
274 # Restore the original values to the variables.
275 for var in self.variables():
276 var.value = old_vals[var.id]
277 return result
278
279 @property
280 def domain(self):

Callers

nothing calls this directly

Calls 10

is_constantMethod · 0.95
variablesMethod · 0.95
solveMethod · 0.95
is_convexMethod · 0.95
is_concaveMethod · 0.95
ProblemClass · 0.90
sumFunction · 0.90
traceFunction · 0.90
cast_to_constMethod · 0.80
is_scalarMethod · 0.80

Tested by

no test coverage detected