virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow,
Index *jCol, Number* values)
Return either the sparsity structure of the Jacobian of the
constraints, or the values for the Jacobian of the constraints at the
point
The Jacobian is the matrix of derivatives where the derivative of
constraint
with respect to variable
is placed in
row
and column
. See Appendix A for a
discussion of the sparse 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 Jacobian (the row and column indices only). At this time, the x argument and the values argument will be NULL.
If the x argument and the values argument are not NULL, then IPOPT wants you to fill in the values of the Jacobian as calculated from the array x (using the same order as you used when specifying the sparsity structure). At this time, the iRow and jCol arguments will be NULL;
The boolean variable new_x will 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_jac are passed in for your convenience. These arguments will have the same values you specified in get_nlp_info.
In our example, the Jacobian is actually dense, but we still specify it using the sparse format.
bool HS071_NLP::eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow, Index *jCol,
Number* values)
{
if (values == NULL) {
// return the structure of the Jacobian
// this particular Jacobian is dense
iRow[0] = 0; jCol[0] = 0;
iRow[1] = 0; jCol[1] = 1;
iRow[2] = 0; jCol[2] = 2;
iRow[3] = 0; jCol[3] = 3;
iRow[4] = 1; jCol[4] = 0;
iRow[5] = 1; jCol[5] = 1;
iRow[6] = 1; jCol[6] = 2;
iRow[7] = 1; jCol[7] = 3;
}
else {
// return the values of the Jacobian of the constraints
values[0] = x[1]*x[2]*x[3]; // 0,0
values[1] = x[0]*x[2]*x[3]; // 0,1
values[2] = x[0]*x[1]*x[3]; // 0,2
values[3] = x[0]*x[1]*x[2]; // 0,3
values[4] = 2*x[0]; // 1,0
values[5] = 2*x[1]; // 1,1
values[6] = 2*x[2]; // 1,2
values[7] = 2*x[3]; // 1,3
}
return true;
}