Solve Nonlinear Problem with Integer and Nonlinear Constraints

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.

Objective and Constraint Functions

The objective function is

f(x)=log(1+3(x2-(x13-x1))2+(x1-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.

x145sinh(x2/5),x225tanh(x1/5)+1.

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.

Scale Integer Constraints to Lie on Fine Grid

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 -2xi3 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

Solve Scaled Problem

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: 58.3316
          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 to Solution Without Integer Constraints

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.3991    0.3746

fval2 = 0.8153
eflag2 = 0
outpt2 = struct with fields:
        elapsedtime: 47.8900
          funccount: 200
    constrviolation: -5.2624e-06
               ineq: [-5.2624e-06 -1.4374]
           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

Helper Function

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

See Also

Related Topics