Next: Method finalize_solution Up: Coding the Problem Representation Previous: Method eval_jac_g   Contents

#### Method eval_h

with prototype
virtual bool eval_h(Index n, const Number* x, bool new_x,
Number obj_factor, Index m, const Number* lambda,
bool new_lambda, Index nele_hess, Index* iRow,
Index* jCol, Number* values)

Return either the sparsity structure of the Hessian of the Lagrangian, or the values of the Hessian of the Lagrangian (9) for the given values for , , and .
• n: (in), the number of variables in the problem (dimension of ).
• x: (in), the values for the primal variables, , at which the Hessian is to be evaluated.
• new_x: (in), false if any evaluation method was previously called with the same values in x, true otherwise.
• obj_factor: (in), factor in front of the objective term in the Hessian, .
• m: (in), the number of constraints in the problem (dimension of ).
• lambda: (in), the values for the constraint multipliers, , at which the Hessian is to be evaluated.
• new_lambda: (in), false if any evaluation method was previously called with the same values in lambda, true otherwise.
• nele_hess: (in), the number of nonzero elements in the Hessian (dimension of iRow, jCol, and values).
• iRow: (out), the row indices of entries in the Hessian.
• jCol: (out), the column indices of entries in the Hessian.
• values: (out), the values of the entries in the Hessian.

The Hessian matrix that IPOPT uses is defined in Eq. 9. See Appendix A for a discussion of the sparse symmetric matrix format used in this method.

If the iRow and jCol arguments are not NULL, then IPOPT wants you to fill in the sparsity structure of the Hessian (the row and column indices for the lower or upper triangular part only). In this case, the x, lambda, and values arrays will be NULL.

If the x, lambda, and values arrays are not NULL, then IPOPT wants you to fill in the values of the Hessian as calculated using x and lambda (using the same order as you used when specifying the sparsity structure). In this case, the iRow and jCol arguments will be NULL.

The boolean variables new_x and new_lambda will both be false if the last call to any of the evaluation methods ( eval_*) used the same values. This can be helpful when users have efficient implementations that calculate multiple outputs at once. IPOPT internally caches results from the TNLP and generally, this flag can be ignored.

The variables n, m, and nele_hess are passed in for your convenience. These arguments will have the same values you specified in get_nlp_info.

In our example, the Hessian is dense, but we still specify it using the sparse matrix format. Because the Hessian is symmetric, we only need to specify the lower left corner.

bool HS071_NLP::eval_h(Index n, const Number* x, bool new_x,
Number obj_factor, Index m, const Number* lambda,
bool new_lambda, Index nele_hess, Index* iRow,
Index* jCol, Number* values)
{
if (values == NULL) {
// return the structure. This is a symmetric matrix, fill the lower left
// triangle only.

// the Hessian for this problem is actually dense
Index idx=0;
for (Index row = 0; row < 4; row++) {
for (Index col = 0; col <= row; col++) {
iRow[idx] = row;
jCol[idx] = col;
idx++;
}
}

assert(idx == nele_hess);
}
else {
// return the values. This is a symmetric matrix, fill the lower left
// triangle only

// fill the objective portion
values[0] = obj_factor * (2*x[3]); // 0,0

values[1] = obj_factor * (x[3]);   // 1,0
values[2] = 0;                     // 1,1

values[3] = obj_factor * (x[3]);   // 2,0
values[4] = 0;                     // 2,1
values[5] = 0;                     // 2,2

values[6] = obj_factor * (2*x[0] + x[1] + x[2]); // 3,0
values[7] = obj_factor * (x[0]);                 // 3,1
values[8] = obj_factor * (x[0]);                 // 3,2
values[9] = 0;                                   // 3,3

// add the portion for the first constraint
values[1] += lambda[0] * (x[2] * x[3]); // 1,0

values[3] += lambda[0] * (x[1] * x[3]); // 2,0
values[4] += lambda[0] * (x[0] * x[3]); // 2,1

values[6] += lambda[0] * (x[1] * x[2]); // 3,0
values[7] += lambda[0] * (x[0] * x[2]); // 3,1
values[8] += lambda[0] * (x[0] * x[1]); // 3,2

// add the portion for the second constraint
values[0] += lambda[1] * 2; // 0,0

values[2] += lambda[1] * 2; // 1,1

values[5] += lambda[1] * 2; // 2,2

values[9] += lambda[1] * 2; // 3,3
}

return true;
}


Next: Method finalize_solution Up: Coding the Problem Representation Previous: Method eval_jac_g   Contents
Andreas Waechter 2008-08-25