@@ -213,7 +213,6 @@ def __init__(self, problem, inital_point):
213213
214214 def objective (self , x ):
215215 """Returns the scalar value of the objective given x."""
216- # Set the variable value
217216 offset = 0
218217 for var in self .main_var :
219218 size = var .size
@@ -227,7 +226,6 @@ def gradient(self, x):
227226 #import pdb
228227 #pdb.set_trace()
229228 """Returns the gradient of the objective with respect to x."""
230- # compute the gradient using _grad
231229 offset = 0
232230 for var in self .main_var :
233231 size = var .size
@@ -248,15 +246,13 @@ def gradient(self, x):
248246
249247 def constraints (self , x ):
250248 """Returns the constraint values."""
251- # Set the variable value
252249 offset = 0
253250 #import pdb
254251 #pdb.set_trace()
255252 for var in self .main_var :
256253 size = var .size
257254 var .value = x [offset :offset + size ].reshape (var .shape , order = 'F' )
258255 offset += size
259-
260256 # Evaluate all constraints
261257 constraint_values = []
262258 for constraint in self .problem .constraints :
@@ -265,15 +261,12 @@ def constraints(self, x):
265261
266262 def jacobian (self , x ):
267263 """Returns only the non-zero values of the Jacobian."""
268- #import pdb
269- #pdb.set_trace()
270264 # Set variable values
271265 offset = 0
272266 for var in self .main_var :
273267 size = var .size
274268 var .value = x [offset :offset + size ].reshape (var .shape , order = 'F' )
275269 offset += size
276-
277270 values = []
278271 for constraint in self .problem .constraints :
279272 # get the jacobian of the constraint
@@ -329,9 +322,44 @@ def jacobianstructure(self):
329322 col_offset += var .size
330323 row_offset += constraint .size
331324 self .jacobian_idxs [constraint ] = constraint_jac
332-
333325 return (np .array (rows ), np .array (cols ))
334326
327+ def hessian (self , x , duals , obj_factor ):
328+ offset = 0
329+ for var in self .main_var :
330+ size = var .size
331+ var .value = x [offset :offset + size ].reshape (var .shape , order = 'F' )
332+ offset += size
333+ hess = np .zeros ((x .size , x .size ), dtype = np .float64 )
334+ # hess_dict = self.problem.objective.expr.hess(obj_factor)
335+ # if we specify the problem in graph form (i.e. t=obj),
336+ # the objective hessian will always be zero.
337+ # To compute the hessian of the constraints, we need to gather the
338+ # second derivatives from each constraint.
339+ # This is done by looping through each constraint and each
340+ # pair of variables and summing up the hessian contributions.
341+ constr_offset = 0
342+ for constraint in self .problem .constraints :
343+ constr_hess = constraint .expr .hess ()
344+ # we have to make sure that the dual variables correspond
345+ # to the constraints in the same order
346+ constr_dual = duals [constr_offset :constr_offset + constraint .size ]
347+ row_offset = 0
348+ for var1 in self .main_var :
349+ col_offset = 0
350+ for var2 in self .main_var :
351+ hess [var1 .index * row_offset , var2 .index * col_offset ] += (
352+ constr_dual * constr_hess .get ((var1 , var2 ), 0 ).toarray ()
353+ )
354+ col_offset += var2 .size
355+ row_offset += var1 .size
356+ constr_offset += constraint .size
357+ return hess
358+
359+ def hessianstructure (self ):
360+ pass
361+
362+
335363 class Bounds ():
336364 def __init__ (self , problem ):
337365 self .problem = problem
0 commit comments