Main Content

The `surrogateopt`

solver accepts both integer constraints and nonlinear constraints. Compare the solution of a nonlinear problem both with and without integer constraints. The integer constraints cause the solution to lie on a reasonably fine grid.

The objective function is

$$f(x)=\mathrm{log}(1+3{({x}_{2}-({x}_{1}^{3}-{x}_{1}))}^{2}+({x}_{1}-4/3{)}^{2}).$$

This objective function is nonnegative, and takes its minimum value of 0 at the point $$x=[4/3,(4/3{)}^{3}-4/3]$$ = [1.3333, 1.0370].

The problem has two nonlinear constraint functions.

$$\begin{array}{l}{x}_{1}^{4}\le 5\mathrm{sinh}({x}_{2}/5),\\ {x}_{2}^{2}\le 5\mathrm{tanh}({x}_{1}/5)+1.\end{array}$$

Plot the feasible region for the nonlinear constraints.

[X,Y] = meshgrid(-2:.01:3); Z = (5*sinh(Y./5) >= X.^4); % Z=1 where the first constraint is satisfied, Z=0 otherwise Z = Z+ 2*(5*tanh(X./5) >= Y.^2 - 1); % Z=2 where the second constraint is satisfied % Z=3 where both constraints are satisfied surf(X,Y,Z,'LineStyle','none'); fig = gcf; fig.Color = 'w'; % white background view(0,90) xlabel('x_1') ylabel('x_2')

The yellow region shows where both constraints are satisfied.

`surrogateopt`

requires that the objective and constraint functions are part of the same function, one that returns a structure. The objective function is in the `Fval`

field of the structure, and the constraints are in the `Ineq`

field. These fields are the output of the `objconstr`

function at the end of this example.

Set the problem to have integer constraints in both variables, `x(1)`

and `x(2)`

.

intcon = [1 2];

Scale the problem so that the variables are scaled by `s = 1/10`

, where `s`

multiplies the variables.

s = 0.1; f = @(x)objconstr(x,s);

For this scaling to be effective, you need to scale the bounds by $$1/s$$. Set the unscaled bounds to $$-2\le {x}_{i}\le 3$$ and scale each by $$1/s$$.

lb = [-2,-2]/s; ub = [3,3]/s;

By using the scaling `s`

, the problem effectively has spacing of `s`

in each component `x(1)`

and `x(2)`

. Plot the integer points as a grid with spacing `s`

.

hold on grid on ax = gca; sp = -2:s:3; ax.XTick = sp; ax.YTick = sp; ax.Layer = 'top'; ax.GridAlpha = 1/2; ax.XTickLabel = ''; ax.YTickLabel = ''; xlabel('x_1') ylabel('x_2') hold off

Set options to use tighter constraints than the default, and to use the `surrogateoptplot`

plot function.

opts = optimoptions('surrogateopt','PlotFcn',"surrogateoptplot","ConstraintTolerance",1e-6);

Call `surrogateopt`

to solve the problem.

rng default % For reproducibility [sol,fval,eflag,outpt] = surrogateopt(f,lb,ub,intcon,opts)

surrogateopt stopped because it exceeded the function evaluation limit set by 'options.MaxFunctionEvaluations'.

`sol = `*1×2*
5 1

fval = 0.8634

eflag = 0

`outpt = `*struct with fields:*
elapsedtime: 59.7165
funccount: 200
constrviolation: -0.0375
ineq: [-0.0375 -1.4883]
rngstate: [1x1 struct]
message: 'surrogateopt stopped because it exceeded the function evaluation limit set by ...'

Plot the solution as a red circle on the figure. Notice that the objective function value is approximately 0.86.

figure(fig); hold on plot3(sol(1)*s,sol(2)*s,5,'ro') hold off

Compare the solution with integer constraints to the solution without integer constraints.

[sol2,fval2,eflag2,outpt2] = surrogateopt(f,lb,ub,[],opts)

surrogateopt stopped because it exceeded the function evaluation limit set by 'options.MaxFunctionEvaluations'.

`sol2 = `*1×2*
4.3757 0.3667

fval2 = 0.8153

eflag2 = 0

`outpt2 = `*struct with fields:*
elapsedtime: 32.5628
funccount: 200
constrviolation: -8.6916e-06
ineq: [-8.6916e-06 -1.4351]
rngstate: [1x1 struct]
message: 'surrogateopt stopped because it exceeded the function evaluation limit set by ...'

Here, the objective function value is approximately 0.815. The integer constraints increase the objective function value by less than 10%. Plot the new solution along with the previous integer solution. Zoom in to see the solution points more clearly.

figure(fig) hold on plot3(sol2(1)*s,sol2(2)*s,5,'k*','MarkerSize',12) xlim([0 1]) ylim([-1/2 1/2]) hold off

This code creates the `objconstr`

helper function. This function scales the variable `x`

by the factor `s`

, returns the objective function value in the `Fval`

field of the `F`

structure, and returns the nonlinear constraints in the `Ineq`

field of the `F`

structure.

function F = objconstr(x,s) x = x*s; fun = log(1 + 3*(x(2) - (x(1)^3 - x(1)))^2 + (x(1) - 4/3)^2); c1 = x(1)^4 - 5*sinh(x(2)/5); c2 = x(2)^2 - 5*tanh(x(1)/5) - 1; c = [c1 c2]; F.Fval = fun; F.Ineq = c; end