Ordinarily, minimization routines use numerical gradients calculated by finite-difference approximation. This procedure systematically perturbs each of the variables in order to calculate function and constraint partial derivatives. Alternatively, you can provide a function to compute partial derivatives analytically. Typically, the problem is solved more accurately and efficiently if such a function is provided.

Consider how to solve

$$\underset{x}{\mathrm{min}}f(x)={e}^{{x}_{1}}\left(4{x}_{1}^{2}+2{x}_{2}^{2}+4{x}_{1}{x}_{2}+2{x}_{2}+1\right).$$

subject to the constraints

*x*_{1}*x*_{2} – *x*_{1} – *x*_{2} ≤
–1.5,*x*_{1}*x*_{2} ≥
–10.

To solve the problem using analytically determined gradients, do the following.

function [f,gradf] = objfungrad(x) f = exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1); % Gradient of the objective function: if nargout > 1 gradf = [ f + exp(x(1)) * (8*x(1) + 4*x(2)), exp(x(1))*(4*x(1)+4*x(2)+2)]; end

function [c,ceq,DC,DCeq] = confungrad(x) c(1) = 1.5 + x(1) * x(2) - x(1) - x(2); % Inequality constraints c(2) = -x(1) * x(2)-10; % No nonlinear equality constraints ceq=[]; % Gradient of the constraints: if nargout > 2 DC= [x(2)-1, -x(2); x(1)-1, -x(1)]; DCeq = []; end

`gradf`

contains the partial derivatives of
the objective function, `f`

, returned by `objfungrad(x)`

,
with respect to each of the elements in `x`

:

$$\nabla f=\left[\begin{array}{c}{e}^{{x}_{1}}\left(4{x}_{1}^{2}+2{x}_{2}^{2}+4{x}_{1}{x}_{2}+2{x}_{2}+1\right)+{e}^{{x}_{1}}\left(8{x}_{1}+4{x}_{2}\right)\\ {e}^{{x}_{1}}\left(4{x}_{1}+4{x}_{2}+2\right)\end{array}\right].$$ | (6-58) |

The columns of `DC`

contain the partial derivatives
for each respective constraint (i.e., the `i`

th column
of `DC`

is the partial derivative of the `i`

th
constraint with respect to `x`

). So in the above
example, `DC`

is

$$\left[\begin{array}{cc}\frac{\partial {c}_{1}}{\partial {x}_{1}}& \frac{\partial {c}_{2}}{\partial {x}_{1}}\\ \frac{\partial {c}_{1}}{\partial {x}_{2}}& \frac{\partial {c}_{2}}{\partial {x}_{2}}\end{array}\right]=\left[\begin{array}{cc}{x}_{2}-1& -{x}_{2}\\ {x}_{1}-1& -{x}_{1}\end{array}\right].$$ | (6-59) |

Since you are providing the gradient of the objective in `objfungrad.m`

and
the gradient of the constraints in `confungrad.m`

,
you *must* tell `fmincon`

that
these files contain this additional information. Use `optimoptions`

to turn the options `SpecifyObjectiveGradient`

and `SpecifyConstraintGradient`

to `true`

in
the example's existing `options`

:

options = optimoptions(options,'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true);

If you do not set these options to `'on'`

, `fmincon`

does not use the analytic gradients.

The arguments `lb`

and `ub`

place
lower and upper bounds on the independent variables in `x`

.
In this example, there are no bound constraints, so set both to `[]`

.

x0 = [-1,1]; % Starting guess options = optimoptions(@fmincon,'Algorithm','sqp'); options = optimoptions(options,'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true); lb = [ ]; ub = [ ]; % No upper or lower bounds [x,fval] = fmincon(@objfungrad,x0,[],[],[],[],lb,ub,... @confungrad,options);

The results:

x,fval x = -9.5474 1.0474 fval = 0.0236 [c,ceq] = confungrad(x) % Check the constraint values at x c = 1.0e-13 * -0.1066 0.1066 ceq = []

Was this topic helpful?